Merge branch 'master' into bbuf
This commit is contained in:
commit
be75ffd028
38
BUILD
38
BUILD
|
|
@ -161,7 +161,6 @@ cc_library(
|
|||
"src/core/channel/context.h",
|
||||
"src/core/channel/http_client_filter.h",
|
||||
"src/core/channel/http_server_filter.h",
|
||||
"src/core/channel/noop_filter.h",
|
||||
"src/core/channel/subchannel_call_holder.h",
|
||||
"src/core/client_config/client_config.h",
|
||||
"src/core/client_config/connector.h",
|
||||
|
|
@ -178,9 +177,8 @@ cc_library(
|
|||
"src/core/client_config/resolvers/sockaddr_resolver.h",
|
||||
"src/core/client_config/subchannel.h",
|
||||
"src/core/client_config/subchannel_factory.h",
|
||||
"src/core/client_config/subchannel_factory_decorators/add_channel_arg.h",
|
||||
"src/core/client_config/subchannel_factory_decorators/merge_channel_args.h",
|
||||
"src/core/client_config/uri_parser.h",
|
||||
"src/core/compression/algorithm_metadata.h",
|
||||
"src/core/compression/message_compress.h",
|
||||
"src/core/debug/trace.h",
|
||||
"src/core/httpcli/format_request.h",
|
||||
|
|
@ -263,6 +261,7 @@ cc_library(
|
|||
"src/core/transport/connectivity_state.h",
|
||||
"src/core/transport/metadata.h",
|
||||
"src/core/transport/metadata_batch.h",
|
||||
"src/core/transport/static_metadata.h",
|
||||
"src/core/transport/transport.h",
|
||||
"src/core/transport/transport_impl.h",
|
||||
"src/core/census/aggregation.h",
|
||||
|
|
@ -299,7 +298,6 @@ cc_library(
|
|||
"src/core/channel/connected_channel.c",
|
||||
"src/core/channel/http_client_filter.c",
|
||||
"src/core/channel/http_server_filter.c",
|
||||
"src/core/channel/noop_filter.c",
|
||||
"src/core/channel/subchannel_call_holder.c",
|
||||
"src/core/client_config/client_config.c",
|
||||
"src/core/client_config/connector.c",
|
||||
|
|
@ -317,8 +315,6 @@ cc_library(
|
|||
"src/core/client_config/resolvers/sockaddr_resolver.c",
|
||||
"src/core/client_config/subchannel.c",
|
||||
"src/core/client_config/subchannel_factory.c",
|
||||
"src/core/client_config/subchannel_factory_decorators/add_channel_arg.c",
|
||||
"src/core/client_config/subchannel_factory_decorators/merge_channel_args.c",
|
||||
"src/core/client_config/uri_parser.c",
|
||||
"src/core/compression/algorithm.c",
|
||||
"src/core/compression/message_compress.c",
|
||||
|
|
@ -379,6 +375,7 @@ cc_library(
|
|||
"src/core/surface/channel.c",
|
||||
"src/core/surface/channel_connectivity.c",
|
||||
"src/core/surface/channel_create.c",
|
||||
"src/core/surface/channel_ping.c",
|
||||
"src/core/surface/completion_queue.c",
|
||||
"src/core/surface/event_string.c",
|
||||
"src/core/surface/init.c",
|
||||
|
|
@ -413,6 +410,7 @@ cc_library(
|
|||
"src/core/transport/connectivity_state.c",
|
||||
"src/core/transport/metadata.c",
|
||||
"src/core/transport/metadata_batch.c",
|
||||
"src/core/transport/static_metadata.c",
|
||||
"src/core/transport/transport.c",
|
||||
"src/core/transport/transport_op_string.c",
|
||||
"src/core/census/context.c",
|
||||
|
|
@ -454,7 +452,6 @@ cc_library(
|
|||
"src/core/channel/context.h",
|
||||
"src/core/channel/http_client_filter.h",
|
||||
"src/core/channel/http_server_filter.h",
|
||||
"src/core/channel/noop_filter.h",
|
||||
"src/core/channel/subchannel_call_holder.h",
|
||||
"src/core/client_config/client_config.h",
|
||||
"src/core/client_config/connector.h",
|
||||
|
|
@ -471,9 +468,8 @@ cc_library(
|
|||
"src/core/client_config/resolvers/sockaddr_resolver.h",
|
||||
"src/core/client_config/subchannel.h",
|
||||
"src/core/client_config/subchannel_factory.h",
|
||||
"src/core/client_config/subchannel_factory_decorators/add_channel_arg.h",
|
||||
"src/core/client_config/subchannel_factory_decorators/merge_channel_args.h",
|
||||
"src/core/client_config/uri_parser.h",
|
||||
"src/core/compression/algorithm_metadata.h",
|
||||
"src/core/compression/message_compress.h",
|
||||
"src/core/debug/trace.h",
|
||||
"src/core/httpcli/format_request.h",
|
||||
|
|
@ -556,6 +552,7 @@ cc_library(
|
|||
"src/core/transport/connectivity_state.h",
|
||||
"src/core/transport/metadata.h",
|
||||
"src/core/transport/metadata_batch.h",
|
||||
"src/core/transport/static_metadata.h",
|
||||
"src/core/transport/transport.h",
|
||||
"src/core/transport/transport_impl.h",
|
||||
"src/core/census/aggregation.h",
|
||||
|
|
@ -572,7 +569,6 @@ cc_library(
|
|||
"src/core/channel/connected_channel.c",
|
||||
"src/core/channel/http_client_filter.c",
|
||||
"src/core/channel/http_server_filter.c",
|
||||
"src/core/channel/noop_filter.c",
|
||||
"src/core/channel/subchannel_call_holder.c",
|
||||
"src/core/client_config/client_config.c",
|
||||
"src/core/client_config/connector.c",
|
||||
|
|
@ -590,8 +586,6 @@ cc_library(
|
|||
"src/core/client_config/resolvers/sockaddr_resolver.c",
|
||||
"src/core/client_config/subchannel.c",
|
||||
"src/core/client_config/subchannel_factory.c",
|
||||
"src/core/client_config/subchannel_factory_decorators/add_channel_arg.c",
|
||||
"src/core/client_config/subchannel_factory_decorators/merge_channel_args.c",
|
||||
"src/core/client_config/uri_parser.c",
|
||||
"src/core/compression/algorithm.c",
|
||||
"src/core/compression/message_compress.c",
|
||||
|
|
@ -652,6 +646,7 @@ cc_library(
|
|||
"src/core/surface/channel.c",
|
||||
"src/core/surface/channel_connectivity.c",
|
||||
"src/core/surface/channel_create.c",
|
||||
"src/core/surface/channel_ping.c",
|
||||
"src/core/surface/completion_queue.c",
|
||||
"src/core/surface/event_string.c",
|
||||
"src/core/surface/init.c",
|
||||
|
|
@ -686,6 +681,7 @@ cc_library(
|
|||
"src/core/transport/connectivity_state.c",
|
||||
"src/core/transport/metadata.c",
|
||||
"src/core/transport/metadata_batch.c",
|
||||
"src/core/transport/static_metadata.c",
|
||||
"src/core/transport/transport.c",
|
||||
"src/core/transport/transport_op_string.c",
|
||||
"src/core/census/context.c",
|
||||
|
|
@ -742,14 +738,13 @@ cc_library(
|
|||
"src/cpp/server/dynamic_thread_pool.h",
|
||||
"src/cpp/server/fixed_size_thread_pool.h",
|
||||
"src/cpp/server/thread_pool_interface.h",
|
||||
"src/cpp/client/secure_channel_arguments.cc",
|
||||
"src/cpp/client/secure_credentials.cc",
|
||||
"src/cpp/common/auth_property_iterator.cc",
|
||||
"src/cpp/common/secure_auth_context.cc",
|
||||
"src/cpp/common/secure_channel_arguments.cc",
|
||||
"src/cpp/common/secure_create_auth_context.cc",
|
||||
"src/cpp/server/secure_server_credentials.cc",
|
||||
"src/cpp/client/channel.cc",
|
||||
"src/cpp/client/channel_arguments.cc",
|
||||
"src/cpp/client/client_context.cc",
|
||||
"src/cpp/client/create_channel.cc",
|
||||
"src/cpp/client/create_channel_internal.cc",
|
||||
|
|
@ -757,6 +752,7 @@ cc_library(
|
|||
"src/cpp/client/generic_stub.cc",
|
||||
"src/cpp/client/insecure_credentials.cc",
|
||||
"src/cpp/common/call.cc",
|
||||
"src/cpp/common/channel_arguments.cc",
|
||||
"src/cpp/common/completion_queue.cc",
|
||||
"src/cpp/common/rpc_method.cc",
|
||||
"src/cpp/proto/proto_utils.cc",
|
||||
|
|
@ -790,6 +786,7 @@ cc_library(
|
|||
"include/grpc++/impl/rpc_method.h",
|
||||
"include/grpc++/impl/rpc_service_method.h",
|
||||
"include/grpc++/impl/serialization_traits.h",
|
||||
"include/grpc++/impl/server_builder_option.h",
|
||||
"include/grpc++/impl/service_type.h",
|
||||
"include/grpc++/impl/sync.h",
|
||||
"include/grpc++/impl/sync_cxx11.h",
|
||||
|
|
@ -841,7 +838,6 @@ cc_library(
|
|||
"src/cpp/server/thread_pool_interface.h",
|
||||
"src/cpp/common/insecure_create_auth_context.cc",
|
||||
"src/cpp/client/channel.cc",
|
||||
"src/cpp/client/channel_arguments.cc",
|
||||
"src/cpp/client/client_context.cc",
|
||||
"src/cpp/client/create_channel.cc",
|
||||
"src/cpp/client/create_channel_internal.cc",
|
||||
|
|
@ -849,6 +845,7 @@ cc_library(
|
|||
"src/cpp/client/generic_stub.cc",
|
||||
"src/cpp/client/insecure_credentials.cc",
|
||||
"src/cpp/common/call.cc",
|
||||
"src/cpp/common/channel_arguments.cc",
|
||||
"src/cpp/common/completion_queue.cc",
|
||||
"src/cpp/common/rpc_method.cc",
|
||||
"src/cpp/proto/proto_utils.cc",
|
||||
|
|
@ -882,6 +879,7 @@ cc_library(
|
|||
"include/grpc++/impl/rpc_method.h",
|
||||
"include/grpc++/impl/rpc_service_method.h",
|
||||
"include/grpc++/impl/serialization_traits.h",
|
||||
"include/grpc++/impl/server_builder_option.h",
|
||||
"include/grpc++/impl/service_type.h",
|
||||
"include/grpc++/impl/sync.h",
|
||||
"include/grpc++/impl/sync_cxx11.h",
|
||||
|
|
@ -1105,7 +1103,6 @@ objc_library(
|
|||
"src/core/channel/connected_channel.c",
|
||||
"src/core/channel/http_client_filter.c",
|
||||
"src/core/channel/http_server_filter.c",
|
||||
"src/core/channel/noop_filter.c",
|
||||
"src/core/channel/subchannel_call_holder.c",
|
||||
"src/core/client_config/client_config.c",
|
||||
"src/core/client_config/connector.c",
|
||||
|
|
@ -1123,8 +1120,6 @@ objc_library(
|
|||
"src/core/client_config/resolvers/sockaddr_resolver.c",
|
||||
"src/core/client_config/subchannel.c",
|
||||
"src/core/client_config/subchannel_factory.c",
|
||||
"src/core/client_config/subchannel_factory_decorators/add_channel_arg.c",
|
||||
"src/core/client_config/subchannel_factory_decorators/merge_channel_args.c",
|
||||
"src/core/client_config/uri_parser.c",
|
||||
"src/core/compression/algorithm.c",
|
||||
"src/core/compression/message_compress.c",
|
||||
|
|
@ -1185,6 +1180,7 @@ objc_library(
|
|||
"src/core/surface/channel.c",
|
||||
"src/core/surface/channel_connectivity.c",
|
||||
"src/core/surface/channel_create.c",
|
||||
"src/core/surface/channel_ping.c",
|
||||
"src/core/surface/completion_queue.c",
|
||||
"src/core/surface/event_string.c",
|
||||
"src/core/surface/init.c",
|
||||
|
|
@ -1219,6 +1215,7 @@ objc_library(
|
|||
"src/core/transport/connectivity_state.c",
|
||||
"src/core/transport/metadata.c",
|
||||
"src/core/transport/metadata_batch.c",
|
||||
"src/core/transport/static_metadata.c",
|
||||
"src/core/transport/transport.c",
|
||||
"src/core/transport/transport_op_string.c",
|
||||
"src/core/census/context.c",
|
||||
|
|
@ -1257,7 +1254,6 @@ objc_library(
|
|||
"src/core/channel/context.h",
|
||||
"src/core/channel/http_client_filter.h",
|
||||
"src/core/channel/http_server_filter.h",
|
||||
"src/core/channel/noop_filter.h",
|
||||
"src/core/channel/subchannel_call_holder.h",
|
||||
"src/core/client_config/client_config.h",
|
||||
"src/core/client_config/connector.h",
|
||||
|
|
@ -1274,9 +1270,8 @@ objc_library(
|
|||
"src/core/client_config/resolvers/sockaddr_resolver.h",
|
||||
"src/core/client_config/subchannel.h",
|
||||
"src/core/client_config/subchannel_factory.h",
|
||||
"src/core/client_config/subchannel_factory_decorators/add_channel_arg.h",
|
||||
"src/core/client_config/subchannel_factory_decorators/merge_channel_args.h",
|
||||
"src/core/client_config/uri_parser.h",
|
||||
"src/core/compression/algorithm_metadata.h",
|
||||
"src/core/compression/message_compress.h",
|
||||
"src/core/debug/trace.h",
|
||||
"src/core/httpcli/format_request.h",
|
||||
|
|
@ -1359,6 +1354,7 @@ objc_library(
|
|||
"src/core/transport/connectivity_state.h",
|
||||
"src/core/transport/metadata.h",
|
||||
"src/core/transport/metadata_batch.h",
|
||||
"src/core/transport/static_metadata.h",
|
||||
"src/core/transport/transport.h",
|
||||
"src/core/transport/transport_impl.h",
|
||||
"src/core/census/aggregation.h",
|
||||
|
|
|
|||
42
README.md
42
README.md
|
|
@ -13,34 +13,28 @@ You can find more detailed documentation and examples in the [doc](doc) and [exa
|
|||
|
||||
See grpc/INSTALL for installation instructions for various platforms.
|
||||
|
||||
#Repository Structure
|
||||
#Repository Structure & Status
|
||||
|
||||
This repository contains source code for gRPC libraries for multiple languages written on top
|
||||
of shared C core library [src/core] (src/core).
|
||||
|
||||
* C++ source code: [src/cpp] (src/cpp)
|
||||
* Ruby source code: [src/ruby] (src/ruby)
|
||||
* NodeJS source code: [src/node] (src/node)
|
||||
* Python source code: [src/python] (src/python)
|
||||
* PHP source code: [src/php] (src/php)
|
||||
* C# source code: [src/csharp] (src/csharp)
|
||||
* Objective-C source code: [src/objective-c] (src/objective-c)
|
||||
|
||||
Java source code is in [grpc-java] (http://github.com/grpc/grpc-java) repository.
|
||||
Go source code is in [grpc-go] (http://github.com/grpc/grpc-go) repository.
|
||||
|
||||
#Current Status of libraries
|
||||
This repository contains source code for gRPC libraries for multiple languages written on top of shared C core library [src/core] (src/core).
|
||||
|
||||
Libraries in different languages are in different state of development. We are seeking contributions for all of these libraries.
|
||||
|
||||
* shared C core library [src/core] (src/core) : Beta - the surface API is stable
|
||||
* C++ Library: [src/cpp] (src/cpp) : Beta - the surface API is stable
|
||||
* Ruby Library: [src/ruby] (src/ruby) : Beta - the surface API is stable
|
||||
* NodeJS Library: [src/node] (src/node) : Beta - the surface API is stable
|
||||
* Python Library: [src/python] (src/python) : Beta - the surface API is stable
|
||||
* C# Library: [src/csharp] (src/csharp) : Beta - the surface API is stable
|
||||
* Objective-C Library: [src/objective-c] (src/objective-c): Beta - the surface API is stable
|
||||
* PHP Library: [src/php] (src/php) : Beta - the surface API is stable
|
||||
| Language | Source | Status |
|
||||
|-------------------------|-------------------------------------|---------------------------------|
|
||||
| Shared C [core library] | [src/core] (src/core) | Beta - the surface API is stable |
|
||||
| C++ | [src/cpp] (src/cpp) | Beta - the surface API is stable |
|
||||
| Ruby | [src/ruby] (src/ruby) | Beta - the surface API is stable |
|
||||
| NodeJS | [src/node] (src/node) | Beta - the surface API is stable |
|
||||
| Python | [src/python] (src/python) | Beta - the surface API is stable |
|
||||
| PHP | [src/php] (src/php) | Beta - the surface API is stable |
|
||||
| C# | [src/csharp] (src/csharp) | Beta - the surface API is stable |
|
||||
| Objective-C | [src/objective-c] (src/objective-c) | Beta - the surface API is stable |
|
||||
|
||||
<small>
|
||||
Java source code is in [grpc-java] (http://github.com/grpc/grpc-java) repository.
|
||||
Go source code is in [grpc-go] (http://github.com/grpc/grpc-go) repository.
|
||||
</small>
|
||||
|
||||
|
||||
#Overview
|
||||
|
||||
|
|
|
|||
|
|
@ -183,7 +183,6 @@
|
|||
'src/core/channel/connected_channel.c',
|
||||
'src/core/channel/http_client_filter.c',
|
||||
'src/core/channel/http_server_filter.c',
|
||||
'src/core/channel/noop_filter.c',
|
||||
'src/core/channel/subchannel_call_holder.c',
|
||||
'src/core/client_config/client_config.c',
|
||||
'src/core/client_config/connector.c',
|
||||
|
|
@ -201,8 +200,6 @@
|
|||
'src/core/client_config/resolvers/sockaddr_resolver.c',
|
||||
'src/core/client_config/subchannel.c',
|
||||
'src/core/client_config/subchannel_factory.c',
|
||||
'src/core/client_config/subchannel_factory_decorators/add_channel_arg.c',
|
||||
'src/core/client_config/subchannel_factory_decorators/merge_channel_args.c',
|
||||
'src/core/client_config/uri_parser.c',
|
||||
'src/core/compression/algorithm.c',
|
||||
'src/core/compression/message_compress.c',
|
||||
|
|
@ -263,6 +260,7 @@
|
|||
'src/core/surface/channel.c',
|
||||
'src/core/surface/channel_connectivity.c',
|
||||
'src/core/surface/channel_create.c',
|
||||
'src/core/surface/channel_ping.c',
|
||||
'src/core/surface/completion_queue.c',
|
||||
'src/core/surface/event_string.c',
|
||||
'src/core/surface/init.c',
|
||||
|
|
@ -297,6 +295,7 @@
|
|||
'src/core/transport/connectivity_state.c',
|
||||
'src/core/transport/metadata.c',
|
||||
'src/core/transport/metadata_batch.c',
|
||||
'src/core/transport/static_metadata.c',
|
||||
'src/core/transport/transport.c',
|
||||
'src/core/transport/transport_op_string.c',
|
||||
'src/core/census/context.c',
|
||||
|
|
|
|||
201
build.yaml
201
build.yaml
|
|
@ -37,6 +37,7 @@ filegroups:
|
|||
- include/grpc++/impl/rpc_method.h
|
||||
- include/grpc++/impl/rpc_service_method.h
|
||||
- include/grpc++/impl/serialization_traits.h
|
||||
- include/grpc++/impl/server_builder_option.h
|
||||
- include/grpc++/impl/service_type.h
|
||||
- include/grpc++/impl/sync.h
|
||||
- include/grpc++/impl/sync_cxx11.h
|
||||
|
|
@ -72,7 +73,6 @@ filegroups:
|
|||
- src/cpp/server/thread_pool_interface.h
|
||||
src:
|
||||
- src/cpp/client/channel.cc
|
||||
- src/cpp/client/channel_arguments.cc
|
||||
- src/cpp/client/client_context.cc
|
||||
- src/cpp/client/create_channel.cc
|
||||
- src/cpp/client/create_channel_internal.cc
|
||||
|
|
@ -80,6 +80,7 @@ filegroups:
|
|||
- src/cpp/client/generic_stub.cc
|
||||
- src/cpp/client/insecure_credentials.cc
|
||||
- src/cpp/common/call.cc
|
||||
- src/cpp/common/channel_arguments.cc
|
||||
- src/cpp/common/completion_queue.cc
|
||||
- src/cpp/common/rpc_method.cc
|
||||
- src/cpp/proto/proto_utils.cc
|
||||
|
|
@ -115,7 +116,6 @@ filegroups:
|
|||
- src/core/channel/context.h
|
||||
- src/core/channel/http_client_filter.h
|
||||
- src/core/channel/http_server_filter.h
|
||||
- src/core/channel/noop_filter.h
|
||||
- src/core/channel/subchannel_call_holder.h
|
||||
- src/core/client_config/client_config.h
|
||||
- src/core/client_config/connector.h
|
||||
|
|
@ -132,9 +132,8 @@ filegroups:
|
|||
- src/core/client_config/resolvers/sockaddr_resolver.h
|
||||
- src/core/client_config/subchannel.h
|
||||
- src/core/client_config/subchannel_factory.h
|
||||
- src/core/client_config/subchannel_factory_decorators/add_channel_arg.h
|
||||
- src/core/client_config/subchannel_factory_decorators/merge_channel_args.h
|
||||
- src/core/client_config/uri_parser.h
|
||||
- src/core/compression/algorithm_metadata.h
|
||||
- src/core/compression/message_compress.h
|
||||
- src/core/debug/trace.h
|
||||
- src/core/httpcli/format_request.h
|
||||
|
|
@ -217,6 +216,7 @@ filegroups:
|
|||
- src/core/transport/connectivity_state.h
|
||||
- src/core/transport/metadata.h
|
||||
- src/core/transport/metadata_batch.h
|
||||
- src/core/transport/static_metadata.h
|
||||
- src/core/transport/transport.h
|
||||
- src/core/transport/transport_impl.h
|
||||
src:
|
||||
|
|
@ -230,7 +230,6 @@ filegroups:
|
|||
- src/core/channel/connected_channel.c
|
||||
- src/core/channel/http_client_filter.c
|
||||
- src/core/channel/http_server_filter.c
|
||||
- src/core/channel/noop_filter.c
|
||||
- src/core/channel/subchannel_call_holder.c
|
||||
- src/core/client_config/client_config.c
|
||||
- src/core/client_config/connector.c
|
||||
|
|
@ -248,8 +247,6 @@ filegroups:
|
|||
- src/core/client_config/resolvers/sockaddr_resolver.c
|
||||
- src/core/client_config/subchannel.c
|
||||
- src/core/client_config/subchannel_factory.c
|
||||
- src/core/client_config/subchannel_factory_decorators/add_channel_arg.c
|
||||
- src/core/client_config/subchannel_factory_decorators/merge_channel_args.c
|
||||
- src/core/client_config/uri_parser.c
|
||||
- src/core/compression/algorithm.c
|
||||
- src/core/compression/message_compress.c
|
||||
|
|
@ -310,6 +307,7 @@ filegroups:
|
|||
- src/core/surface/channel.c
|
||||
- src/core/surface/channel_connectivity.c
|
||||
- src/core/surface/channel_create.c
|
||||
- src/core/surface/channel_ping.c
|
||||
- src/core/surface/completion_queue.c
|
||||
- src/core/surface/event_string.c
|
||||
- src/core/surface/init.c
|
||||
|
|
@ -344,6 +342,7 @@ filegroups:
|
|||
- src/core/transport/connectivity_state.c
|
||||
- src/core/transport/metadata.c
|
||||
- src/core/transport/metadata_batch.c
|
||||
- src/core/transport/static_metadata.c
|
||||
- src/core/transport/transport.c
|
||||
- src/core/transport/transport_op_string.c
|
||||
- name: grpc_test_util_base
|
||||
|
|
@ -351,7 +350,6 @@ filegroups:
|
|||
- test/core/end2end/cq_verifier.h
|
||||
- test/core/end2end/fixtures/proxy.h
|
||||
- test/core/iomgr/endpoint_tests.h
|
||||
- test/core/security/oauth2_utils.h
|
||||
- test/core/util/grpc_profiler.h
|
||||
- test/core/util/parse_hexstring.h
|
||||
- test/core/util/port.h
|
||||
|
|
@ -360,7 +358,6 @@ filegroups:
|
|||
- test/core/end2end/cq_verifier.c
|
||||
- test/core/end2end/fixtures/proxy.c
|
||||
- test/core/iomgr/endpoint_tests.c
|
||||
- test/core/security/oauth2_utils.c
|
||||
- test/core/util/grpc_profiler.c
|
||||
- test/core/util/parse_hexstring.c
|
||||
- test/core/util/port_posix.c
|
||||
|
|
@ -523,10 +520,12 @@ libs:
|
|||
language: c
|
||||
headers:
|
||||
- test/core/end2end/data/ssl_test_data.h
|
||||
- test/core/security/oauth2_utils.h
|
||||
src:
|
||||
- test/core/end2end/data/server1_cert.c
|
||||
- test/core/end2end/data/server1_key.c
|
||||
- test/core/end2end/data/test_root_cert.c
|
||||
- test/core/security/oauth2_utils.c
|
||||
deps:
|
||||
- gpr
|
||||
- gpr_test_util
|
||||
|
|
@ -540,7 +539,7 @@ libs:
|
|||
deps:
|
||||
- gpr
|
||||
- gpr_test_util
|
||||
- grpc
|
||||
- grpc_unsecure
|
||||
filegroups:
|
||||
- grpc_test_util_base
|
||||
secure: false
|
||||
|
|
@ -609,10 +608,10 @@ libs:
|
|||
- src/cpp/common/secure_auth_context.h
|
||||
- src/cpp/server/secure_server_credentials.h
|
||||
src:
|
||||
- src/cpp/client/secure_channel_arguments.cc
|
||||
- src/cpp/client/secure_credentials.cc
|
||||
- src/cpp/common/auth_property_iterator.cc
|
||||
- src/cpp/common/secure_auth_context.cc
|
||||
- src/cpp/common/secure_channel_arguments.cc
|
||||
- src/cpp/common/secure_create_auth_context.cc
|
||||
- src/cpp/server/secure_server_credentials.cc
|
||||
deps:
|
||||
|
|
@ -811,6 +810,24 @@ libs:
|
|||
- winsock
|
||||
- global
|
||||
targets:
|
||||
- name: algorithm_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/compression/algorithm_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: alloc_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/support/alloc_test.c
|
||||
deps:
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: alpn_test
|
||||
build: test
|
||||
language: c
|
||||
|
|
@ -831,6 +848,16 @@ targets:
|
|||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: channel_create_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/surface/channel_create_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: chttp2_hpack_encoder_test
|
||||
build: test
|
||||
language: c
|
||||
|
|
@ -861,6 +888,16 @@ targets:
|
|||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: chttp2_varint_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/transport/chttp2/varint_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: compression_test
|
||||
build: test
|
||||
language: c
|
||||
|
|
@ -871,6 +908,16 @@ targets:
|
|||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: dns_resolver_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/client_config/resolvers/dns_resolver_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: dualstack_socket_test
|
||||
build: test
|
||||
language: c
|
||||
|
|
@ -1213,6 +1260,16 @@ targets:
|
|||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: grpc_invalid_channel_args_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/surface/invalid_channel_args_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: grpc_json_token_test
|
||||
build: test
|
||||
language: c
|
||||
|
|
@ -1321,6 +1378,38 @@ targets:
|
|||
- mac
|
||||
- linux
|
||||
- posix
|
||||
- name: httpscli_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/httpcli/httpscli_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
platforms:
|
||||
- linux
|
||||
- name: init_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/surface/init_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: invalid_call_argument_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/end2end/invalid_call_argument_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: json_rewrite
|
||||
build: test
|
||||
run: false
|
||||
|
|
@ -1340,6 +1429,16 @@ targets:
|
|||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: json_stream_error_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/json/json_stream_error_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: json_test
|
||||
build: test
|
||||
language: c
|
||||
|
|
@ -1394,16 +1493,6 @@ targets:
|
|||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: multi_init_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/surface/multi_init_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: multiple_server_queues_test
|
||||
build: test
|
||||
language: c
|
||||
|
|
@ -1442,6 +1531,16 @@ targets:
|
|||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: secure_channel_create_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/surface/secure_channel_create_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: secure_endpoint_test
|
||||
build: test
|
||||
language: c
|
||||
|
|
@ -1452,6 +1551,26 @@ targets:
|
|||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: server_chttp2_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/surface/server_chttp2_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: server_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/surface/server_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: set_initial_connect_string_test
|
||||
build: test
|
||||
language: c
|
||||
|
|
@ -1463,6 +1582,16 @@ targets:
|
|||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: sockaddr_resolver_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/client_config/resolvers/sockaddr_resolver_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: sockaddr_utils_test
|
||||
build: test
|
||||
language: c
|
||||
|
|
@ -1473,6 +1602,20 @@ targets:
|
|||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: socket_utils_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/iomgr/socket_utils_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
platforms:
|
||||
- mac
|
||||
- linux
|
||||
- posix
|
||||
- name: tcp_client_posix_test
|
||||
build: test
|
||||
language: c
|
||||
|
|
@ -1565,6 +1708,16 @@ targets:
|
|||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: transport_connectivity_state_test
|
||||
build: test
|
||||
language: c
|
||||
src:
|
||||
- test/core/transport/connectivity_state_test.c
|
||||
deps:
|
||||
- grpc_test_util
|
||||
- grpc
|
||||
- gpr_test_util
|
||||
- gpr
|
||||
- name: transport_metadata_test
|
||||
build: test
|
||||
language: c
|
||||
|
|
@ -1689,7 +1842,7 @@ targets:
|
|||
build: test
|
||||
language: c++
|
||||
src:
|
||||
- test/cpp/client/channel_arguments_test.cc
|
||||
- test/cpp/common/channel_arguments_test.cc
|
||||
deps:
|
||||
- grpc++
|
||||
- grpc
|
||||
|
|
@ -2266,11 +2419,11 @@ vspackages:
|
|||
name: grpc.dependencies.zlib
|
||||
props: false
|
||||
redist: true
|
||||
version: 1.2.8.9
|
||||
version: 1.2.8.10
|
||||
- name: grpc.dependencies.openssl
|
||||
props: true
|
||||
redist: true
|
||||
version: 1.0.2.3
|
||||
version: 1.0.204.1
|
||||
- name: gflags
|
||||
props: false
|
||||
redist: false
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ Request-Headers are delivered as HTTP2 headers in HEADERS + CONTINUATION frames.
|
|||
* **Custom-Metadata** → Binary-Header / ASCII-Header
|
||||
* **Binary-Header** → {Header-Name "-bin" } {_base64 encoded value_}
|
||||
* **ASCII-Header** → Header-Name ASCII-Value
|
||||
* **Header-Name** → 1\*( %x30-39 / %x61-7A / "\_" / "-") ; 0-9 a-z \_ -
|
||||
* **Header-Name** → 1\*( %x30-39 / %x61-7A / "\_" / "-" / ".") ; 0-9 a-z \_ - .
|
||||
* **ASCII-Value** → 1\*( %x20-%x7E ) ; space and printable ASCII
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,289 +0,0 @@
|
|||
#gRPC Authentication support
|
||||
|
||||
gRPC is designed to plug-in a number of authentication mechanisms. This document
|
||||
provides a quick overview of the various auth mechanisms supported, discusses
|
||||
the API with some examples, and concludes with a discussion of extensibility.
|
||||
More documentation and examples are coming soon!
|
||||
|
||||
## Supported auth mechanisms
|
||||
|
||||
###SSL/TLS
|
||||
gRPC has SSL/TLS integration and promotes the use of SSL/TLS to authenticate the
|
||||
server, and encrypt all the data exchanged between the client and the server.
|
||||
Optional mechanisms are available for clients to provide certificates to
|
||||
accomplish mutual authentication.
|
||||
|
||||
###OAuth 2.0
|
||||
gRPC provides a generic mechanism (described below) to attach metadata to
|
||||
requests and responses. This mechanism can be used to attach OAuth 2.0 Access
|
||||
Tokens to RPCs being made at a client. Additional support for acquiring Access
|
||||
Tokens while accessing Google APIs through gRPC is provided for certain auth
|
||||
flows, demonstrated through code examples below.
|
||||
|
||||
## API
|
||||
To reduce complexity and minimize API clutter, gRPC works with a unified concept
|
||||
of a Credentials object. Users construct gRPC credentials using corresponding
|
||||
bootstrap credentials (e.g., SSL client certs or Service Account Keys), and use
|
||||
the credentials while creating a gRPC channel to any server. Depending on the
|
||||
type of credential supplied, the channel uses the credentials during the initial
|
||||
SSL/TLS handshake with the server, or uses the credential to generate and
|
||||
attach Access Tokens to each request being made on the channel.
|
||||
|
||||
###SSL/TLS for server authentication and encryption
|
||||
This is the simplest authentication scenario, where a client just wants to
|
||||
authenticate the server and encrypt all data.
|
||||
|
||||
```cpp
|
||||
SslCredentialsOptions ssl_opts; // Options to override SSL params, empty by default
|
||||
// Create the credentials object by providing service account key in constructor
|
||||
std::shared_ptr<ChannelCredentials> creds = SslCredentials(ssl_opts);
|
||||
// Create a channel using the credentials created in the previous step
|
||||
std::shared_ptr<Channel> channel = CreateChannel(server_name, creds);
|
||||
// Create a stub on the channel
|
||||
std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
|
||||
// Make actual RPC calls on the stub.
|
||||
grpc::Status s = stub->sayHello(&context, *request, response);
|
||||
```
|
||||
|
||||
For advanced use cases such as modifying the root CA or using client certs,
|
||||
the corresponding options can be set in the SslCredentialsOptions parameter
|
||||
passed to the factory method.
|
||||
|
||||
|
||||
###Authenticating with Google
|
||||
|
||||
gRPC applications can use a simple API to create a credential that works in various deployment scenarios.
|
||||
|
||||
```cpp
|
||||
std::shared_ptr<ChannelCredentials> creds = GoogleDefaultCredentials();
|
||||
// Create a channel, stub and make RPC calls (same as in the previous example)
|
||||
std::shared_ptr<Channel> channel = CreateChannel(server_name, creds);
|
||||
std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
|
||||
grpc::Status s = stub->sayHello(&context, *request, response);
|
||||
```
|
||||
|
||||
This credential works for applications using Service Accounts as well as for
|
||||
applications running in [Google Compute Engine (GCE)](https://cloud.google.com/compute/). In the former case, the
|
||||
service account’s private keys are loaded from the file named in the environment
|
||||
variable `GOOGLE_APPLICATION_CREDENTIALS`. The
|
||||
keys are used to generate bearer tokens that are attached to each outgoing RPC
|
||||
on the corresponding channel.
|
||||
|
||||
For applications running in GCE, a default service account and corresponding
|
||||
OAuth scopes can be configured during VM setup. At run-time, this credential
|
||||
handles communication with the authentication systems to obtain OAuth2 access
|
||||
tokens and attaches them to each outgoing RPC on the corresponding channel.
|
||||
Extending gRPC to support other authentication mechanisms
|
||||
The gRPC protocol is designed with a general mechanism for sending metadata
|
||||
associated with RPC. Clients can send metadata at the beginning of an RPC and
|
||||
servers can send back metadata at the beginning and end of the RPC. This
|
||||
provides a natural mechanism to support OAuth2 and other authentication
|
||||
mechanisms that need attach bearer tokens to individual request.
|
||||
|
||||
In the simplest case, there is a single line of code required on the client
|
||||
to add a specific token as metadata to an RPC and a corresponding access on
|
||||
the server to retrieve this piece of metadata. The generation of the token
|
||||
on the client side and its verification at the server can be done separately.
|
||||
|
||||
A deeper integration can be achieved by plugging in a gRPC credentials implementation for any custom authentication mechanism that needs to attach per-request tokens. gRPC internals also allow switching out SSL/TLS with other encryption mechanisms.
|
||||
|
||||
## Examples
|
||||
|
||||
These authentication mechanisms will be available in all gRPC's supported languages.
|
||||
The following sections demonstrate how authentication and authorization features described above appear in each language: more languages are coming soon.
|
||||
|
||||
###SSL/TLS for server authentication and encryption (Ruby)
|
||||
```ruby
|
||||
# Base case - No encryption
|
||||
stub = Helloworld::Greeter::Stub.new('localhost:50051')
|
||||
...
|
||||
|
||||
# With server authentication SSL/TLS
|
||||
creds = GRPC::Core::Credentials.new(load_certs) # load_certs typically loads a CA roots file
|
||||
stub = Helloworld::Greeter::Stub.new('localhost:50051', creds: creds)
|
||||
```
|
||||
|
||||
###SSL/TLS for server authentication and encryption (C#)
|
||||
```csharp
|
||||
// Base case - No encryption
|
||||
var channel = new Channel("localhost:50051");
|
||||
var client = new Greeter.GreeterClient(channel);
|
||||
...
|
||||
|
||||
// With server authentication SSL/TLS
|
||||
var credentials = new SslCredentials(File.ReadAllText("ca.pem")); // Load a CA file
|
||||
var channel = new Channel("localhost:50051", credentials);
|
||||
var client = new Greeter.GreeterClient(channel);
|
||||
```
|
||||
|
||||
###SSL/TLS for server authentication and encryption (Objective-C)
|
||||
|
||||
The default for Objective-C is to use SSL/TLS, as that's the most common use case when accessing
|
||||
remote APIs.
|
||||
|
||||
```objective-c
|
||||
// Base case - With server authentication SSL/TLS
|
||||
HLWGreeter *client = [[HLWGreeter alloc] initWithHost:@"localhost:50051"];
|
||||
// Same as using @"https://localhost:50051".
|
||||
...
|
||||
|
||||
// No encryption
|
||||
HLWGreeter *client = [[HLWGreeter alloc] initWithHost:@"http://localhost:50051"];
|
||||
// Specifying the HTTP scheme explicitly forces no encryption.
|
||||
```
|
||||
|
||||
###SSL/TLS for server authentication and encryption (Python)
|
||||
```python
|
||||
# Base case - No encryption
|
||||
stub = early_adopter_create_GreeterService_stub('localhost', 50051)
|
||||
...
|
||||
|
||||
# With server authentication SSL/TLS
|
||||
stub = early_adopter_create_GreeterService_stub(
|
||||
'localhost', 50051, secure=True, root_certificates=open('ca.pem').read())
|
||||
...
|
||||
```
|
||||
n.b.: the beta API will look different
|
||||
|
||||
###Authenticating with Google (Ruby)
|
||||
```ruby
|
||||
# Base case - No encryption/authorization
|
||||
stub = Helloworld::Greeter::Stub.new('localhost:50051')
|
||||
...
|
||||
|
||||
# Authenticating with Google
|
||||
require 'googleauth' # from http://www.rubydoc.info/gems/googleauth/0.1.0
|
||||
...
|
||||
creds = GRPC::Core::Credentials.new(load_certs) # load_certs typically loads a CA roots file
|
||||
scope = 'https://www.googleapis.com/auth/grpc-testing'
|
||||
authorization = Google::Auth.get_application_default(scope)
|
||||
stub = Helloworld::Greeter::Stub.new('localhost:50051',
|
||||
creds: creds,
|
||||
update_metadata: authorization.updater_proc)
|
||||
```
|
||||
|
||||
###Authenticating with Google (Node.js)
|
||||
|
||||
```node
|
||||
// Base case - No encryption/authorization
|
||||
var stub = new helloworld.Greeter('localhost:50051');
|
||||
...
|
||||
// Authenticating with Google
|
||||
var GoogleAuth = require('google-auth-library'); // from https://www.npmjs.com/package/google-auth-library
|
||||
...
|
||||
var creds = grpc.Credentials.createSsl(load_certs); // load_certs typically loads a CA roots file
|
||||
var scope = 'https://www.googleapis.com/auth/grpc-testing';
|
||||
(new GoogleAuth()).getApplicationDefault(function(err, auth) {
|
||||
if (auth.createScopeRequired()) {
|
||||
auth = auth.createScoped(scope);
|
||||
}
|
||||
var stub = new helloworld.Greeter('localhost:50051',
|
||||
{credentials: creds},
|
||||
grpc.getGoogleAuthDelegate(auth));
|
||||
});
|
||||
```
|
||||
|
||||
###Authenticating with Google (C#)
|
||||
```csharp
|
||||
// Base case - No encryption/authorization
|
||||
var channel = new Channel("localhost:50051");
|
||||
var client = new Greeter.GreeterClient(channel);
|
||||
...
|
||||
|
||||
// Authenticating with Google
|
||||
using Grpc.Auth; // from Grpc.Auth NuGet package
|
||||
...
|
||||
var credentials = new SslCredentials(File.ReadAllText("ca.pem")); // Load a CA file
|
||||
var channel = new Channel("localhost:50051", credentials);
|
||||
|
||||
string scope = "https://www.googleapis.com/auth/grpc-testing";
|
||||
var authorization = GoogleCredential.GetApplicationDefault();
|
||||
if (authorization.IsCreateScopedRequired)
|
||||
{
|
||||
authorization = credential.CreateScoped(new[] { scope });
|
||||
}
|
||||
var client = new Greeter.GreeterClient(channel,
|
||||
new StubConfiguration(OAuth2InterceptorFactory.Create(credential)));
|
||||
```
|
||||
|
||||
###Authenticating with Google (PHP)
|
||||
```php
|
||||
// Base case - No encryption/authorization
|
||||
$client = new helloworld\GreeterClient(
|
||||
new Grpc\BaseStub('localhost:50051', []));
|
||||
...
|
||||
|
||||
// Authenticating with Google
|
||||
// the environment variable "GOOGLE_APPLICATION_CREDENTIALS" needs to be set
|
||||
$scope = "https://www.googleapis.com/auth/grpc-testing";
|
||||
$auth = Google\Auth\ApplicationDefaultCredentials::getCredentials($scope);
|
||||
$opts = [
|
||||
'credentials' => Grpc\Credentials::createSsl(file_get_contents('ca.pem'));
|
||||
'update_metadata' => $auth->getUpdateMetadataFunc(),
|
||||
];
|
||||
|
||||
$client = new helloworld\GreeterClient(
|
||||
new Grpc\BaseStub('localhost:50051', $opts));
|
||||
|
||||
```
|
||||
|
||||
###Authenticating with Google (Objective-C)
|
||||
|
||||
This example uses the [Google iOS Sign-In library](https://developers.google.com/identity/sign-in/ios/),
|
||||
but it's easily extrapolated to any other OAuth2 library.
|
||||
|
||||
```objective-c
|
||||
// Base case - No authentication
|
||||
[client sayHelloWithRequest:request handler:^(HLWHelloReply *response, NSError *error) {
|
||||
...
|
||||
}];
|
||||
|
||||
...
|
||||
|
||||
// Authenticating with Google
|
||||
|
||||
// When signing the user in, ask her for the relevant scopes.
|
||||
GIDSignIn.sharedInstance.scopes = @[@"https://www.googleapis.com/auth/grpc-testing"];
|
||||
|
||||
...
|
||||
|
||||
#import <ProtoRPC/ProtoRPC.h>
|
||||
|
||||
// Create a not-yet-started RPC. We want to set the request headers on this object before starting
|
||||
// it.
|
||||
ProtoRPC *call =
|
||||
[client RPCToSayHelloWithRequest:request handler:^(HLWHelloReply *response, NSError *error) {
|
||||
...
|
||||
}];
|
||||
|
||||
// Set the access token to be used.
|
||||
NSString *accessToken = GIDSignIn.sharedInstance.currentUser.authentication.accessToken;
|
||||
call.requestMetadata[@"Authorization"] = [@"Bearer " stringByAppendingString:accessToken]}];
|
||||
|
||||
// Start the RPC.
|
||||
[call start];
|
||||
```
|
||||
|
||||
You can see a working example app, with a more detailed explanation, [here](examples/objective-c/auth_sample).
|
||||
|
||||
### Authenticating with Google (Python)
|
||||
```python
|
||||
# Base case - No encryption
|
||||
stub = early_adopter_create_GreeterService_stub('localhost', 50051)
|
||||
...
|
||||
|
||||
# With server authentication SSL/TLS
|
||||
import oauth2client.client
|
||||
credentials = oauth2client.GoogleCredentials.get_application_default()
|
||||
scope = 'https://www.googleapis.com/auth/grpc-testing'
|
||||
scoped_credentials = credentials.create_scoped([scope])
|
||||
access_token = scoped_credentials.get_access_token().access_token
|
||||
metadata_transformer = (
|
||||
lambda x: [('Authorization', 'Bearer {}'.format(access_token))])
|
||||
|
||||
stub = early_adopter_create_GreeterService_stub(
|
||||
'localhost', 50051, secure=True, root_certificates=open('ca.pem').read(),
|
||||
metadata_transformer=metadata_transformer)
|
||||
...
|
||||
```
|
||||
n.b.: the beta API will look different
|
||||
|
|
@ -41,7 +41,7 @@ message from the remote client containing the user's name, then send back
|
|||
a greeting in a single `HelloReply`. This is the simplest type of RPC you
|
||||
can specify in gRPC - we'll look at some other types later in this document.
|
||||
|
||||
```
|
||||
```protobuf
|
||||
syntax = "proto3";
|
||||
|
||||
option java_package = "ex.grpc";
|
||||
|
|
@ -93,20 +93,20 @@ $ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto
|
|||
channel can be created with the target address, credentials to use and
|
||||
arguments as follows
|
||||
|
||||
```
|
||||
```cpp
|
||||
auto channel = CreateChannel("localhost:50051", InsecureChannelCredentials());
|
||||
```
|
||||
|
||||
- Create a stub. A stub implements the rpc methods of a service and in the
|
||||
generated code, a method is provided to created a stub with a channel:
|
||||
|
||||
```
|
||||
```cpp
|
||||
auto stub = helloworld::Greeter::NewStub(channel);
|
||||
```
|
||||
|
||||
- Make a unary rpc, with `ClientContext` and request/response proto messages.
|
||||
|
||||
```
|
||||
```cpp
|
||||
ClientContext context;
|
||||
HelloRequest request;
|
||||
request.set_name("hello");
|
||||
|
|
@ -116,7 +116,7 @@ $ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto
|
|||
|
||||
- Check returned status and response.
|
||||
|
||||
```
|
||||
```cpp
|
||||
if (status.ok()) {
|
||||
// check reply.message()
|
||||
} else {
|
||||
|
|
@ -130,7 +130,7 @@ For a working example, refer to [greeter_client.cc](greeter_client.cc).
|
|||
|
||||
- Implement the service interface
|
||||
|
||||
```
|
||||
```cpp
|
||||
class GreeterServiceImpl final : public Greeter::Service {
|
||||
Status SayHello(ServerContext* context, const HelloRequest* request,
|
||||
HelloReply* reply) override {
|
||||
|
|
@ -144,7 +144,7 @@ For a working example, refer to [greeter_client.cc](greeter_client.cc).
|
|||
|
||||
- Build a server exporting the service
|
||||
|
||||
```
|
||||
```cpp
|
||||
GreeterServiceImpl service;
|
||||
ServerBuilder builder;
|
||||
builder.AddListeningPort("0.0.0.0:50051", grpc::InsecureServerCredentials());
|
||||
|
|
@ -170,14 +170,14 @@ The channel and stub creation code is the same as the sync client.
|
|||
- Initiate the rpc and create a handle for the rpc. Bind the rpc to a
|
||||
`CompletionQueue`.
|
||||
|
||||
```
|
||||
```cpp
|
||||
CompletionQueue cq;
|
||||
auto rpc = stub->AsyncSayHello(&context, request, &cq);
|
||||
```
|
||||
|
||||
- Ask for reply and final status, with a unique tag
|
||||
|
||||
```
|
||||
```cpp
|
||||
Status status;
|
||||
rpc->Finish(&reply, &status, (void*)1);
|
||||
```
|
||||
|
|
@ -185,7 +185,7 @@ The channel and stub creation code is the same as the sync client.
|
|||
- Wait for the completion queue to return the next tag. The reply and status are
|
||||
ready once the tag passed into the corresponding `Finish()` call is returned.
|
||||
|
||||
```
|
||||
```cpp
|
||||
void* got_tag;
|
||||
bool ok = false;
|
||||
cq.Next(&got_tag, &ok);
|
||||
|
|
@ -203,7 +203,7 @@ completion queue to return the tag. The basic flow is
|
|||
|
||||
- Build a server exporting the async service
|
||||
|
||||
```
|
||||
```cpp
|
||||
helloworld::Greeter::AsyncService service;
|
||||
ServerBuilder builder;
|
||||
builder.AddListeningPort("0.0.0.0:50051", InsecureServerCredentials());
|
||||
|
|
@ -214,7 +214,7 @@ completion queue to return the tag. The basic flow is
|
|||
|
||||
- Request one rpc
|
||||
|
||||
```
|
||||
```cpp
|
||||
ServerContext context;
|
||||
HelloRequest request;
|
||||
ServerAsyncResponseWriter<HelloReply> responder;
|
||||
|
|
@ -224,7 +224,7 @@ completion queue to return the tag. The basic flow is
|
|||
- Wait for the completion queue to return the tag. The context, request and
|
||||
responder are ready once the tag is retrieved.
|
||||
|
||||
```
|
||||
```cpp
|
||||
HelloReply reply;
|
||||
Status status;
|
||||
void* got_tag;
|
||||
|
|
@ -239,7 +239,7 @@ completion queue to return the tag. The basic flow is
|
|||
- Wait for the completion queue to return the tag. The rpc is finished when the
|
||||
tag is back.
|
||||
|
||||
```
|
||||
```cpp
|
||||
void* got_tag;
|
||||
bool ok = false;
|
||||
cq.Next(&got_tag, &ok);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ Pod::Spec.new do |s|
|
|||
ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}"
|
||||
ss.header_mappings_dir = dir
|
||||
ss.requires_arc = true
|
||||
ss.dependency "gRPC", "~> 0.11"
|
||||
ss.dependency "gRPC", "~> 0.12"
|
||||
ss.dependency "#{s.name}/Messages"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ source 'https://github.com/CocoaPods/Specs.git'
|
|||
platform :ios, '8.0'
|
||||
|
||||
pod 'Protobuf', :path => "../../../third_party/protobuf"
|
||||
pod 'BoringSSL', :podspec => "../../../src/objective-c"
|
||||
pod 'gRPC', :path => "../../.."
|
||||
|
||||
target 'AuthSample' do
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ Pod::Spec.new do |s|
|
|||
ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}"
|
||||
ss.header_mappings_dir = dir
|
||||
ss.requires_arc = true
|
||||
ss.dependency "gRPC", "~> 0.11"
|
||||
ss.dependency "gRPC", "~> 0.12"
|
||||
ss.dependency "#{s.name}/Messages"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ source 'https://github.com/CocoaPods/Specs.git'
|
|||
platform :ios, '8.0'
|
||||
|
||||
pod 'Protobuf', :path => "../../../third_party/protobuf"
|
||||
pod 'BoringSSL', :podspec => "../../../src/objective-c"
|
||||
pod 'gRPC', :path => "../../.."
|
||||
|
||||
target 'HelloWorld' do
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ platform :ios, '8.0'
|
|||
|
||||
target 'RouteGuideClient' do
|
||||
pod 'Protobuf', :path => "../../../third_party/protobuf"
|
||||
pod 'BoringSSL', :podspec => "../../../src/objective-c"
|
||||
pod 'gRPC', :path => "../../.."
|
||||
# Depend on the generated RouteGuide library.
|
||||
pod 'RouteGuide', :path => '.'
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ Pod::Spec.new do |s|
|
|||
ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}"
|
||||
ss.header_mappings_dir = dir
|
||||
ss.requires_arc = true
|
||||
ss.dependency "gRPC", "~> 0.11"
|
||||
ss.dependency "gRPC", "~> 0.12"
|
||||
ss.dependency "#{s.name}/Messages"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
19
gRPC.podspec
19
gRPC.podspec
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'gRPC'
|
||||
version = '0.11.2'
|
||||
version = '0.12.0'
|
||||
s.version = version
|
||||
s.summary = 'gRPC client library for iOS/OSX'
|
||||
s.homepage = 'http://www.grpc.io'
|
||||
|
|
@ -165,7 +165,6 @@ Pod::Spec.new do |s|
|
|||
'src/core/channel/context.h',
|
||||
'src/core/channel/http_client_filter.h',
|
||||
'src/core/channel/http_server_filter.h',
|
||||
'src/core/channel/noop_filter.h',
|
||||
'src/core/channel/subchannel_call_holder.h',
|
||||
'src/core/client_config/client_config.h',
|
||||
'src/core/client_config/connector.h',
|
||||
|
|
@ -182,9 +181,8 @@ Pod::Spec.new do |s|
|
|||
'src/core/client_config/resolvers/sockaddr_resolver.h',
|
||||
'src/core/client_config/subchannel.h',
|
||||
'src/core/client_config/subchannel_factory.h',
|
||||
'src/core/client_config/subchannel_factory_decorators/add_channel_arg.h',
|
||||
'src/core/client_config/subchannel_factory_decorators/merge_channel_args.h',
|
||||
'src/core/client_config/uri_parser.h',
|
||||
'src/core/compression/algorithm_metadata.h',
|
||||
'src/core/compression/message_compress.h',
|
||||
'src/core/debug/trace.h',
|
||||
'src/core/httpcli/format_request.h',
|
||||
|
|
@ -267,6 +265,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/transport/connectivity_state.h',
|
||||
'src/core/transport/metadata.h',
|
||||
'src/core/transport/metadata_batch.h',
|
||||
'src/core/transport/static_metadata.h',
|
||||
'src/core/transport/transport.h',
|
||||
'src/core/transport/transport_impl.h',
|
||||
'src/core/census/aggregation.h',
|
||||
|
|
@ -310,7 +309,6 @@ Pod::Spec.new do |s|
|
|||
'src/core/channel/connected_channel.c',
|
||||
'src/core/channel/http_client_filter.c',
|
||||
'src/core/channel/http_server_filter.c',
|
||||
'src/core/channel/noop_filter.c',
|
||||
'src/core/channel/subchannel_call_holder.c',
|
||||
'src/core/client_config/client_config.c',
|
||||
'src/core/client_config/connector.c',
|
||||
|
|
@ -328,8 +326,6 @@ Pod::Spec.new do |s|
|
|||
'src/core/client_config/resolvers/sockaddr_resolver.c',
|
||||
'src/core/client_config/subchannel.c',
|
||||
'src/core/client_config/subchannel_factory.c',
|
||||
'src/core/client_config/subchannel_factory_decorators/add_channel_arg.c',
|
||||
'src/core/client_config/subchannel_factory_decorators/merge_channel_args.c',
|
||||
'src/core/client_config/uri_parser.c',
|
||||
'src/core/compression/algorithm.c',
|
||||
'src/core/compression/message_compress.c',
|
||||
|
|
@ -390,6 +386,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/surface/channel.c',
|
||||
'src/core/surface/channel_connectivity.c',
|
||||
'src/core/surface/channel_create.c',
|
||||
'src/core/surface/channel_ping.c',
|
||||
'src/core/surface/completion_queue.c',
|
||||
'src/core/surface/event_string.c',
|
||||
'src/core/surface/init.c',
|
||||
|
|
@ -424,6 +421,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/transport/connectivity_state.c',
|
||||
'src/core/transport/metadata.c',
|
||||
'src/core/transport/metadata_batch.c',
|
||||
'src/core/transport/static_metadata.c',
|
||||
'src/core/transport/transport.c',
|
||||
'src/core/transport/transport_op_string.c',
|
||||
'src/core/census/context.c',
|
||||
|
|
@ -464,7 +462,6 @@ Pod::Spec.new do |s|
|
|||
'src/core/channel/context.h',
|
||||
'src/core/channel/http_client_filter.h',
|
||||
'src/core/channel/http_server_filter.h',
|
||||
'src/core/channel/noop_filter.h',
|
||||
'src/core/channel/subchannel_call_holder.h',
|
||||
'src/core/client_config/client_config.h',
|
||||
'src/core/client_config/connector.h',
|
||||
|
|
@ -481,9 +478,8 @@ Pod::Spec.new do |s|
|
|||
'src/core/client_config/resolvers/sockaddr_resolver.h',
|
||||
'src/core/client_config/subchannel.h',
|
||||
'src/core/client_config/subchannel_factory.h',
|
||||
'src/core/client_config/subchannel_factory_decorators/add_channel_arg.h',
|
||||
'src/core/client_config/subchannel_factory_decorators/merge_channel_args.h',
|
||||
'src/core/client_config/uri_parser.h',
|
||||
'src/core/compression/algorithm_metadata.h',
|
||||
'src/core/compression/message_compress.h',
|
||||
'src/core/debug/trace.h',
|
||||
'src/core/httpcli/format_request.h',
|
||||
|
|
@ -566,6 +562,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/transport/connectivity_state.h',
|
||||
'src/core/transport/metadata.h',
|
||||
'src/core/transport/metadata_batch.h',
|
||||
'src/core/transport/static_metadata.h',
|
||||
'src/core/transport/transport.h',
|
||||
'src/core/transport/transport_impl.h',
|
||||
'src/core/census/aggregation.h',
|
||||
|
|
@ -584,7 +581,7 @@ Pod::Spec.new do |s|
|
|||
|
||||
ss.requires_arc = false
|
||||
ss.libraries = 'z'
|
||||
ss.dependency 'OpenSSL', '~> 1.0.200'
|
||||
ss.dependency 'BoringSSL', '~> 1.0'
|
||||
|
||||
# ss.compiler_flags = '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ class ClientContext {
|
|||
/// \return The call's peer URI.
|
||||
grpc::string peer() const;
|
||||
|
||||
/// Get and set census context
|
||||
/// Get and set census context.
|
||||
void set_census_context(struct census_context* ccp) { census_context_ = ccp; }
|
||||
struct census_context* census_context() const {
|
||||
return census_context_;
|
||||
|
|
@ -280,6 +280,17 @@ class ClientContext {
|
|||
/// There is no guarantee the call will be cancelled.
|
||||
void TryCancel();
|
||||
|
||||
/// Global Callbacks
|
||||
///
|
||||
/// Can be set exactly once per application to install hooks whenever
|
||||
/// a client context is constructed and destructed.
|
||||
class GlobalCallbacks {
|
||||
public:
|
||||
virtual void DefaultConstructor(ClientContext* context) = 0;
|
||||
virtual void Destructor(ClientContext* context) = 0;
|
||||
};
|
||||
static void SetGlobalCallbacks(GlobalCallbacks* callbacks);
|
||||
|
||||
private:
|
||||
// Disallow copy and assign.
|
||||
ClientContext(const ClientContext&);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#ifndef GRPCXX_IMPL_RPC_SERVICE_METHOD_H
|
||||
#define GRPCXX_IMPL_RPC_SERVICE_METHOD_H
|
||||
|
||||
#include <climits>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
|
@ -251,7 +252,11 @@ class RpcService {
|
|||
void AddMethod(RpcServiceMethod* method) { methods_.emplace_back(method); }
|
||||
|
||||
RpcServiceMethod* GetMethod(int i) { return methods_[i].get(); }
|
||||
int GetMethodCount() const { return methods_.size(); }
|
||||
int GetMethodCount() const {
|
||||
// On win x64, int is only 32bit
|
||||
GPR_ASSERT(methods_.size() <= INT_MAX);
|
||||
return (int)methods_.size();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<RpcServiceMethod>> methods_;
|
||||
|
|
|
|||
|
|
@ -31,16 +31,21 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_ADD_CHANNEL_ARG_H
|
||||
#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_ADD_CHANNEL_ARG_H
|
||||
#ifndef GRPCXX_IMPL_SERVER_BUILDER_OPTION_H
|
||||
#define GRPCXX_IMPL_SERVER_BUILDER_OPTION_H
|
||||
|
||||
#include "src/core/client_config/subchannel_factory.h"
|
||||
#include <grpc++/support/channel_arguments.h>
|
||||
|
||||
/** Takes a subchannel factory, returns a new one that mutates incoming
|
||||
channel_args by adding a new argument; ownership of input, arg is retained
|
||||
by the caller. */
|
||||
grpc_subchannel_factory *grpc_subchannel_factory_add_channel_arg(
|
||||
grpc_subchannel_factory *input, const grpc_arg *arg);
|
||||
namespace grpc {
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_ADD_CHANNEL_ARG_H \
|
||||
*/
|
||||
/// Interface to pass an option to a \a ServerBuilder.
|
||||
class ServerBuilderOption {
|
||||
public:
|
||||
virtual ~ServerBuilderOption() {}
|
||||
/// Alter the \a ChannelArguments used to create the gRPC server.
|
||||
virtual void UpdateArguments(ChannelArguments* args) = 0;
|
||||
};
|
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif // GRPCXX_IMPL_SERVER_BUILDER_OPTION_H
|
||||
|
|
@ -38,6 +38,7 @@
|
|||
#include <memory>
|
||||
|
||||
#include <grpc++/impl/grpc_library.h>
|
||||
#include <grpc++/security/auth_context.h>
|
||||
#include <grpc++/support/config.h>
|
||||
#include <grpc++/support/status.h>
|
||||
#include <grpc++/support/string_ref.h>
|
||||
|
|
@ -206,9 +207,17 @@ class MetadataCredentialsPlugin {
|
|||
// a different thread from the one processing the call.
|
||||
virtual bool IsBlocking() const { return true; }
|
||||
|
||||
// Type of credentials this plugin is implementing.
|
||||
virtual const char* GetType() const { return ""; }
|
||||
|
||||
// Gets the auth metatada produced by this plugin.
|
||||
// The fully qualified method name is:
|
||||
// service_url + "/" + method_name.
|
||||
// The channel_auth_context contains (among other things), the identity of
|
||||
// the server.
|
||||
virtual Status GetMetadata(
|
||||
grpc::string_ref service_url,
|
||||
grpc::string_ref service_url, grpc::string_ref method_name,
|
||||
const AuthContext& channel_auth_context,
|
||||
std::multimap<grpc::string, grpc::string>* metadata) = 0;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -37,14 +37,15 @@
|
|||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
#include <grpc/compression.h>
|
||||
#include <grpc++/completion_queue.h>
|
||||
#include <grpc++/impl/call.h>
|
||||
#include <grpc++/impl/grpc_library.h>
|
||||
#include <grpc++/impl/sync.h>
|
||||
#include <grpc++/security/server_credentials.h>
|
||||
#include <grpc++/support/channel_arguments.h>
|
||||
#include <grpc++/support/config.h>
|
||||
#include <grpc++/support/status.h>
|
||||
#include <grpc/compression.h>
|
||||
|
||||
struct grpc_server;
|
||||
|
||||
|
|
@ -56,6 +57,7 @@ class AsyncGenericService;
|
|||
class RpcService;
|
||||
class RpcServiceMethod;
|
||||
class ServerAsyncStreamingInterface;
|
||||
class ServerContext;
|
||||
class ThreadPoolInterface;
|
||||
|
||||
/// Models a gRPC server.
|
||||
|
|
@ -84,6 +86,23 @@ class Server GRPC_FINAL : public GrpcLibrary, private CallHook {
|
|||
/// call \a Shutdown for this function to ever return.
|
||||
void Wait();
|
||||
|
||||
/// Global Callbacks
|
||||
///
|
||||
/// Can be set exactly once per application to install hooks whenever
|
||||
/// a server event occurs
|
||||
class GlobalCallbacks {
|
||||
public:
|
||||
virtual ~GlobalCallbacks() {}
|
||||
/// Called before application callback for each synchronous server request
|
||||
virtual void PreSynchronousRequest(ServerContext* context) = 0;
|
||||
/// Called after application callback for each synchronous server request
|
||||
virtual void PostSynchronousRequest(ServerContext* context) = 0;
|
||||
};
|
||||
/// Set the global callback object. Can only be called once. Does not take
|
||||
/// ownership of callbacks, and expects the pointed to object to be alive
|
||||
/// until all server objects in the process have been destroyed.
|
||||
static void SetGlobalCallbacks(GlobalCallbacks* callbacks);
|
||||
|
||||
private:
|
||||
friend class AsyncGenericService;
|
||||
friend class AsynchronousService;
|
||||
|
|
@ -100,7 +119,7 @@ class Server GRPC_FINAL : public GrpcLibrary, private CallHook {
|
|||
/// \param max_message_size Maximum message length that the channel can
|
||||
/// receive.
|
||||
Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
|
||||
int max_message_size, grpc_compression_options compression_options);
|
||||
int max_message_size, const ChannelArguments& args);
|
||||
|
||||
/// Register a service. This call does not take ownership of the service.
|
||||
/// The service must exist for the lifetime of the Server instance.
|
||||
|
|
|
|||
|
|
@ -37,8 +37,9 @@
|
|||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <grpc/compression.h>
|
||||
#include <grpc++/impl/server_builder_option.h>
|
||||
#include <grpc++/support/config.h>
|
||||
#include <grpc/compression.h>
|
||||
|
||||
namespace grpc {
|
||||
|
||||
|
|
@ -98,6 +99,8 @@ class ServerBuilder {
|
|||
compression_options_ = options;
|
||||
}
|
||||
|
||||
void SetOption(std::unique_ptr<ServerBuilderOption> option);
|
||||
|
||||
/// Tries to bind \a server to the given \a addr.
|
||||
///
|
||||
/// It can be invoked multiple times.
|
||||
|
|
@ -140,6 +143,7 @@ class ServerBuilder {
|
|||
|
||||
int max_message_size_;
|
||||
grpc_compression_options compression_options_;
|
||||
std::vector<std::unique_ptr<ServerBuilderOption>> options_;
|
||||
std::vector<std::unique_ptr<NamedService<RpcService>>> services_;
|
||||
std::vector<std::unique_ptr<NamedService<AsynchronousService>>>
|
||||
async_services_;
|
||||
|
|
|
|||
|
|
@ -80,6 +80,11 @@ class ChannelArguments {
|
|||
// Generic channel argument setters. Only for advanced use cases.
|
||||
/// Set an integer argument \a value under \a key.
|
||||
void SetInt(const grpc::string& key, int value);
|
||||
|
||||
// Generic channel argument setter. Only for advanced use cases.
|
||||
/// Set a pointer argument \a value under \a key. Owership is not transferred.
|
||||
void SetPointer(const grpc::string& key, void* value);
|
||||
|
||||
/// Set a textual argument \a value under \a key.
|
||||
void SetString(const grpc::string& key, const grpc::string& value);
|
||||
|
||||
|
|
|
|||
|
|
@ -79,12 +79,6 @@ int grpc_compression_algorithm_parse(const char *name, size_t name_length,
|
|||
int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
|
||||
char **name);
|
||||
|
||||
/** Returns the compression level corresponding to \a algorithm.
|
||||
*
|
||||
* It abort()s for unknown algorithms. */
|
||||
grpc_compression_level grpc_compression_level_for_algorithm(
|
||||
grpc_compression_algorithm algorithm);
|
||||
|
||||
/** Returns the compression algorithm corresponding to \a level.
|
||||
*
|
||||
* It abort()s for unknown levels . */
|
||||
|
|
|
|||
|
|
@ -531,6 +531,11 @@ grpc_call *grpc_channel_create_call(grpc_channel *channel,
|
|||
const char *method, const char *host,
|
||||
gpr_timespec deadline, void *reserved);
|
||||
|
||||
/** Ping the channels peer (load balanced channels will select one sub-channel
|
||||
to ping); if the channel is not connected, posts a failed. */
|
||||
void grpc_channel_ping(grpc_channel *channel, grpc_completion_queue *cq,
|
||||
void *tag, void *reserved);
|
||||
|
||||
/** Pre-register a method/host pair on a channel. */
|
||||
void *grpc_channel_register_call(grpc_channel *channel, const char *method,
|
||||
const char *host, void *reserved);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,81 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* --- Authentication Context. --- */
|
||||
|
||||
#define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME "transport_security_type"
|
||||
#define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl"
|
||||
|
||||
#define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"
|
||||
#define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
|
||||
|
||||
typedef struct grpc_auth_context grpc_auth_context;
|
||||
|
||||
typedef struct grpc_auth_property_iterator {
|
||||
const grpc_auth_context *ctx;
|
||||
size_t index;
|
||||
const char *name;
|
||||
} grpc_auth_property_iterator;
|
||||
|
||||
/* value, if not NULL, is guaranteed to be NULL terminated. */
|
||||
typedef struct grpc_auth_property {
|
||||
char *name;
|
||||
char *value;
|
||||
size_t value_length;
|
||||
} grpc_auth_property;
|
||||
|
||||
/* Returns NULL when the iterator is at the end. */
|
||||
const grpc_auth_property *grpc_auth_property_iterator_next(
|
||||
grpc_auth_property_iterator *it);
|
||||
|
||||
/* Iterates over the auth context. */
|
||||
grpc_auth_property_iterator grpc_auth_context_property_iterator(
|
||||
const grpc_auth_context *ctx);
|
||||
|
||||
/* Gets the peer identity. Returns an empty iterator (first _next will return
|
||||
NULL) if the peer is not authenticated. */
|
||||
grpc_auth_property_iterator grpc_auth_context_peer_identity(
|
||||
const grpc_auth_context *ctx);
|
||||
|
||||
/* Finds a property in the context. May return an empty iterator (first _next
|
||||
will return NULL) if no property with this name was found in the context. */
|
||||
grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
|
||||
const grpc_auth_context *ctx, const char *name);
|
||||
|
||||
/* Gets the name of the property that indicates the peer identity. Will return
|
||||
NULL if the peer is not authenticated. */
|
||||
const char *grpc_auth_context_peer_identity_property_name(
|
||||
const grpc_auth_context *ctx);
|
||||
|
||||
/* Returns 1 if the peer is authenticated, 0 otherwise. */
|
||||
int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx);
|
||||
|
||||
/* Gets the auth context from the call. Caller needs to call
|
||||
grpc_auth_context_release on the returned context. */
|
||||
grpc_auth_context *grpc_call_auth_context(grpc_call *call);
|
||||
|
||||
/* Releases the auth context returned from grpc_call_auth_context. */
|
||||
void grpc_auth_context_release(grpc_auth_context *context);
|
||||
|
||||
/* --
|
||||
The following auth context methods should only be called by a server metadata
|
||||
processor to set properties extracted from auth metadata.
|
||||
-- */
|
||||
|
||||
/* Add a property. */
|
||||
void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name,
|
||||
const char *value, size_t value_length);
|
||||
|
||||
/* Add a C string property. */
|
||||
void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx,
|
||||
const char *name,
|
||||
const char *value);
|
||||
|
||||
/* Sets the property name. Returns 1 if successful or 0 in case of failure
|
||||
(which means that no property with this name exists). */
|
||||
int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx,
|
||||
const char *name);
|
||||
|
||||
/* --- grpc_channel_credentials object. ---
|
||||
|
||||
A channel credentials object represents a way to authenticate a client on a
|
||||
|
|
@ -165,6 +240,24 @@ typedef void (*grpc_credentials_plugin_metadata_cb)(
|
|||
void *user_data, const grpc_metadata *creds_md, size_t num_creds_md,
|
||||
grpc_status_code status, const char *error_details);
|
||||
|
||||
/* Context that can be used by metadata credentials plugin in order to create
|
||||
auth related metadata. */
|
||||
typedef struct {
|
||||
/* The fully qualifed service url. */
|
||||
const char *service_url;
|
||||
|
||||
/* The method name of the RPC being called (not fully qualified).
|
||||
The fully qualified method name can be built from the service_url:
|
||||
full_qualified_method_name = ctx->service_url + '/' + ctx->method_name. */
|
||||
const char *method_name;
|
||||
|
||||
/* The auth_context of the channel which gives the server's identity. */
|
||||
const grpc_auth_context *channel_auth_context;
|
||||
|
||||
/* Reserved for future use. */
|
||||
void *reserved;
|
||||
} grpc_auth_metadata_context;
|
||||
|
||||
/* grpc_metadata_credentials plugin is an API user provided structure used to
|
||||
create grpc_credentials objects that can be set on a channel (composed) or
|
||||
a call. See grpc_credentials_metadata_create_from_plugin below.
|
||||
|
|
@ -172,11 +265,11 @@ typedef void (*grpc_credentials_plugin_metadata_cb)(
|
|||
every call in scope for the credentials created from it. */
|
||||
typedef struct {
|
||||
/* The implementation of this method has to be non-blocking.
|
||||
- service_url is the fully qualified URL that the client stack is
|
||||
connecting to.
|
||||
- context is the information that can be used by the plugin to create auth
|
||||
metadata.
|
||||
- cb is the callback that needs to be called when the metadata is ready.
|
||||
- user_data needs to be passed as the first parameter of the callback. */
|
||||
void (*get_metadata)(void *state, const char *service_url,
|
||||
void (*get_metadata)(void *state, grpc_auth_metadata_context context,
|
||||
grpc_credentials_plugin_metadata_cb cb, void *user_data);
|
||||
|
||||
/* Destroys the plugin state. */
|
||||
|
|
@ -184,6 +277,9 @@ typedef struct {
|
|||
|
||||
/* State that will be set as the first parameter of the methods above. */
|
||||
void *state;
|
||||
|
||||
/* Type of credentials that this plugin is implementing. */
|
||||
const char *type;
|
||||
} grpc_metadata_credentials_plugin;
|
||||
|
||||
/* Creates a credentials object from a plugin. */
|
||||
|
|
@ -239,81 +335,6 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
|
|||
grpc_call_error grpc_call_set_credentials(grpc_call *call,
|
||||
grpc_call_credentials *creds);
|
||||
|
||||
/* --- Authentication Context. --- */
|
||||
|
||||
#define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME "transport_security_type"
|
||||
#define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl"
|
||||
|
||||
#define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"
|
||||
#define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
|
||||
|
||||
typedef struct grpc_auth_context grpc_auth_context;
|
||||
|
||||
typedef struct grpc_auth_property_iterator {
|
||||
const grpc_auth_context *ctx;
|
||||
size_t index;
|
||||
const char *name;
|
||||
} grpc_auth_property_iterator;
|
||||
|
||||
/* value, if not NULL, is guaranteed to be NULL terminated. */
|
||||
typedef struct grpc_auth_property {
|
||||
char *name;
|
||||
char *value;
|
||||
size_t value_length;
|
||||
} grpc_auth_property;
|
||||
|
||||
/* Returns NULL when the iterator is at the end. */
|
||||
const grpc_auth_property *grpc_auth_property_iterator_next(
|
||||
grpc_auth_property_iterator *it);
|
||||
|
||||
/* Iterates over the auth context. */
|
||||
grpc_auth_property_iterator grpc_auth_context_property_iterator(
|
||||
const grpc_auth_context *ctx);
|
||||
|
||||
/* Gets the peer identity. Returns an empty iterator (first _next will return
|
||||
NULL) if the peer is not authenticated. */
|
||||
grpc_auth_property_iterator grpc_auth_context_peer_identity(
|
||||
const grpc_auth_context *ctx);
|
||||
|
||||
/* Finds a property in the context. May return an empty iterator (first _next
|
||||
will return NULL) if no property with this name was found in the context. */
|
||||
grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
|
||||
const grpc_auth_context *ctx, const char *name);
|
||||
|
||||
/* Gets the name of the property that indicates the peer identity. Will return
|
||||
NULL if the peer is not authenticated. */
|
||||
const char *grpc_auth_context_peer_identity_property_name(
|
||||
const grpc_auth_context *ctx);
|
||||
|
||||
/* Returns 1 if the peer is authenticated, 0 otherwise. */
|
||||
int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx);
|
||||
|
||||
/* Gets the auth context from the call. Caller needs to call
|
||||
grpc_auth_context_release on the returned context. */
|
||||
grpc_auth_context *grpc_call_auth_context(grpc_call *call);
|
||||
|
||||
/* Releases the auth context returned from grpc_call_auth_context. */
|
||||
void grpc_auth_context_release(grpc_auth_context *context);
|
||||
|
||||
/* --
|
||||
The following auth context methods should only be called by a server metadata
|
||||
processor to set properties extracted from auth metadata.
|
||||
-- */
|
||||
|
||||
/* Add a property. */
|
||||
void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name,
|
||||
const char *value, size_t value_length);
|
||||
|
||||
/* Add a C string property. */
|
||||
void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx,
|
||||
const char *name,
|
||||
const char *value);
|
||||
|
||||
/* Sets the property name. Returns 1 if successful or 0 in case of failure
|
||||
(which means that no property with this name exists). */
|
||||
int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx,
|
||||
const char *name);
|
||||
|
||||
/* --- Auth Metadata Processing --- */
|
||||
|
||||
/* Callback function that is called when the metadata processing is done.
|
||||
|
|
|
|||
|
|
@ -40,6 +40,12 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct gpr_allocation_functions {
|
||||
void *(*malloc_fn)(size_t size);
|
||||
void *(*realloc_fn)(void *ptr, size_t size);
|
||||
void (*free_fn)(void *ptr);
|
||||
} gpr_allocation_functions;
|
||||
|
||||
/* malloc, never returns NULL */
|
||||
void *gpr_malloc(size_t size);
|
||||
/* free */
|
||||
|
|
@ -51,6 +57,14 @@ void *gpr_malloc_aligned(size_t size, size_t alignment_log);
|
|||
/* free memory allocated by gpr_malloc_aligned */
|
||||
void gpr_free_aligned(void *ptr);
|
||||
|
||||
/** Request the family of allocation functions in \a functions be used. NOTE
|
||||
* that this request will be honored in a *best effort* basis and that no
|
||||
* guarantees are made about the default functions (eg, malloc) being called. */
|
||||
void gpr_set_allocation_functions(gpr_allocation_functions functions);
|
||||
|
||||
/** Return the family of allocation functions currently in effect. */
|
||||
gpr_allocation_functions gpr_get_allocation_functions();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -83,8 +83,12 @@ void gpr_cmdline_add_string(gpr_cmdline *cl, const char *name, const char *help,
|
|||
void gpr_cmdline_on_extra_arg(
|
||||
gpr_cmdline *cl, const char *name, const char *help,
|
||||
void (*on_extra_arg)(void *user_data, const char *arg), void *user_data);
|
||||
/* Parse the command line */
|
||||
void gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv);
|
||||
/* Enable surviving failure: default behavior is to exit the process */
|
||||
void gpr_cmdline_set_survive_failure(gpr_cmdline *cl);
|
||||
/* Parse the command line; returns 1 on success, on failure either dies
|
||||
(by default) or returns 0 if gpr_cmdline_set_survive_failure() has been
|
||||
called */
|
||||
int gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv);
|
||||
/* Destroy the parser */
|
||||
void gpr_cmdline_destroy(gpr_cmdline *cl);
|
||||
/* Get a string describing usage */
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@
|
|||
#endif
|
||||
#define GPR_MSG_IOVLEN_TYPE int
|
||||
#if TARGET_OS_IPHONE
|
||||
#define GPR_FORBID_UNREACHABLE_CODE
|
||||
#define GPR_FORBID_UNREACHABLE_CODE 1
|
||||
#define GPR_PLATFORM_STRING "ios"
|
||||
#define GPR_CPU_IPHONE 1
|
||||
#define GPR_PTHREAD_TLS 1
|
||||
|
|
@ -252,6 +252,11 @@
|
|||
#define GPR_PLATFORM_STRING "unknown"
|
||||
#endif
|
||||
|
||||
#ifdef GPR_GCOV
|
||||
#undef GPR_FORBID_UNREACHABLE_CODE
|
||||
#define GPR_FORBID_UNREACHABLE_CODE 1
|
||||
#endif
|
||||
|
||||
/* For a common case, assume that the platform has a C99-like stdint.h */
|
||||
|
||||
#include <stdint.h>
|
||||
|
|
@ -337,7 +342,7 @@ typedef uintptr_t gpr_uintptr;
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef GPR_FORBID_UNREACHABLE_CODE
|
||||
#if GPR_FORBID_UNREACHABLE_CODE
|
||||
#define GPR_UNREACHABLE_CODE(STATEMENT)
|
||||
#else
|
||||
#define GPR_UNREACHABLE_CODE(STATEMENT) \
|
||||
|
|
|
|||
|
|
@ -144,6 +144,9 @@ gpr_slice gpr_slice_from_copied_string(const char *source);
|
|||
memcpy(slice->data, source, len); */
|
||||
gpr_slice gpr_slice_from_copied_buffer(const char *source, size_t len);
|
||||
|
||||
/* Create a slice pointing to constant memory */
|
||||
gpr_slice gpr_slice_from_static_string(const char *source);
|
||||
|
||||
/* Return a result slice derived from s, which shares a ref count with s, where
|
||||
result.data==s.data+begin, and result.length==end-begin.
|
||||
The ref count of s is increased by one.
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@ typedef enum {
|
|||
} gpr_clock_type;
|
||||
|
||||
typedef struct gpr_timespec {
|
||||
time_t tv_sec;
|
||||
int tv_nsec;
|
||||
gpr_int64 tv_sec;
|
||||
gpr_int32 tv_nsec;
|
||||
/** Against which clock was this time measured? (or GPR_TIMESPAN if
|
||||
this is a relative time meaure) */
|
||||
gpr_clock_type clock_type;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "grpc",
|
||||
"version": "0.11.1",
|
||||
"version": "0.12.0",
|
||||
"author": "Google Inc.",
|
||||
"description": "gRPC Library for Node",
|
||||
"homepage": "http://www.grpc.io/",
|
||||
|
|
@ -39,7 +39,8 @@
|
|||
"minimist": "^1.1.0",
|
||||
"mocha": "~1.21.0",
|
||||
"mocha-jenkins-reporter": "^0.1.9",
|
||||
"mustache": "^2.0.0"
|
||||
"mustache": "^2.0.0",
|
||||
"poisson-process": "^0.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.13"
|
||||
|
|
|
|||
|
|
@ -36,14 +36,12 @@
|
|||
|
||||
#include <grpc/census.h>
|
||||
|
||||
#define GRPC_CENSUS_MAX_ON_THE_WIRE_TAG_BYTES 2048
|
||||
|
||||
/* census_context is the in-memory representation of information needed to
|
||||
* maintain tracing, RPC statistics and resource usage information. */
|
||||
struct census_context {
|
||||
gpr_uint64 op_id; /* Operation identifier - unique per-context */
|
||||
gpr_uint64 trace_id; /* Globally unique trace identifier */
|
||||
/* TODO(aveitch) Add census tags:
|
||||
const census_tag_set *tags;
|
||||
*/
|
||||
census_tag_set *tags; /* Opaque data structure for census tags. */
|
||||
};
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_CENSUS_CONTEXT_H */
|
||||
|
|
|
|||
|
|
@ -36,16 +36,17 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "src/core/channel/channel_stack.h"
|
||||
#include "src/core/channel/noop_filter.h"
|
||||
#include "src/core/statistics/census_interface.h"
|
||||
#include "src/core/statistics/census_rpc_stats.h"
|
||||
#include <grpc/census.h>
|
||||
#include <grpc/support/alloc.h>
|
||||
#include <grpc/support/log.h>
|
||||
#include <grpc/support/slice.h>
|
||||
#include <grpc/support/time.h>
|
||||
|
||||
#include "src/core/channel/channel_stack.h"
|
||||
#include "src/core/statistics/census_interface.h"
|
||||
#include "src/core/statistics/census_rpc_stats.h"
|
||||
#include "src/core/transport/static_metadata.h"
|
||||
|
||||
typedef struct call_data {
|
||||
census_op_id op_id;
|
||||
census_context *ctxt;
|
||||
|
|
@ -58,16 +59,14 @@ typedef struct call_data {
|
|||
grpc_closure finish_recv;
|
||||
} call_data;
|
||||
|
||||
typedef struct channel_data {
|
||||
grpc_mdstr *path_str; /* pointer to meta data str with key == ":path" */
|
||||
} channel_data;
|
||||
typedef struct channel_data { gpr_uint8 unused; } channel_data;
|
||||
|
||||
static void extract_and_annotate_method_tag(grpc_metadata_batch *md,
|
||||
call_data *calld,
|
||||
channel_data *chand) {
|
||||
grpc_linked_mdelem *m;
|
||||
for (m = md->list.head; m != NULL; m = m->next) {
|
||||
if (m->md->key == chand->path_str) {
|
||||
if (m->md->key == GRPC_MDSTR_PATH) {
|
||||
gpr_log(GPR_DEBUG, "%s",
|
||||
(const char *)GPR_SLICE_START_PTR(m->md->value->slice));
|
||||
/* Add method tag here */
|
||||
|
|
@ -116,8 +115,11 @@ static void server_mutate_op(grpc_call_element *elem,
|
|||
static void server_start_transport_op(grpc_exec_ctx *exec_ctx,
|
||||
grpc_call_element *elem,
|
||||
grpc_transport_stream_op *op) {
|
||||
/* TODO(ctiller): this code fails. I don't know why. I expect it's
|
||||
incomplete, and someone should look at it soon.
|
||||
|
||||
call_data *calld = elem->call_data;
|
||||
GPR_ASSERT((calld->op_id.upper != 0) || (calld->op_id.lower != 0));
|
||||
GPR_ASSERT((calld->op_id.upper != 0) || (calld->op_id.lower != 0)); */
|
||||
server_mutate_op(elem, op);
|
||||
grpc_call_next_op(exec_ctx, elem, op);
|
||||
}
|
||||
|
|
@ -161,16 +163,12 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
|
|||
grpc_channel_element_args *args) {
|
||||
channel_data *chand = elem->channel_data;
|
||||
GPR_ASSERT(chand != NULL);
|
||||
chand->path_str = grpc_mdstr_from_string(args->metadata_context, ":path");
|
||||
}
|
||||
|
||||
static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *elem) {
|
||||
channel_data *chand = elem->channel_data;
|
||||
GPR_ASSERT(chand != NULL);
|
||||
if (chand->path_str != NULL) {
|
||||
GRPC_MDSTR_UNREF(chand->path_str);
|
||||
}
|
||||
}
|
||||
|
||||
const grpc_channel_filter grpc_client_census_filter = {
|
||||
|
|
|
|||
|
|
@ -101,12 +101,12 @@ grpc_call_element *grpc_call_stack_element(grpc_call_stack *call_stack,
|
|||
return CALL_ELEMS_FROM_STACK(call_stack) + index;
|
||||
}
|
||||
|
||||
void grpc_channel_stack_init(grpc_exec_ctx *exec_ctx,
|
||||
void grpc_channel_stack_init(grpc_exec_ctx *exec_ctx, int initial_refs,
|
||||
grpc_iomgr_cb_func destroy, void *destroy_arg,
|
||||
const grpc_channel_filter **filters,
|
||||
size_t filter_count, grpc_channel *master,
|
||||
size_t filter_count,
|
||||
const grpc_channel_args *channel_args,
|
||||
grpc_mdctx *metadata_context,
|
||||
grpc_channel_stack *stack) {
|
||||
const char *name, grpc_channel_stack *stack) {
|
||||
size_t call_size =
|
||||
ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)) +
|
||||
ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_call_element));
|
||||
|
|
@ -116,6 +116,8 @@ void grpc_channel_stack_init(grpc_exec_ctx *exec_ctx,
|
|||
size_t i;
|
||||
|
||||
stack->count = filter_count;
|
||||
GRPC_STREAM_REF_INIT(&stack->refcount, initial_refs, destroy, destroy_arg,
|
||||
name);
|
||||
elems = CHANNEL_ELEMS_FROM_STACK(stack);
|
||||
user_data =
|
||||
((char *)elems) +
|
||||
|
|
@ -123,9 +125,8 @@ void grpc_channel_stack_init(grpc_exec_ctx *exec_ctx,
|
|||
|
||||
/* init per-filter data */
|
||||
for (i = 0; i < filter_count; i++) {
|
||||
args.master = master;
|
||||
args.channel_stack = stack;
|
||||
args.channel_args = channel_args;
|
||||
args.metadata_context = metadata_context;
|
||||
args.is_first = i == 0;
|
||||
args.is_last = i == (filter_count - 1);
|
||||
elems[i].filter = filters[i];
|
||||
|
|
@ -168,15 +169,15 @@ void grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
|
|||
size_t i;
|
||||
|
||||
call_stack->count = count;
|
||||
gpr_ref_init(&call_stack->refcount.refs, initial_refs);
|
||||
grpc_closure_init(&call_stack->refcount.destroy, destroy, destroy_arg);
|
||||
GRPC_STREAM_REF_INIT(&call_stack->refcount, initial_refs, destroy,
|
||||
destroy_arg, "CALL_STACK");
|
||||
call_elems = CALL_ELEMS_FROM_STACK(call_stack);
|
||||
user_data = ((char *)call_elems) +
|
||||
ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));
|
||||
|
||||
/* init per-filter data */
|
||||
for (i = 0; i < count; i++) {
|
||||
args.refcount = &call_stack->refcount;
|
||||
args.call_stack = call_stack;
|
||||
args.server_transport_data = transport_server_data;
|
||||
args.context = context;
|
||||
call_elems[i].filter = channel_elems[i].filter;
|
||||
|
|
|
|||
|
|
@ -51,16 +51,18 @@
|
|||
typedef struct grpc_channel_element grpc_channel_element;
|
||||
typedef struct grpc_call_element grpc_call_element;
|
||||
|
||||
typedef struct grpc_channel_stack grpc_channel_stack;
|
||||
typedef struct grpc_call_stack grpc_call_stack;
|
||||
|
||||
typedef struct {
|
||||
grpc_channel *master;
|
||||
grpc_channel_stack *channel_stack;
|
||||
const grpc_channel_args *channel_args;
|
||||
grpc_mdctx *metadata_context;
|
||||
int is_first;
|
||||
int is_last;
|
||||
} grpc_channel_element_args;
|
||||
|
||||
typedef struct {
|
||||
grpc_stream_refcount *refcount;
|
||||
grpc_call_stack *call_stack;
|
||||
const void *server_transport_data;
|
||||
grpc_call_context_element *context;
|
||||
} grpc_call_element_args;
|
||||
|
|
@ -145,23 +147,24 @@ struct grpc_call_element {
|
|||
|
||||
/* A channel stack tracks a set of related filters for one channel, and
|
||||
guarantees they live within a single malloc() allocation */
|
||||
typedef struct {
|
||||
struct grpc_channel_stack {
|
||||
grpc_stream_refcount refcount;
|
||||
size_t count;
|
||||
/* Memory required for a call stack (computed at channel stack
|
||||
initialization) */
|
||||
size_t call_stack_size;
|
||||
} grpc_channel_stack;
|
||||
};
|
||||
|
||||
/* A call stack tracks a set of related filters for one call, and guarantees
|
||||
they live within a single malloc() allocation */
|
||||
typedef struct {
|
||||
struct grpc_call_stack {
|
||||
/* shared refcount for this channel stack.
|
||||
MUST be the first element: the underlying code calls destroy
|
||||
with the address of the refcount, but higher layers prefer to think
|
||||
about the address of the call stack itself. */
|
||||
grpc_stream_refcount refcount;
|
||||
size_t count;
|
||||
} grpc_call_stack;
|
||||
};
|
||||
|
||||
/* Get a channel element given a channel stack and its index */
|
||||
grpc_channel_element *grpc_channel_stack_element(grpc_channel_stack *stack,
|
||||
|
|
@ -176,12 +179,11 @@ grpc_call_element *grpc_call_stack_element(grpc_call_stack *stack, size_t i);
|
|||
size_t grpc_channel_stack_size(const grpc_channel_filter **filters,
|
||||
size_t filter_count);
|
||||
/* Initialize a channel stack given some filters */
|
||||
void grpc_channel_stack_init(grpc_exec_ctx *exec_ctx,
|
||||
void grpc_channel_stack_init(grpc_exec_ctx *exec_ctx, int initial_refs,
|
||||
grpc_iomgr_cb_func destroy, void *destroy_arg,
|
||||
const grpc_channel_filter **filters,
|
||||
size_t filter_count, grpc_channel *master,
|
||||
const grpc_channel_args *args,
|
||||
grpc_mdctx *metadata_context,
|
||||
grpc_channel_stack *stack);
|
||||
size_t filter_count, const grpc_channel_args *args,
|
||||
const char *name, grpc_channel_stack *stack);
|
||||
/* Destroy a channel stack */
|
||||
void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_stack *stack);
|
||||
|
|
@ -201,14 +203,23 @@ void grpc_call_stack_set_pollset(grpc_exec_ctx *exec_ctx,
|
|||
grpc_pollset *pollset);
|
||||
|
||||
#ifdef GRPC_STREAM_REFCOUNT_DEBUG
|
||||
#define grpc_call_stack_ref(call_stack, reason) \
|
||||
#define GRPC_CALL_STACK_REF(call_stack, reason) \
|
||||
grpc_stream_ref(&(call_stack)->refcount, reason)
|
||||
#define grpc_call_stack_unref(exec_ctx, call_stack, reason) \
|
||||
#define GRPC_CALL_STACK_UNREF(exec_ctx, call_stack, reason) \
|
||||
grpc_stream_unref(exec_ctx, &(call_stack)->refcount, reason)
|
||||
#define GRPC_CHANNEL_STACK_REF(channel_stack, reason) \
|
||||
grpc_stream_ref(&(channel_stack)->refcount, reason)
|
||||
#define GRPC_CHANNEL_STACK_UNREF(exec_ctx, channel_stack, reason) \
|
||||
grpc_stream_unref(exec_ctx, &(channel_stack)->refcount, reason)
|
||||
#else
|
||||
#define grpc_call_stack_ref(call_stack) grpc_stream_ref(&(call_stack)->refcount)
|
||||
#define grpc_call_stack_unref(exec_ctx, call_stack) \
|
||||
#define GRPC_CALL_STACK_REF(call_stack, reason) \
|
||||
grpc_stream_ref(&(call_stack)->refcount)
|
||||
#define GRPC_CALL_STACK_UNREF(exec_ctx, call_stack, reason) \
|
||||
grpc_stream_unref(exec_ctx, &(call_stack)->refcount)
|
||||
#define GRPC_CHANNEL_STACK_REF(channel_stack, reason) \
|
||||
grpc_stream_ref(&(channel_stack)->refcount)
|
||||
#define GRPC_CHANNEL_STACK_UNREF(exec_ctx, channel_stack, reason) \
|
||||
grpc_stream_unref(exec_ctx, &(channel_stack)->refcount)
|
||||
#endif
|
||||
|
||||
/* Destroy a call stack */
|
||||
|
|
|
|||
|
|
@ -55,17 +55,10 @@
|
|||
typedef grpc_subchannel_call_holder call_data;
|
||||
|
||||
typedef struct client_channel_channel_data {
|
||||
/** metadata context for this channel */
|
||||
grpc_mdctx *mdctx;
|
||||
/** resolver for this channel */
|
||||
grpc_resolver *resolver;
|
||||
/** have we started resolving this channel */
|
||||
int started_resolving;
|
||||
/** master channel - the grpc_channel instance that ultimately owns
|
||||
this channel_data via its channel stack.
|
||||
We occasionally use this to bump the refcount on the master channel
|
||||
to keep ourselves alive through an asynchronous operation. */
|
||||
grpc_channel *master;
|
||||
|
||||
/** mutex protecting client configuration, including all
|
||||
variables below in this data structure */
|
||||
|
|
@ -83,8 +76,10 @@ typedef struct client_channel_channel_data {
|
|||
grpc_connectivity_state_tracker state_tracker;
|
||||
/** when an lb_policy arrives, should we try to exit idle */
|
||||
int exit_idle_when_lb_policy_arrives;
|
||||
/** pollset_set of interested parties in a new connection */
|
||||
grpc_pollset_set pollset_set;
|
||||
/** owning stack */
|
||||
grpc_channel_stack *owning_stack;
|
||||
/** interested parties */
|
||||
grpc_pollset_set interested_parties;
|
||||
} channel_data;
|
||||
|
||||
/** We create one watcher for each new lb_policy that is returned from a
|
||||
|
|
@ -105,9 +100,7 @@ typedef struct {
|
|||
} waiting_call;
|
||||
|
||||
static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
|
||||
channel_data *chand = elem->channel_data;
|
||||
return grpc_subchannel_call_holder_get_peer(exec_ctx, elem->call_data,
|
||||
chand->master);
|
||||
return grpc_subchannel_call_holder_get_peer(exec_ctx, elem->call_data);
|
||||
}
|
||||
|
||||
static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
|
||||
|
|
@ -123,10 +116,18 @@ static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
|
|||
|
||||
static void on_lb_policy_state_changed_locked(
|
||||
grpc_exec_ctx *exec_ctx, lb_policy_connectivity_watcher *w) {
|
||||
grpc_connectivity_state publish_state = w->state;
|
||||
/* check if the notification is for a stale policy */
|
||||
if (w->lb_policy != w->chand->lb_policy) return;
|
||||
|
||||
grpc_connectivity_state_set(exec_ctx, &w->chand->state_tracker, w->state,
|
||||
if (publish_state == GRPC_CHANNEL_FATAL_FAILURE &&
|
||||
w->chand->resolver != NULL) {
|
||||
publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
|
||||
grpc_resolver_channel_saw_error(exec_ctx, w->chand->resolver);
|
||||
GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
|
||||
w->chand->lb_policy = NULL;
|
||||
}
|
||||
grpc_connectivity_state_set(exec_ctx, &w->chand->state_tracker, publish_state,
|
||||
"lb_changed");
|
||||
if (w->state != GRPC_CHANNEL_FATAL_FAILURE) {
|
||||
watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
|
||||
|
|
@ -141,7 +142,7 @@ static void on_lb_policy_state_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
on_lb_policy_state_changed_locked(exec_ctx, w);
|
||||
gpr_mu_unlock(&w->chand->mu_config);
|
||||
|
||||
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, w->chand->master, "watch_lb_policy");
|
||||
GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
|
||||
gpr_free(w);
|
||||
}
|
||||
|
||||
|
|
@ -149,7 +150,7 @@ static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
|
|||
grpc_lb_policy *lb_policy,
|
||||
grpc_connectivity_state current_state) {
|
||||
lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
|
||||
GRPC_CHANNEL_INTERNAL_REF(chand->master, "watch_lb_policy");
|
||||
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
|
||||
|
||||
w->chand = chand;
|
||||
grpc_closure_init(&w->on_changed, on_lb_policy_state_changed, w);
|
||||
|
|
@ -181,6 +182,11 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
|
||||
chand->incoming_configuration = NULL;
|
||||
|
||||
if (lb_policy != NULL) {
|
||||
grpc_pollset_set_add_pollset_set(exec_ctx, &lb_policy->interested_parties,
|
||||
&chand->interested_parties);
|
||||
}
|
||||
|
||||
gpr_mu_lock(&chand->mu_config);
|
||||
old_lb_policy = chand->lb_policy;
|
||||
chand->lb_policy = lb_policy;
|
||||
|
|
@ -202,7 +208,7 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
watch_lb_policy(exec_ctx, chand, lb_policy, state);
|
||||
}
|
||||
gpr_mu_unlock(&chand->mu_config);
|
||||
GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
|
||||
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
|
||||
grpc_resolver_next(exec_ctx, resolver, &chand->incoming_configuration,
|
||||
&chand->on_config_changed);
|
||||
GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel-next");
|
||||
|
|
@ -224,7 +230,9 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
}
|
||||
|
||||
if (old_lb_policy != NULL) {
|
||||
grpc_lb_policy_shutdown(exec_ctx, old_lb_policy);
|
||||
grpc_pollset_set_del_pollset_set(exec_ctx,
|
||||
&old_lb_policy->interested_parties,
|
||||
&chand->interested_parties);
|
||||
GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
|
||||
}
|
||||
|
||||
|
|
@ -232,20 +240,22 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
|
||||
}
|
||||
|
||||
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->master, "resolver");
|
||||
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
|
||||
}
|
||||
|
||||
static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *elem,
|
||||
grpc_transport_op *op) {
|
||||
grpc_lb_policy *lb_policy = NULL;
|
||||
channel_data *chand = elem->channel_data;
|
||||
grpc_resolver *destroy_resolver = NULL;
|
||||
|
||||
grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, 1);
|
||||
|
||||
GPR_ASSERT(op->set_accept_stream == NULL);
|
||||
GPR_ASSERT(op->bind_pollset == NULL);
|
||||
if (op->bind_pollset != NULL) {
|
||||
grpc_pollset_set_add_pollset(exec_ctx, &chand->interested_parties,
|
||||
op->bind_pollset);
|
||||
}
|
||||
|
||||
gpr_mu_lock(&chand->mu_config);
|
||||
if (op->on_connectivity_state_change != NULL) {
|
||||
|
|
@ -256,9 +266,14 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
|
|||
op->connectivity_state = NULL;
|
||||
}
|
||||
|
||||
lb_policy = chand->lb_policy;
|
||||
if (lb_policy) {
|
||||
GRPC_LB_POLICY_REF(lb_policy, "broadcast");
|
||||
if (op->send_ping != NULL) {
|
||||
if (chand->lb_policy == NULL) {
|
||||
grpc_exec_ctx_enqueue(exec_ctx, op->send_ping, 0);
|
||||
} else {
|
||||
grpc_lb_policy_ping_one(exec_ctx, chand->lb_policy, op->send_ping);
|
||||
op->bind_pollset = NULL;
|
||||
}
|
||||
op->send_ping = NULL;
|
||||
}
|
||||
|
||||
if (op->disconnect && chand->resolver != NULL) {
|
||||
|
|
@ -267,7 +282,9 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
|
|||
destroy_resolver = chand->resolver;
|
||||
chand->resolver = NULL;
|
||||
if (chand->lb_policy != NULL) {
|
||||
grpc_lb_policy_shutdown(exec_ctx, chand->lb_policy);
|
||||
grpc_pollset_set_del_pollset_set(exec_ctx,
|
||||
&chand->lb_policy->interested_parties,
|
||||
&chand->interested_parties);
|
||||
GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
|
||||
chand->lb_policy = NULL;
|
||||
}
|
||||
|
|
@ -278,16 +295,11 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
|
|||
grpc_resolver_shutdown(exec_ctx, destroy_resolver);
|
||||
GRPC_RESOLVER_UNREF(exec_ctx, destroy_resolver, "channel");
|
||||
}
|
||||
|
||||
if (lb_policy) {
|
||||
grpc_lb_policy_broadcast(exec_ctx, lb_policy, op);
|
||||
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "broadcast");
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
grpc_metadata_batch *initial_metadata;
|
||||
grpc_subchannel **subchannel;
|
||||
grpc_connected_subchannel **connected_subchannel;
|
||||
grpc_closure *on_ready;
|
||||
grpc_call_element *elem;
|
||||
grpc_closure closure;
|
||||
|
|
@ -295,17 +307,17 @@ typedef struct {
|
|||
|
||||
static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
|
||||
grpc_metadata_batch *initial_metadata,
|
||||
grpc_subchannel **subchannel,
|
||||
grpc_connected_subchannel **connected_subchannel,
|
||||
grpc_closure *on_ready);
|
||||
|
||||
static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, int success) {
|
||||
continue_picking_args *cpa = arg;
|
||||
if (!success) {
|
||||
grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, 0);
|
||||
} else if (cpa->subchannel == NULL) {
|
||||
} else if (cpa->connected_subchannel == NULL) {
|
||||
/* cancelled, do nothing */
|
||||
} else if (cc_pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata,
|
||||
cpa->subchannel, cpa->on_ready)) {
|
||||
cpa->connected_subchannel, cpa->on_ready)) {
|
||||
grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, 1);
|
||||
}
|
||||
gpr_free(cpa);
|
||||
|
|
@ -313,7 +325,7 @@ static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, int success) {
|
|||
|
||||
static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
|
||||
grpc_metadata_batch *initial_metadata,
|
||||
grpc_subchannel **subchannel,
|
||||
grpc_connected_subchannel **connected_subchannel,
|
||||
grpc_closure *on_ready) {
|
||||
grpc_call_element *elem = elemp;
|
||||
channel_data *chand = elem->channel_data;
|
||||
|
|
@ -321,18 +333,19 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
|
|||
continue_picking_args *cpa;
|
||||
grpc_closure *closure;
|
||||
|
||||
GPR_ASSERT(subchannel);
|
||||
GPR_ASSERT(connected_subchannel);
|
||||
|
||||
gpr_mu_lock(&chand->mu_config);
|
||||
if (initial_metadata == NULL) {
|
||||
if (chand->lb_policy != NULL) {
|
||||
grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy, subchannel);
|
||||
grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy,
|
||||
connected_subchannel);
|
||||
}
|
||||
for (closure = chand->waiting_for_config_closures.head; closure != NULL;
|
||||
closure = grpc_closure_next(closure)) {
|
||||
cpa = closure->cb_arg;
|
||||
if (cpa->subchannel == subchannel) {
|
||||
cpa->subchannel = NULL;
|
||||
if (cpa->connected_subchannel == connected_subchannel) {
|
||||
cpa->connected_subchannel = NULL;
|
||||
grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -340,21 +353,22 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
|
|||
return 1;
|
||||
}
|
||||
if (chand->lb_policy != NULL) {
|
||||
int r = grpc_lb_policy_pick(exec_ctx, chand->lb_policy, calld->pollset,
|
||||
initial_metadata, subchannel, on_ready);
|
||||
int r =
|
||||
grpc_lb_policy_pick(exec_ctx, chand->lb_policy, calld->pollset,
|
||||
initial_metadata, connected_subchannel, on_ready);
|
||||
gpr_mu_unlock(&chand->mu_config);
|
||||
return r;
|
||||
}
|
||||
if (chand->resolver != NULL && !chand->started_resolving) {
|
||||
chand->started_resolving = 1;
|
||||
GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
|
||||
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
|
||||
grpc_resolver_next(exec_ctx, chand->resolver,
|
||||
&chand->incoming_configuration,
|
||||
&chand->on_config_changed);
|
||||
}
|
||||
cpa = gpr_malloc(sizeof(*cpa));
|
||||
cpa->initial_metadata = initial_metadata;
|
||||
cpa->subchannel = subchannel;
|
||||
cpa->connected_subchannel = connected_subchannel;
|
||||
cpa->on_ready = on_ready;
|
||||
cpa->elem = elem;
|
||||
grpc_closure_init(&cpa->closure, continue_picking, cpa);
|
||||
|
|
@ -366,7 +380,8 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
|
|||
/* Constructor for call_data */
|
||||
static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
|
||||
grpc_call_element_args *args) {
|
||||
grpc_subchannel_call_holder_init(elem->call_data, cc_pick_subchannel, elem);
|
||||
grpc_subchannel_call_holder_init(elem->call_data, cc_pick_subchannel, elem,
|
||||
args->call_stack);
|
||||
}
|
||||
|
||||
/* Destructor for call_data */
|
||||
|
|
@ -387,13 +402,12 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
|
|||
GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
|
||||
|
||||
gpr_mu_init(&chand->mu_config);
|
||||
chand->mdctx = args->metadata_context;
|
||||
chand->master = args->master;
|
||||
grpc_pollset_set_init(&chand->pollset_set);
|
||||
grpc_closure_init(&chand->on_config_changed, cc_on_config_changed, chand);
|
||||
chand->owning_stack = args->channel_stack;
|
||||
|
||||
grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
|
||||
"client_channel");
|
||||
grpc_pollset_set_init(&chand->interested_parties);
|
||||
}
|
||||
|
||||
/* Destructor for channel_data */
|
||||
|
|
@ -406,10 +420,13 @@ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
|
|||
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
|
||||
}
|
||||
if (chand->lb_policy != NULL) {
|
||||
grpc_pollset_set_del_pollset_set(exec_ctx,
|
||||
&chand->lb_policy->interested_parties,
|
||||
&chand->interested_parties);
|
||||
GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
|
||||
}
|
||||
grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
|
||||
grpc_pollset_set_destroy(&chand->pollset_set);
|
||||
grpc_pollset_set_destroy(&chand->interested_parties);
|
||||
gpr_mu_destroy(&chand->mu_config);
|
||||
}
|
||||
|
||||
|
|
@ -438,7 +455,7 @@ void grpc_client_channel_set_resolver(grpc_exec_ctx *exec_ctx,
|
|||
if (!grpc_closure_list_empty(chand->waiting_for_config_closures) ||
|
||||
chand->exit_idle_when_lb_policy_arrives) {
|
||||
chand->started_resolving = 1;
|
||||
GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
|
||||
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
|
||||
grpc_resolver_next(exec_ctx, resolver, &chand->incoming_configuration,
|
||||
&chand->on_config_changed);
|
||||
}
|
||||
|
|
@ -457,7 +474,7 @@ grpc_connectivity_state grpc_client_channel_check_connectivity_state(
|
|||
} else {
|
||||
chand->exit_idle_when_lb_policy_arrives = 1;
|
||||
if (!chand->started_resolving && chand->resolver != NULL) {
|
||||
GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
|
||||
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
|
||||
chand->started_resolving = 1;
|
||||
grpc_resolver_next(exec_ctx, chand->resolver,
|
||||
&chand->incoming_configuration,
|
||||
|
|
@ -469,32 +486,39 @@ grpc_connectivity_state grpc_client_channel_check_connectivity_state(
|
|||
return out;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
channel_data *chand;
|
||||
grpc_pollset *pollset;
|
||||
grpc_closure *on_complete;
|
||||
grpc_closure my_closure;
|
||||
} external_connectivity_watcher;
|
||||
|
||||
static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
|
||||
int iomgr_success) {
|
||||
external_connectivity_watcher *w = arg;
|
||||
grpc_closure *follow_up = w->on_complete;
|
||||
grpc_pollset_set_del_pollset(exec_ctx, &w->chand->interested_parties,
|
||||
w->pollset);
|
||||
GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
|
||||
"external_connectivity_watcher");
|
||||
gpr_free(w);
|
||||
follow_up->cb(exec_ctx, follow_up->cb_arg, iomgr_success);
|
||||
}
|
||||
|
||||
void grpc_client_channel_watch_connectivity_state(
|
||||
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
|
||||
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
|
||||
grpc_connectivity_state *state, grpc_closure *on_complete) {
|
||||
channel_data *chand = elem->channel_data;
|
||||
external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
|
||||
w->chand = chand;
|
||||
w->pollset = pollset;
|
||||
w->on_complete = on_complete;
|
||||
grpc_pollset_set_add_pollset(exec_ctx, &chand->interested_parties, pollset);
|
||||
grpc_closure_init(&w->my_closure, on_external_watch_complete, w);
|
||||
GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
|
||||
"external_connectivity_watcher");
|
||||
gpr_mu_lock(&chand->mu_config);
|
||||
grpc_connectivity_state_notify_on_state_change(
|
||||
exec_ctx, &chand->state_tracker, state, on_complete);
|
||||
exec_ctx, &chand->state_tracker, state, &w->my_closure);
|
||||
gpr_mu_unlock(&chand->mu_config);
|
||||
}
|
||||
|
||||
grpc_pollset_set *grpc_client_channel_get_connecting_pollset_set(
|
||||
grpc_channel_element *elem) {
|
||||
channel_data *chand = elem->channel_data;
|
||||
return &chand->pollset_set;
|
||||
}
|
||||
|
||||
void grpc_client_channel_add_interested_party(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *elem,
|
||||
grpc_pollset *pollset) {
|
||||
channel_data *chand = elem->channel_data;
|
||||
grpc_pollset_set_add_pollset(exec_ctx, &chand->pollset_set, pollset);
|
||||
}
|
||||
|
||||
void grpc_client_channel_del_interested_party(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *elem,
|
||||
grpc_pollset *pollset) {
|
||||
channel_data *chand = elem->channel_data;
|
||||
grpc_pollset_set_del_pollset(exec_ctx, &chand->pollset_set, pollset);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,17 +57,7 @@ grpc_connectivity_state grpc_client_channel_check_connectivity_state(
|
|||
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect);
|
||||
|
||||
void grpc_client_channel_watch_connectivity_state(
|
||||
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
|
||||
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
|
||||
grpc_connectivity_state *state, grpc_closure *on_complete);
|
||||
|
||||
grpc_pollset_set *grpc_client_channel_get_connecting_pollset_set(
|
||||
grpc_channel_element *elem);
|
||||
|
||||
void grpc_client_channel_add_interested_party(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *channel,
|
||||
grpc_pollset *pollset);
|
||||
void grpc_client_channel_del_interested_party(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *channel,
|
||||
grpc_pollset *pollset);
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_CHANNEL_CLIENT_CHANNEL_H */
|
||||
|
|
|
|||
|
|
@ -54,20 +54,17 @@
|
|||
* load-balancing mechanisms meant for communication from within the core. */
|
||||
|
||||
typedef struct client_uchannel_channel_data {
|
||||
/** metadata context for this channel */
|
||||
grpc_mdctx *mdctx;
|
||||
|
||||
/** master channel - the grpc_channel instance that ultimately owns
|
||||
this channel_data via its channel stack.
|
||||
We occasionally use this to bump the refcount on the master channel
|
||||
to keep ourselves alive through an asynchronous operation. */
|
||||
grpc_channel *master;
|
||||
grpc_channel_stack *owning_stack;
|
||||
|
||||
/** connectivity state being tracked */
|
||||
grpc_connectivity_state_tracker state_tracker;
|
||||
|
||||
/** the subchannel wrapped by the microchannel */
|
||||
grpc_subchannel *subchannel;
|
||||
grpc_connected_subchannel *connected_subchannel;
|
||||
|
||||
/** the callback used to stay subscribed to subchannel connectivity
|
||||
* notifications */
|
||||
|
|
@ -87,15 +84,13 @@ static void monitor_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
|
||||
chand->subchannel_connectivity,
|
||||
"uchannel_monitor_subchannel");
|
||||
grpc_subchannel_notify_on_state_change(exec_ctx, chand->subchannel,
|
||||
&chand->subchannel_connectivity,
|
||||
&chand->connectivity_cb);
|
||||
grpc_connected_subchannel_notify_on_state_change(
|
||||
exec_ctx, chand->connected_subchannel, NULL,
|
||||
&chand->subchannel_connectivity, &chand->connectivity_cb);
|
||||
}
|
||||
|
||||
static char *cuc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
|
||||
channel_data *chand = elem->channel_data;
|
||||
return grpc_subchannel_call_holder_get_peer(exec_ctx, elem->call_data,
|
||||
chand->master);
|
||||
return grpc_subchannel_call_holder_get_peer(exec_ctx, elem->call_data);
|
||||
}
|
||||
|
||||
static void cuc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
|
||||
|
|
@ -131,11 +126,11 @@ static void cuc_start_transport_op(grpc_exec_ctx *exec_ctx,
|
|||
|
||||
static int cuc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
|
||||
grpc_metadata_batch *initial_metadata,
|
||||
grpc_subchannel **subchannel,
|
||||
grpc_connected_subchannel **connected_subchannel,
|
||||
grpc_closure *on_ready) {
|
||||
channel_data *chand = arg;
|
||||
GPR_ASSERT(initial_metadata != NULL);
|
||||
*subchannel = chand->subchannel;
|
||||
*connected_subchannel = chand->connected_subchannel;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -143,7 +138,7 @@ static int cuc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
static void cuc_init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
|
||||
grpc_call_element_args *args) {
|
||||
grpc_subchannel_call_holder_init(elem->call_data, cuc_pick_subchannel,
|
||||
elem->channel_data);
|
||||
elem->channel_data, args->call_stack);
|
||||
}
|
||||
|
||||
/* Destructor for call_data */
|
||||
|
|
@ -161,8 +156,7 @@ static void cuc_init_channel_elem(grpc_exec_ctx *exec_ctx,
|
|||
grpc_closure_init(&chand->connectivity_cb, monitor_subchannel, chand);
|
||||
GPR_ASSERT(args->is_last);
|
||||
GPR_ASSERT(elem->filter == &grpc_client_uchannel_filter);
|
||||
chand->mdctx = args->metadata_context;
|
||||
chand->master = args->master;
|
||||
chand->owning_stack = args->channel_stack;
|
||||
grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
|
||||
"client_uchannel");
|
||||
gpr_mu_init(&chand->mu_state);
|
||||
|
|
@ -172,10 +166,14 @@ static void cuc_init_channel_elem(grpc_exec_ctx *exec_ctx,
|
|||
static void cuc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *elem) {
|
||||
channel_data *chand = elem->channel_data;
|
||||
grpc_subchannel_state_change_unsubscribe(exec_ctx, chand->subchannel,
|
||||
&chand->connectivity_cb);
|
||||
/* cancel subscription */
|
||||
grpc_connected_subchannel_notify_on_state_change(
|
||||
exec_ctx, chand->connected_subchannel, NULL, NULL,
|
||||
&chand->connectivity_cb);
|
||||
grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
|
||||
gpr_mu_destroy(&chand->mu_state);
|
||||
GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, chand->connected_subchannel,
|
||||
"uchannel");
|
||||
}
|
||||
|
||||
static void cuc_set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
|
||||
|
|
@ -195,23 +193,14 @@ grpc_connectivity_state grpc_client_uchannel_check_connectivity_state(
|
|||
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
|
||||
channel_data *chand = elem->channel_data;
|
||||
grpc_connectivity_state out;
|
||||
out = grpc_connectivity_state_check(&chand->state_tracker);
|
||||
gpr_mu_lock(&chand->mu_state);
|
||||
if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
|
||||
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
|
||||
GRPC_CHANNEL_CONNECTING,
|
||||
"uchannel_connecting_changed");
|
||||
chand->subchannel_connectivity = out;
|
||||
grpc_subchannel_notify_on_state_change(exec_ctx, chand->subchannel,
|
||||
&chand->subchannel_connectivity,
|
||||
&chand->connectivity_cb);
|
||||
}
|
||||
out = grpc_connectivity_state_check(&chand->state_tracker);
|
||||
gpr_mu_unlock(&chand->mu_state);
|
||||
return out;
|
||||
}
|
||||
|
||||
void grpc_client_uchannel_watch_connectivity_state(
|
||||
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
|
||||
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
|
||||
grpc_connectivity_state *state, grpc_closure *on_complete) {
|
||||
channel_data *chand = elem->channel_data;
|
||||
gpr_mu_lock(&chand->mu_state);
|
||||
|
|
@ -220,45 +209,14 @@ void grpc_client_uchannel_watch_connectivity_state(
|
|||
gpr_mu_unlock(&chand->mu_state);
|
||||
}
|
||||
|
||||
grpc_pollset_set *grpc_client_uchannel_get_connecting_pollset_set(
|
||||
grpc_channel_element *elem) {
|
||||
channel_data *chand = elem->channel_data;
|
||||
grpc_channel_element *parent_elem;
|
||||
gpr_mu_lock(&chand->mu_state);
|
||||
parent_elem = grpc_channel_stack_last_element(grpc_channel_get_channel_stack(
|
||||
grpc_subchannel_get_master(chand->subchannel)));
|
||||
gpr_mu_unlock(&chand->mu_state);
|
||||
return grpc_client_channel_get_connecting_pollset_set(parent_elem);
|
||||
}
|
||||
|
||||
void grpc_client_uchannel_add_interested_party(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *elem,
|
||||
grpc_pollset *pollset) {
|
||||
grpc_pollset_set *master_pollset_set =
|
||||
grpc_client_uchannel_get_connecting_pollset_set(elem);
|
||||
grpc_pollset_set_add_pollset(exec_ctx, master_pollset_set, pollset);
|
||||
}
|
||||
|
||||
void grpc_client_uchannel_del_interested_party(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *elem,
|
||||
grpc_pollset *pollset) {
|
||||
grpc_pollset_set *master_pollset_set =
|
||||
grpc_client_uchannel_get_connecting_pollset_set(elem);
|
||||
grpc_pollset_set_del_pollset(exec_ctx, master_pollset_set, pollset);
|
||||
}
|
||||
|
||||
grpc_channel *grpc_client_uchannel_create(grpc_subchannel *subchannel,
|
||||
grpc_channel_args *args) {
|
||||
grpc_channel *channel = NULL;
|
||||
#define MAX_FILTERS 3
|
||||
const grpc_channel_filter *filters[MAX_FILTERS];
|
||||
grpc_mdctx *mdctx = grpc_subchannel_get_mdctx(subchannel);
|
||||
grpc_channel *master = grpc_subchannel_get_master(subchannel);
|
||||
char *target = grpc_channel_get_target(master);
|
||||
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
|
||||
size_t n = 0;
|
||||
|
||||
grpc_mdctx_ref(mdctx);
|
||||
if (grpc_channel_args_is_census_enabled(args)) {
|
||||
filters[n++] = &grpc_client_census_filter;
|
||||
}
|
||||
|
|
@ -266,20 +224,20 @@ grpc_channel *grpc_client_uchannel_create(grpc_subchannel *subchannel,
|
|||
filters[n++] = &grpc_client_uchannel_filter;
|
||||
GPR_ASSERT(n <= MAX_FILTERS);
|
||||
|
||||
channel = grpc_channel_create_from_filters(&exec_ctx, target, filters, n,
|
||||
args, mdctx, 1);
|
||||
channel =
|
||||
grpc_channel_create_from_filters(&exec_ctx, NULL, filters, n, args, 1);
|
||||
|
||||
gpr_free(target);
|
||||
return channel;
|
||||
}
|
||||
|
||||
void grpc_client_uchannel_set_subchannel(grpc_channel *uchannel,
|
||||
grpc_subchannel *subchannel) {
|
||||
void grpc_client_uchannel_set_connected_subchannel(
|
||||
grpc_channel *uchannel, grpc_connected_subchannel *connected_subchannel) {
|
||||
grpc_channel_element *elem =
|
||||
grpc_channel_stack_last_element(grpc_channel_get_channel_stack(uchannel));
|
||||
channel_data *chand = elem->channel_data;
|
||||
GPR_ASSERT(elem->filter == &grpc_client_uchannel_filter);
|
||||
gpr_mu_lock(&chand->mu_state);
|
||||
chand->subchannel = subchannel;
|
||||
chand->connected_subchannel = connected_subchannel;
|
||||
GRPC_CONNECTED_SUBCHANNEL_REF(connected_subchannel, "uchannel");
|
||||
gpr_mu_unlock(&chand->mu_state);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,23 +48,13 @@ grpc_connectivity_state grpc_client_uchannel_check_connectivity_state(
|
|||
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect);
|
||||
|
||||
void grpc_client_uchannel_watch_connectivity_state(
|
||||
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
|
||||
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
|
||||
grpc_connectivity_state *state, grpc_closure *on_complete);
|
||||
|
||||
grpc_pollset_set *grpc_client_uchannel_get_connecting_pollset_set(
|
||||
grpc_channel_element *elem);
|
||||
|
||||
void grpc_client_uchannel_add_interested_party(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *channel,
|
||||
grpc_pollset *pollset);
|
||||
void grpc_client_uchannel_del_interested_party(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *channel,
|
||||
grpc_pollset *pollset);
|
||||
|
||||
grpc_channel *grpc_client_uchannel_create(grpc_subchannel *subchannel,
|
||||
grpc_channel_args *args);
|
||||
|
||||
void grpc_client_uchannel_set_subchannel(grpc_channel *uchannel,
|
||||
grpc_subchannel *subchannel);
|
||||
void grpc_client_uchannel_set_connected_subchannel(
|
||||
grpc_channel *uchannel, grpc_connected_subchannel *connected_subchannel);
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_CHANNEL_CLIENT_MICROCHANNEL_H */
|
||||
|
|
|
|||
|
|
@ -39,11 +39,13 @@
|
|||
#include <grpc/support/log.h>
|
||||
#include <grpc/support/slice_buffer.h>
|
||||
|
||||
#include "src/core/channel/compress_filter.h"
|
||||
#include "src/core/channel/channel_args.h"
|
||||
#include "src/core/profiling/timers.h"
|
||||
#include "src/core/channel/compress_filter.h"
|
||||
#include "src/core/compression/algorithm_metadata.h"
|
||||
#include "src/core/compression/message_compress.h"
|
||||
#include "src/core/profiling/timers.h"
|
||||
#include "src/core/support/string.h"
|
||||
#include "src/core/transport/static_metadata.h"
|
||||
|
||||
typedef struct call_data {
|
||||
gpr_slice_buffer slices; /**< Buffers up input slices to be compressed */
|
||||
|
|
@ -67,20 +69,12 @@ typedef struct call_data {
|
|||
} call_data;
|
||||
|
||||
typedef struct channel_data {
|
||||
/** Metadata key for the incoming (requested) compression algorithm */
|
||||
grpc_mdstr *mdstr_request_compression_algorithm_key;
|
||||
/** Metadata key for the outgoing (used) compression algorithm */
|
||||
grpc_mdstr *mdstr_outgoing_compression_algorithm_key;
|
||||
/** Metadata key for the accepted encodings */
|
||||
grpc_mdstr *mdstr_compression_capabilities_key;
|
||||
/** Precomputed metadata elements for all available compression algorithms */
|
||||
grpc_mdelem *mdelem_compression_algorithms[GRPC_COMPRESS_ALGORITHMS_COUNT];
|
||||
/** Precomputed metadata elements for the accepted encodings */
|
||||
grpc_mdelem *mdelem_accept_encoding;
|
||||
/** The default, channel-level, compression algorithm */
|
||||
grpc_compression_algorithm default_compression_algorithm;
|
||||
/** Compression options for the channel */
|
||||
grpc_compression_options compression_options;
|
||||
/** Supported compression algorithms */
|
||||
gpr_uint32 supported_compression_algorithms;
|
||||
} channel_data;
|
||||
|
||||
/** For each \a md element from the incoming metadata, filter out the entry for
|
||||
|
|
@ -91,7 +85,7 @@ static grpc_mdelem *compression_md_filter(void *user_data, grpc_mdelem *md) {
|
|||
call_data *calld = elem->call_data;
|
||||
channel_data *channeld = elem->channel_data;
|
||||
|
||||
if (md->key == channeld->mdstr_request_compression_algorithm_key) {
|
||||
if (md->key == GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST) {
|
||||
const char *md_c_str = grpc_mdstr_as_c_string(md->value);
|
||||
if (!grpc_compression_algorithm_parse(md_c_str, strlen(md_c_str),
|
||||
&calld->compression_algorithm)) {
|
||||
|
|
@ -147,14 +141,13 @@ static void process_send_initial_metadata(
|
|||
/* hint compression algorithm */
|
||||
grpc_metadata_batch_add_tail(
|
||||
initial_metadata, &calld->compression_algorithm_storage,
|
||||
GRPC_MDELEM_REF(
|
||||
channeld
|
||||
->mdelem_compression_algorithms[calld->compression_algorithm]));
|
||||
grpc_compression_encoding_mdelem(calld->compression_algorithm));
|
||||
|
||||
/* convey supported compression algorithms */
|
||||
grpc_metadata_batch_add_tail(
|
||||
initial_metadata, &calld->accept_encoding_storage,
|
||||
GRPC_MDELEM_REF(channeld->mdelem_accept_encoding));
|
||||
grpc_metadata_batch_add_tail(initial_metadata,
|
||||
&calld->accept_encoding_storage,
|
||||
GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(
|
||||
channeld->supported_compression_algorithms));
|
||||
}
|
||||
|
||||
static void continue_send_message(grpc_exec_ctx *exec_ctx,
|
||||
|
|
@ -266,10 +259,6 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
|
|||
grpc_channel_element_args *args) {
|
||||
channel_data *channeld = elem->channel_data;
|
||||
grpc_compression_algorithm algo_idx;
|
||||
const char *supported_algorithms_names[GRPC_COMPRESS_ALGORITHMS_COUNT - 1];
|
||||
size_t supported_algorithms_idx = 0;
|
||||
char *accept_encoding_str;
|
||||
size_t accept_encoding_str_len;
|
||||
|
||||
grpc_compression_options_init(&channeld->compression_options);
|
||||
channeld->compression_options.enabled_algorithms_bitset =
|
||||
|
|
@ -284,62 +273,22 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
|
|||
channeld->compression_options.default_compression_algorithm =
|
||||
channeld->default_compression_algorithm;
|
||||
|
||||
channeld->mdstr_request_compression_algorithm_key = grpc_mdstr_from_string(
|
||||
args->metadata_context, GRPC_COMPRESS_REQUEST_ALGORITHM_KEY);
|
||||
|
||||
channeld->mdstr_outgoing_compression_algorithm_key =
|
||||
grpc_mdstr_from_string(args->metadata_context, "grpc-encoding");
|
||||
|
||||
channeld->mdstr_compression_capabilities_key =
|
||||
grpc_mdstr_from_string(args->metadata_context, "grpc-accept-encoding");
|
||||
|
||||
channeld->supported_compression_algorithms = 0;
|
||||
for (algo_idx = 0; algo_idx < GRPC_COMPRESS_ALGORITHMS_COUNT; ++algo_idx) {
|
||||
char *algorithm_name;
|
||||
/* skip disabled algorithms */
|
||||
if (grpc_compression_options_is_algorithm_enabled(
|
||||
&channeld->compression_options, algo_idx) == 0) {
|
||||
continue;
|
||||
}
|
||||
GPR_ASSERT(grpc_compression_algorithm_name(algo_idx, &algorithm_name) != 0);
|
||||
channeld->mdelem_compression_algorithms[algo_idx] =
|
||||
grpc_mdelem_from_metadata_strings(
|
||||
args->metadata_context,
|
||||
GRPC_MDSTR_REF(channeld->mdstr_outgoing_compression_algorithm_key),
|
||||
grpc_mdstr_from_string(args->metadata_context, algorithm_name));
|
||||
if (algo_idx > 0) {
|
||||
supported_algorithms_names[supported_algorithms_idx++] = algorithm_name;
|
||||
}
|
||||
channeld->supported_compression_algorithms |= 1u << algo_idx;
|
||||
}
|
||||
|
||||
/* TODO(dgq): gpr_strjoin_sep could be made to work with statically allocated
|
||||
* arrays, as to avoid the heap allocs */
|
||||
accept_encoding_str =
|
||||
gpr_strjoin_sep(supported_algorithms_names, supported_algorithms_idx, ",",
|
||||
&accept_encoding_str_len);
|
||||
|
||||
channeld->mdelem_accept_encoding = grpc_mdelem_from_metadata_strings(
|
||||
args->metadata_context,
|
||||
GRPC_MDSTR_REF(channeld->mdstr_compression_capabilities_key),
|
||||
grpc_mdstr_from_string(args->metadata_context, accept_encoding_str));
|
||||
gpr_free(accept_encoding_str);
|
||||
|
||||
GPR_ASSERT(!args->is_last);
|
||||
}
|
||||
|
||||
/* Destructor for channel data */
|
||||
static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *elem) {
|
||||
channel_data *channeld = elem->channel_data;
|
||||
grpc_compression_algorithm algo_idx;
|
||||
|
||||
GRPC_MDSTR_UNREF(channeld->mdstr_request_compression_algorithm_key);
|
||||
GRPC_MDSTR_UNREF(channeld->mdstr_outgoing_compression_algorithm_key);
|
||||
GRPC_MDSTR_UNREF(channeld->mdstr_compression_capabilities_key);
|
||||
for (algo_idx = 0; algo_idx < GRPC_COMPRESS_ALGORITHMS_COUNT; ++algo_idx) {
|
||||
GRPC_MDELEM_UNREF(channeld->mdelem_compression_algorithms[algo_idx]);
|
||||
}
|
||||
GRPC_MDELEM_UNREF(channeld->mdelem_accept_encoding);
|
||||
}
|
||||
grpc_channel_element *elem) {}
|
||||
|
||||
const grpc_channel_filter grpc_compress_filter = {
|
||||
compress_start_transport_stream_op, grpc_channel_next_op, sizeof(call_data),
|
||||
|
|
|
|||
|
|
@ -89,9 +89,9 @@ static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
|
|||
int r;
|
||||
|
||||
GPR_ASSERT(elem->filter == &grpc_connected_channel_filter);
|
||||
r = grpc_transport_init_stream(exec_ctx, chand->transport,
|
||||
TRANSPORT_STREAM_FROM_CALL_DATA(calld),
|
||||
args->refcount, args->server_transport_data);
|
||||
r = grpc_transport_init_stream(
|
||||
exec_ctx, chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld),
|
||||
&args->call_stack->refcount, args->server_transport_data);
|
||||
GPR_ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,12 +31,13 @@
|
|||
*/
|
||||
|
||||
#include "src/core/channel/http_client_filter.h"
|
||||
#include <string.h>
|
||||
#include <grpc/support/alloc.h>
|
||||
#include <grpc/support/log.h>
|
||||
#include <grpc/support/string_util.h>
|
||||
#include "src/core/support/string.h"
|
||||
#include <string.h>
|
||||
#include "src/core/profiling/timers.h"
|
||||
#include "src/core/support/string.h"
|
||||
#include "src/core/transport/static_metadata.h"
|
||||
|
||||
typedef struct call_data {
|
||||
grpc_linked_mdelem method;
|
||||
|
|
@ -57,12 +58,7 @@ typedef struct call_data {
|
|||
} call_data;
|
||||
|
||||
typedef struct channel_data {
|
||||
grpc_mdelem *te_trailers;
|
||||
grpc_mdelem *method;
|
||||
grpc_mdelem *scheme;
|
||||
grpc_mdelem *content_type;
|
||||
grpc_mdelem *status;
|
||||
/** complete user agent mdelem */
|
||||
grpc_mdelem *static_scheme;
|
||||
grpc_mdelem *user_agent;
|
||||
} channel_data;
|
||||
|
||||
|
|
@ -73,14 +69,12 @@ typedef struct {
|
|||
|
||||
static grpc_mdelem *client_recv_filter(void *user_data, grpc_mdelem *md) {
|
||||
client_recv_filter_args *a = user_data;
|
||||
grpc_call_element *elem = a->elem;
|
||||
channel_data *channeld = elem->channel_data;
|
||||
if (md == channeld->status) {
|
||||
if (md == GRPC_MDELEM_STATUS_200) {
|
||||
return NULL;
|
||||
} else if (md->key == channeld->status->key) {
|
||||
grpc_call_element_send_cancel(a->exec_ctx, elem);
|
||||
} else if (md->key == GRPC_MDSTR_STATUS) {
|
||||
grpc_call_element_send_cancel(a->exec_ctx, a->elem);
|
||||
return NULL;
|
||||
} else if (md->key == channeld->content_type->key) {
|
||||
} else if (md->key == GRPC_MDSTR_CONTENT_TYPE) {
|
||||
return NULL;
|
||||
}
|
||||
return md;
|
||||
|
|
@ -98,14 +92,12 @@ static void hc_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, int success) {
|
|||
}
|
||||
|
||||
static grpc_mdelem *client_strip_filter(void *user_data, grpc_mdelem *md) {
|
||||
grpc_call_element *elem = user_data;
|
||||
channel_data *channeld = elem->channel_data;
|
||||
/* eat the things we'd like to set ourselves */
|
||||
if (md->key == channeld->method->key) return NULL;
|
||||
if (md->key == channeld->scheme->key) return NULL;
|
||||
if (md->key == channeld->te_trailers->key) return NULL;
|
||||
if (md->key == channeld->content_type->key) return NULL;
|
||||
if (md->key == channeld->user_agent->key) return NULL;
|
||||
if (md->key == GRPC_MDSTR_METHOD) return NULL;
|
||||
if (md->key == GRPC_MDSTR_SCHEME) return NULL;
|
||||
if (md->key == GRPC_MDSTR_TE) return NULL;
|
||||
if (md->key == GRPC_MDSTR_CONTENT_TYPE) return NULL;
|
||||
if (md->key == GRPC_MDSTR_USER_AGENT) return NULL;
|
||||
return md;
|
||||
}
|
||||
|
||||
|
|
@ -120,14 +112,14 @@ static void hc_mutate_op(grpc_call_element *elem,
|
|||
/* Send : prefixed headers, which have to be before any application
|
||||
layer headers. */
|
||||
grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->method,
|
||||
GRPC_MDELEM_REF(channeld->method));
|
||||
GRPC_MDELEM_METHOD_POST);
|
||||
grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->scheme,
|
||||
GRPC_MDELEM_REF(channeld->scheme));
|
||||
channeld->static_scheme);
|
||||
grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->te_trailers,
|
||||
GRPC_MDELEM_REF(channeld->te_trailers));
|
||||
grpc_metadata_batch_add_tail(op->send_initial_metadata,
|
||||
&calld->content_type,
|
||||
GRPC_MDELEM_REF(channeld->content_type));
|
||||
GRPC_MDELEM_TE_TRAILERS);
|
||||
grpc_metadata_batch_add_tail(
|
||||
op->send_initial_metadata, &calld->content_type,
|
||||
GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC);
|
||||
grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->user_agent,
|
||||
GRPC_MDELEM_REF(channeld->user_agent));
|
||||
}
|
||||
|
|
@ -162,21 +154,28 @@ static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
|
|||
static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
|
||||
grpc_call_element *elem) {}
|
||||
|
||||
static const char *scheme_from_args(const grpc_channel_args *args) {
|
||||
static grpc_mdelem *scheme_from_args(const grpc_channel_args *args) {
|
||||
unsigned i;
|
||||
size_t j;
|
||||
grpc_mdelem *valid_schemes[] = {GRPC_MDELEM_SCHEME_HTTP,
|
||||
GRPC_MDELEM_SCHEME_HTTPS};
|
||||
if (args != NULL) {
|
||||
for (i = 0; i < args->num_args; ++i) {
|
||||
if (args->args[i].type == GRPC_ARG_STRING &&
|
||||
strcmp(args->args[i].key, GRPC_ARG_HTTP2_SCHEME) == 0) {
|
||||
return args->args[i].value.string;
|
||||
for (j = 0; j < GPR_ARRAY_SIZE(valid_schemes); j++) {
|
||||
if (0 == strcmp(grpc_mdstr_as_c_string(valid_schemes[j]->value),
|
||||
args->args[i].value.string)) {
|
||||
return valid_schemes[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "http";
|
||||
return GRPC_MDELEM_SCHEME_HTTP;
|
||||
}
|
||||
|
||||
static grpc_mdstr *user_agent_from_args(grpc_mdctx *mdctx,
|
||||
const grpc_channel_args *args) {
|
||||
static grpc_mdstr *user_agent_from_args(const grpc_channel_args *args) {
|
||||
gpr_strvec v;
|
||||
size_t i;
|
||||
int is_first = 1;
|
||||
|
|
@ -218,7 +217,7 @@ static grpc_mdstr *user_agent_from_args(grpc_mdctx *mdctx,
|
|||
|
||||
tmp = gpr_strvec_flatten(&v, NULL);
|
||||
gpr_strvec_destroy(&v);
|
||||
result = grpc_mdstr_from_string(mdctx, tmp);
|
||||
result = grpc_mdstr_from_string(tmp);
|
||||
gpr_free(tmp);
|
||||
|
||||
return result;
|
||||
|
|
@ -228,43 +227,18 @@ static grpc_mdstr *user_agent_from_args(grpc_mdctx *mdctx,
|
|||
static void init_channel_elem(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *elem,
|
||||
grpc_channel_element_args *args) {
|
||||
/* grab pointers to our data from the channel element */
|
||||
channel_data *channeld = elem->channel_data;
|
||||
|
||||
/* The first and the last filters tend to be implemented differently to
|
||||
handle the case that there's no 'next' filter to call on the up or down
|
||||
path */
|
||||
channel_data *chand = elem->channel_data;
|
||||
GPR_ASSERT(!args->is_last);
|
||||
|
||||
/* initialize members */
|
||||
channeld->te_trailers =
|
||||
grpc_mdelem_from_strings(args->metadata_context, "te", "trailers");
|
||||
channeld->method =
|
||||
grpc_mdelem_from_strings(args->metadata_context, ":method", "POST");
|
||||
channeld->scheme = grpc_mdelem_from_strings(
|
||||
args->metadata_context, ":scheme", scheme_from_args(args->channel_args));
|
||||
channeld->content_type = grpc_mdelem_from_strings(
|
||||
args->metadata_context, "content-type", "application/grpc");
|
||||
channeld->status =
|
||||
grpc_mdelem_from_strings(args->metadata_context, ":status", "200");
|
||||
channeld->user_agent = grpc_mdelem_from_metadata_strings(
|
||||
args->metadata_context,
|
||||
grpc_mdstr_from_string(args->metadata_context, "user-agent"),
|
||||
user_agent_from_args(args->metadata_context, args->channel_args));
|
||||
chand->static_scheme = scheme_from_args(args->channel_args);
|
||||
chand->user_agent = grpc_mdelem_from_metadata_strings(
|
||||
GRPC_MDSTR_USER_AGENT, user_agent_from_args(args->channel_args));
|
||||
}
|
||||
|
||||
/* Destructor for channel data */
|
||||
static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *elem) {
|
||||
/* grab pointers to our data from the channel element */
|
||||
channel_data *channeld = elem->channel_data;
|
||||
|
||||
GRPC_MDELEM_UNREF(channeld->te_trailers);
|
||||
GRPC_MDELEM_UNREF(channeld->method);
|
||||
GRPC_MDELEM_UNREF(channeld->scheme);
|
||||
GRPC_MDELEM_UNREF(channeld->content_type);
|
||||
GRPC_MDELEM_UNREF(channeld->status);
|
||||
GRPC_MDELEM_UNREF(channeld->user_agent);
|
||||
channel_data *chand = elem->channel_data;
|
||||
GRPC_MDELEM_UNREF(chand->user_agent);
|
||||
}
|
||||
|
||||
const grpc_channel_filter grpc_http_client_filter = {
|
||||
|
|
|
|||
|
|
@ -33,10 +33,11 @@
|
|||
|
||||
#include "src/core/channel/http_server_filter.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <grpc/support/alloc.h>
|
||||
#include <grpc/support/log.h>
|
||||
#include <string.h>
|
||||
#include "src/core/profiling/timers.h"
|
||||
#include "src/core/transport/static_metadata.h"
|
||||
|
||||
typedef struct call_data {
|
||||
gpr_uint8 seen_path;
|
||||
|
|
@ -57,22 +58,7 @@ typedef struct call_data {
|
|||
grpc_closure hs_on_recv;
|
||||
} call_data;
|
||||
|
||||
typedef struct channel_data {
|
||||
grpc_mdelem *te_trailers;
|
||||
grpc_mdelem *method_post;
|
||||
grpc_mdelem *http_scheme;
|
||||
grpc_mdelem *https_scheme;
|
||||
/* TODO(klempner): Remove this once we stop using it */
|
||||
grpc_mdelem *grpc_scheme;
|
||||
grpc_mdelem *content_type;
|
||||
grpc_mdelem *status_ok;
|
||||
grpc_mdelem *status_not_found;
|
||||
grpc_mdstr *path_key;
|
||||
grpc_mdstr *authority_key;
|
||||
grpc_mdstr *host_key;
|
||||
|
||||
grpc_mdctx *mdctx;
|
||||
} channel_data;
|
||||
typedef struct channel_data { gpr_uint8 unused; } channel_data;
|
||||
|
||||
typedef struct {
|
||||
grpc_call_element *elem;
|
||||
|
|
@ -82,25 +68,24 @@ typedef struct {
|
|||
static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
|
||||
server_filter_args *a = user_data;
|
||||
grpc_call_element *elem = a->elem;
|
||||
channel_data *channeld = elem->channel_data;
|
||||
call_data *calld = elem->call_data;
|
||||
|
||||
/* Check if it is one of the headers we care about. */
|
||||
if (md == channeld->te_trailers || md == channeld->method_post ||
|
||||
md == channeld->http_scheme || md == channeld->https_scheme ||
|
||||
md == channeld->grpc_scheme || md == channeld->content_type) {
|
||||
if (md == GRPC_MDELEM_TE_TRAILERS || md == GRPC_MDELEM_METHOD_POST ||
|
||||
md == GRPC_MDELEM_SCHEME_HTTP || md == GRPC_MDELEM_SCHEME_HTTPS ||
|
||||
md == GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC) {
|
||||
/* swallow it */
|
||||
if (md == channeld->method_post) {
|
||||
if (md == GRPC_MDELEM_METHOD_POST) {
|
||||
calld->seen_post = 1;
|
||||
} else if (md->key == channeld->http_scheme->key) {
|
||||
} else if (md->key == GRPC_MDSTR_SCHEME) {
|
||||
calld->seen_scheme = 1;
|
||||
} else if (md == channeld->te_trailers) {
|
||||
} else if (md == GRPC_MDELEM_TE_TRAILERS) {
|
||||
calld->seen_te_trailers = 1;
|
||||
}
|
||||
/* TODO(klempner): Track that we've seen all the headers we should
|
||||
require */
|
||||
return NULL;
|
||||
} else if (md->key == channeld->content_type->key) {
|
||||
} else if (md->key == GRPC_MDSTR_CONTENT_TYPE) {
|
||||
if (strncmp(grpc_mdstr_as_c_string(md->value), "application/grpc+", 17) ==
|
||||
0) {
|
||||
/* Although the C implementation doesn't (currently) generate them,
|
||||
|
|
@ -112,12 +97,11 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
|
|||
/* TODO(klempner): We're currently allowing this, but we shouldn't
|
||||
see it without a proxy so log for now. */
|
||||
gpr_log(GPR_INFO, "Unexpected content-type %s",
|
||||
channeld->content_type->key);
|
||||
grpc_mdstr_as_c_string(md->value));
|
||||
}
|
||||
return NULL;
|
||||
} else if (md->key == channeld->te_trailers->key ||
|
||||
md->key == channeld->method_post->key ||
|
||||
md->key == channeld->http_scheme->key) {
|
||||
} else if (md->key == GRPC_MDSTR_TE || md->key == GRPC_MDSTR_METHOD ||
|
||||
md->key == GRPC_MDSTR_SCHEME) {
|
||||
gpr_log(GPR_ERROR, "Invalid %s: header: '%s'",
|
||||
grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value));
|
||||
/* swallow it and error everything out. */
|
||||
|
|
@ -125,23 +109,21 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
|
|||
on the wire here. */
|
||||
grpc_call_element_send_cancel(a->exec_ctx, elem);
|
||||
return NULL;
|
||||
} else if (md->key == channeld->path_key) {
|
||||
} else if (md->key == GRPC_MDSTR_PATH) {
|
||||
if (calld->seen_path) {
|
||||
gpr_log(GPR_ERROR, "Received :path twice");
|
||||
return NULL;
|
||||
}
|
||||
calld->seen_path = 1;
|
||||
return md;
|
||||
} else if (md->key == channeld->authority_key) {
|
||||
} else if (md->key == GRPC_MDSTR_AUTHORITY) {
|
||||
calld->seen_authority = 1;
|
||||
return md;
|
||||
} else if (md->key == channeld->host_key) {
|
||||
} else if (md->key == GRPC_MDSTR_HOST) {
|
||||
/* translate host to :authority since :authority may be
|
||||
omitted */
|
||||
grpc_mdelem *authority = grpc_mdelem_from_metadata_strings(
|
||||
channeld->mdctx, GRPC_MDSTR_REF(channeld->authority_key),
|
||||
GRPC_MDSTR_REF(md->value));
|
||||
GRPC_MDELEM_UNREF(md);
|
||||
GRPC_MDSTR_AUTHORITY, GRPC_MDSTR_REF(md->value));
|
||||
calld->seen_authority = 1;
|
||||
return authority;
|
||||
} else {
|
||||
|
|
@ -191,15 +173,14 @@ static void hs_mutate_op(grpc_call_element *elem,
|
|||
grpc_transport_stream_op *op) {
|
||||
/* grab pointers to our data from the call element */
|
||||
call_data *calld = elem->call_data;
|
||||
channel_data *channeld = elem->channel_data;
|
||||
|
||||
if (op->send_initial_metadata != NULL && !calld->sent_status) {
|
||||
calld->sent_status = 1;
|
||||
grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->status,
|
||||
GRPC_MDELEM_REF(channeld->status_ok));
|
||||
grpc_metadata_batch_add_tail(op->send_initial_metadata,
|
||||
&calld->content_type,
|
||||
GRPC_MDELEM_REF(channeld->content_type));
|
||||
GRPC_MDELEM_STATUS_200);
|
||||
grpc_metadata_batch_add_tail(
|
||||
op->send_initial_metadata, &calld->content_type,
|
||||
GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC);
|
||||
}
|
||||
|
||||
if (op->recv_initial_metadata) {
|
||||
|
|
@ -238,57 +219,12 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
|
|||
static void init_channel_elem(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *elem,
|
||||
grpc_channel_element_args *args) {
|
||||
/* grab pointers to our data from the channel element */
|
||||
channel_data *channeld = elem->channel_data;
|
||||
|
||||
/* The first and the last filters tend to be implemented differently to
|
||||
handle the case that there's no 'next' filter to call on the up or down
|
||||
path */
|
||||
GPR_ASSERT(!args->is_last);
|
||||
|
||||
/* initialize members */
|
||||
channeld->te_trailers =
|
||||
grpc_mdelem_from_strings(args->metadata_context, "te", "trailers");
|
||||
channeld->status_ok =
|
||||
grpc_mdelem_from_strings(args->metadata_context, ":status", "200");
|
||||
channeld->status_not_found =
|
||||
grpc_mdelem_from_strings(args->metadata_context, ":status", "404");
|
||||
channeld->method_post =
|
||||
grpc_mdelem_from_strings(args->metadata_context, ":method", "POST");
|
||||
channeld->http_scheme =
|
||||
grpc_mdelem_from_strings(args->metadata_context, ":scheme", "http");
|
||||
channeld->https_scheme =
|
||||
grpc_mdelem_from_strings(args->metadata_context, ":scheme", "https");
|
||||
channeld->grpc_scheme =
|
||||
grpc_mdelem_from_strings(args->metadata_context, ":scheme", "grpc");
|
||||
channeld->path_key = grpc_mdstr_from_string(args->metadata_context, ":path");
|
||||
channeld->authority_key =
|
||||
grpc_mdstr_from_string(args->metadata_context, ":authority");
|
||||
channeld->host_key = grpc_mdstr_from_string(args->metadata_context, "host");
|
||||
channeld->content_type = grpc_mdelem_from_strings(
|
||||
args->metadata_context, "content-type", "application/grpc");
|
||||
|
||||
channeld->mdctx = args->metadata_context;
|
||||
}
|
||||
|
||||
/* Destructor for channel data */
|
||||
static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *elem) {
|
||||
/* grab pointers to our data from the channel element */
|
||||
channel_data *channeld = elem->channel_data;
|
||||
|
||||
GRPC_MDELEM_UNREF(channeld->te_trailers);
|
||||
GRPC_MDELEM_UNREF(channeld->status_ok);
|
||||
GRPC_MDELEM_UNREF(channeld->status_not_found);
|
||||
GRPC_MDELEM_UNREF(channeld->method_post);
|
||||
GRPC_MDELEM_UNREF(channeld->http_scheme);
|
||||
GRPC_MDELEM_UNREF(channeld->https_scheme);
|
||||
GRPC_MDELEM_UNREF(channeld->grpc_scheme);
|
||||
GRPC_MDELEM_UNREF(channeld->content_type);
|
||||
GRPC_MDSTR_UNREF(channeld->path_key);
|
||||
GRPC_MDSTR_UNREF(channeld->authority_key);
|
||||
GRPC_MDSTR_UNREF(channeld->host_key);
|
||||
}
|
||||
grpc_channel_element *elem) {}
|
||||
|
||||
const grpc_channel_filter grpc_http_server_filter = {
|
||||
hs_start_transport_op, grpc_channel_next_op, sizeof(call_data),
|
||||
|
|
|
|||
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "src/core/channel/noop_filter.h"
|
||||
#include <grpc/support/log.h>
|
||||
|
||||
typedef struct call_data {
|
||||
int unused; /* C89 requires at least one struct element */
|
||||
} call_data;
|
||||
|
||||
typedef struct channel_data {
|
||||
int unused; /* C89 requires at least one struct element */
|
||||
} channel_data;
|
||||
|
||||
/* used to silence 'variable not used' warnings */
|
||||
static void ignore_unused(void *ignored) {}
|
||||
|
||||
static void noop_mutate_op(grpc_call_element *elem,
|
||||
grpc_transport_stream_op *op) {
|
||||
/* grab pointers to our data from the call element */
|
||||
call_data *calld = elem->call_data;
|
||||
channel_data *channeld = elem->channel_data;
|
||||
|
||||
ignore_unused(calld);
|
||||
ignore_unused(channeld);
|
||||
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
/* Called either:
|
||||
- in response to an API call (or similar) from above, to send something
|
||||
- a network event (or similar) from below, to receive something
|
||||
op contains type and call direction information, in addition to the data
|
||||
that is being sent or received. */
|
||||
static void noop_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
|
||||
grpc_call_element *elem,
|
||||
grpc_transport_stream_op *op) {
|
||||
noop_mutate_op(elem, op);
|
||||
|
||||
/* pass control down the stack */
|
||||
grpc_call_next_op(exec_ctx, elem, op);
|
||||
}
|
||||
|
||||
/* Constructor for call_data */
|
||||
static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
|
||||
grpc_call_element_args *args) {
|
||||
/* grab pointers to our data from the call element */
|
||||
call_data *calld = elem->call_data;
|
||||
channel_data *channeld = elem->channel_data;
|
||||
|
||||
/* initialize members */
|
||||
calld->unused = channeld->unused;
|
||||
}
|
||||
|
||||
/* Destructor for call_data */
|
||||
static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
|
||||
grpc_call_element *elem) {}
|
||||
|
||||
/* Constructor for channel_data */
|
||||
static void init_channel_elem(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *elem,
|
||||
grpc_channel_element_args *args) {
|
||||
/* grab pointers to our data from the channel element */
|
||||
channel_data *channeld = elem->channel_data;
|
||||
|
||||
/* The last filter tends to be implemented differently to
|
||||
handle the case that there's no 'next' filter to call on the down
|
||||
path */
|
||||
GPR_ASSERT(!args->is_last);
|
||||
|
||||
/* initialize members */
|
||||
channeld->unused = 0;
|
||||
}
|
||||
|
||||
/* Destructor for channel data */
|
||||
static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
|
||||
grpc_channel_element *elem) {
|
||||
/* grab pointers to our data from the channel element */
|
||||
channel_data *channeld = elem->channel_data;
|
||||
|
||||
ignore_unused(channeld);
|
||||
}
|
||||
|
||||
const grpc_channel_filter grpc_no_op_filter = {
|
||||
noop_start_transport_stream_op, grpc_channel_next_op, sizeof(call_data),
|
||||
init_call_elem, grpc_call_stack_ignore_set_pollset, destroy_call_elem,
|
||||
sizeof(channel_data), init_channel_elem, destroy_channel_elem,
|
||||
grpc_call_next_get_peer, "no-op"};
|
||||
|
|
@ -44,7 +44,6 @@
|
|||
|
||||
static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *holder,
|
||||
int success);
|
||||
static void call_ready(grpc_exec_ctx *exec_ctx, void *holder, int success);
|
||||
static void retry_ops(grpc_exec_ctx *exec_ctx, void *retry_ops_args,
|
||||
int success);
|
||||
|
||||
|
|
@ -58,16 +57,17 @@ static void retry_waiting_locked(grpc_exec_ctx *exec_ctx,
|
|||
void grpc_subchannel_call_holder_init(
|
||||
grpc_subchannel_call_holder *holder,
|
||||
grpc_subchannel_call_holder_pick_subchannel pick_subchannel,
|
||||
void *pick_subchannel_arg) {
|
||||
void *pick_subchannel_arg, grpc_call_stack *owning_call) {
|
||||
gpr_atm_rel_store(&holder->subchannel_call, 0);
|
||||
holder->pick_subchannel = pick_subchannel;
|
||||
holder->pick_subchannel_arg = pick_subchannel_arg;
|
||||
gpr_mu_init(&holder->mu);
|
||||
holder->subchannel = NULL;
|
||||
holder->connected_subchannel = NULL;
|
||||
holder->waiting_ops = NULL;
|
||||
holder->waiting_ops_count = 0;
|
||||
holder->waiting_ops_capacity = 0;
|
||||
holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
|
||||
holder->owning_call = owning_call;
|
||||
}
|
||||
|
||||
void grpc_subchannel_call_holder_destroy(grpc_exec_ctx *exec_ctx,
|
||||
|
|
@ -125,13 +125,9 @@ retry:
|
|||
case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
|
||||
fail_locked(exec_ctx, holder);
|
||||
break;
|
||||
case GRPC_SUBCHANNEL_CALL_HOLDER_CREATING_CALL:
|
||||
grpc_subchannel_cancel_create_call(exec_ctx, holder->subchannel,
|
||||
&holder->subchannel_call);
|
||||
break;
|
||||
case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
|
||||
holder->pick_subchannel(exec_ctx, holder->pick_subchannel_arg, NULL,
|
||||
&holder->subchannel, NULL);
|
||||
&holder->connected_subchannel, NULL);
|
||||
break;
|
||||
}
|
||||
gpr_mu_unlock(&holder->mu);
|
||||
|
|
@ -142,28 +138,27 @@ retry:
|
|||
}
|
||||
/* if we don't have a subchannel, try to get one */
|
||||
if (holder->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
|
||||
holder->subchannel == NULL && op->send_initial_metadata != NULL) {
|
||||
holder->connected_subchannel == NULL &&
|
||||
op->send_initial_metadata != NULL) {
|
||||
holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
|
||||
grpc_closure_init(&holder->next_step, subchannel_ready, holder);
|
||||
if (holder->pick_subchannel(exec_ctx, holder->pick_subchannel_arg,
|
||||
op->send_initial_metadata, &holder->subchannel,
|
||||
&holder->next_step)) {
|
||||
GRPC_CALL_STACK_REF(holder->owning_call, "pick_subchannel");
|
||||
if (holder->pick_subchannel(
|
||||
exec_ctx, holder->pick_subchannel_arg, op->send_initial_metadata,
|
||||
&holder->connected_subchannel, &holder->next_step)) {
|
||||
holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
|
||||
GRPC_CALL_STACK_UNREF(exec_ctx, holder->owning_call, "pick_subchannel");
|
||||
}
|
||||
}
|
||||
/* if we've got a subchannel, then let's ask it to create a call */
|
||||
if (holder->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
|
||||
holder->subchannel != NULL) {
|
||||
holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_CREATING_CALL;
|
||||
grpc_closure_init(&holder->next_step, call_ready, holder);
|
||||
if (grpc_subchannel_create_call(exec_ctx, holder->subchannel,
|
||||
holder->pollset, &holder->subchannel_call,
|
||||
&holder->next_step)) {
|
||||
/* got one immediately - continue the op (and any waiting ops) */
|
||||
holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
|
||||
retry_waiting_locked(exec_ctx, holder);
|
||||
goto retry;
|
||||
}
|
||||
holder->connected_subchannel != NULL) {
|
||||
gpr_atm_rel_store(
|
||||
&holder->subchannel_call,
|
||||
(gpr_atm)(gpr_uintptr)grpc_connected_subchannel_create_call(
|
||||
exec_ctx, holder->connected_subchannel, holder->pollset));
|
||||
retry_waiting_locked(exec_ctx, holder);
|
||||
goto retry;
|
||||
}
|
||||
/* nothing to be done but wait */
|
||||
add_waiting_locked(holder, op);
|
||||
|
|
@ -179,36 +174,18 @@ static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, int success) {
|
|||
GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
|
||||
call = GET_CALL(holder);
|
||||
GPR_ASSERT(call == NULL || call == CANCELLED_CALL);
|
||||
if (holder->subchannel == NULL) {
|
||||
holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
|
||||
fail_locked(exec_ctx, holder);
|
||||
} else {
|
||||
grpc_closure_init(&holder->next_step, call_ready, holder);
|
||||
if (grpc_subchannel_create_call(exec_ctx, holder->subchannel,
|
||||
holder->pollset, &holder->subchannel_call,
|
||||
&holder->next_step)) {
|
||||
holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
|
||||
/* got one immediately - continue the op (and any waiting ops) */
|
||||
retry_waiting_locked(exec_ctx, holder);
|
||||
}
|
||||
}
|
||||
gpr_mu_unlock(&holder->mu);
|
||||
}
|
||||
|
||||
static void call_ready(grpc_exec_ctx *exec_ctx, void *arg, int success) {
|
||||
grpc_subchannel_call_holder *holder = arg;
|
||||
GPR_TIMER_BEGIN("call_ready", 0);
|
||||
gpr_mu_lock(&holder->mu);
|
||||
GPR_ASSERT(holder->creation_phase ==
|
||||
GRPC_SUBCHANNEL_CALL_HOLDER_CREATING_CALL);
|
||||
holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
|
||||
if (GET_CALL(holder) != NULL) {
|
||||
retry_waiting_locked(exec_ctx, holder);
|
||||
} else {
|
||||
if (holder->connected_subchannel == NULL) {
|
||||
fail_locked(exec_ctx, holder);
|
||||
} else {
|
||||
gpr_atm_rel_store(
|
||||
&holder->subchannel_call,
|
||||
(gpr_atm)(gpr_uintptr)grpc_connected_subchannel_create_call(
|
||||
exec_ctx, holder->connected_subchannel, holder->pollset));
|
||||
retry_waiting_locked(exec_ctx, holder);
|
||||
}
|
||||
gpr_mu_unlock(&holder->mu);
|
||||
GPR_TIMER_END("call_ready", 0);
|
||||
GRPC_CALL_STACK_UNREF(exec_ctx, holder->owning_call, "pick_subchannel");
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -270,14 +247,13 @@ static void fail_locked(grpc_exec_ctx *exec_ctx,
|
|||
holder->waiting_ops_count = 0;
|
||||
}
|
||||
|
||||
char *grpc_subchannel_call_holder_get_peer(grpc_exec_ctx *exec_ctx,
|
||||
grpc_subchannel_call_holder *holder,
|
||||
grpc_channel *master) {
|
||||
char *grpc_subchannel_call_holder_get_peer(
|
||||
grpc_exec_ctx *exec_ctx, grpc_subchannel_call_holder *holder) {
|
||||
grpc_subchannel_call *subchannel_call = GET_CALL(holder);
|
||||
|
||||
if (subchannel_call) {
|
||||
return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
|
||||
} else {
|
||||
return grpc_channel_get_target(master);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,12 +42,11 @@
|
|||
called when the subchannel is available) */
|
||||
typedef int (*grpc_subchannel_call_holder_pick_subchannel)(
|
||||
grpc_exec_ctx *exec_ctx, void *arg, grpc_metadata_batch *initial_metadata,
|
||||
grpc_subchannel **subchannel, grpc_closure *on_ready);
|
||||
grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready);
|
||||
|
||||
typedef enum {
|
||||
GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING,
|
||||
GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL,
|
||||
GRPC_SUBCHANNEL_CALL_HOLDER_CREATING_CALL
|
||||
GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL
|
||||
} grpc_subchannel_call_holder_creation_phase;
|
||||
|
||||
/** Wrapper for holding a pointer to grpc_subchannel_call, and the
|
||||
|
|
@ -71,7 +70,7 @@ typedef struct grpc_subchannel_call_holder {
|
|||
gpr_mu mu;
|
||||
|
||||
grpc_subchannel_call_holder_creation_phase creation_phase;
|
||||
grpc_subchannel *subchannel;
|
||||
grpc_connected_subchannel *connected_subchannel;
|
||||
grpc_pollset *pollset;
|
||||
|
||||
grpc_transport_stream_op *waiting_ops;
|
||||
|
|
@ -79,12 +78,14 @@ typedef struct grpc_subchannel_call_holder {
|
|||
size_t waiting_ops_capacity;
|
||||
|
||||
grpc_closure next_step;
|
||||
|
||||
grpc_call_stack *owning_call;
|
||||
} grpc_subchannel_call_holder;
|
||||
|
||||
void grpc_subchannel_call_holder_init(
|
||||
grpc_subchannel_call_holder *holder,
|
||||
grpc_subchannel_call_holder_pick_subchannel pick_subchannel,
|
||||
void *pick_subchannel_arg);
|
||||
void *pick_subchannel_arg, grpc_call_stack *owning_call);
|
||||
void grpc_subchannel_call_holder_destroy(grpc_exec_ctx *exec_ctx,
|
||||
grpc_subchannel_call_holder *holder);
|
||||
|
||||
|
|
@ -92,7 +93,6 @@ void grpc_subchannel_call_holder_perform_op(grpc_exec_ctx *exec_ctx,
|
|||
grpc_subchannel_call_holder *holder,
|
||||
grpc_transport_stream_op *op);
|
||||
char *grpc_subchannel_call_holder_get_peer(grpc_exec_ctx *exec_ctx,
|
||||
grpc_subchannel_call_holder *holder,
|
||||
grpc_channel *master);
|
||||
grpc_subchannel_call_holder *holder);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -65,6 +65,9 @@ typedef struct {
|
|||
/** any additional filters (owned by the caller of connect) */
|
||||
const grpc_channel_filter **filters;
|
||||
size_t num_filters;
|
||||
|
||||
/** channel arguments (to be passed to the filters) */
|
||||
const grpc_channel_args *channel_args;
|
||||
} grpc_connect_out_args;
|
||||
|
||||
struct grpc_connector_vtable {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
typedef struct pending_pick {
|
||||
struct pending_pick *next;
|
||||
grpc_pollset *pollset;
|
||||
grpc_subchannel **target;
|
||||
grpc_connected_subchannel **target;
|
||||
grpc_closure *on_complete;
|
||||
} pending_pick;
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ typedef struct {
|
|||
/** the selected channel
|
||||
TODO(ctiller): this should be atomically set so we don't
|
||||
need to take a mutex in the common case */
|
||||
grpc_subchannel *selected;
|
||||
grpc_connected_subchannel *selected;
|
||||
/** have we started picking? */
|
||||
int started_picking;
|
||||
/** are we shut down? */
|
||||
|
|
@ -76,24 +76,6 @@ typedef struct {
|
|||
grpc_connectivity_state_tracker state_tracker;
|
||||
} pick_first_lb_policy;
|
||||
|
||||
static void del_interested_parties_locked(grpc_exec_ctx *exec_ctx,
|
||||
pick_first_lb_policy *p) {
|
||||
pending_pick *pp;
|
||||
for (pp = p->pending_picks; pp; pp = pp->next) {
|
||||
grpc_subchannel_del_interested_party(
|
||||
exec_ctx, p->subchannels[p->checking_subchannel], pp->pollset);
|
||||
}
|
||||
}
|
||||
|
||||
static void add_interested_parties_locked(grpc_exec_ctx *exec_ctx,
|
||||
pick_first_lb_policy *p) {
|
||||
pending_pick *pp;
|
||||
for (pp = p->pending_picks; pp; pp = pp->next) {
|
||||
grpc_subchannel_add_interested_party(
|
||||
exec_ctx, p->subchannels[p->checking_subchannel], pp->pollset);
|
||||
}
|
||||
}
|
||||
|
||||
void pf_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
|
||||
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
|
||||
size_t i;
|
||||
|
|
@ -102,7 +84,7 @@ void pf_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
|
|||
GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[i], "pick_first");
|
||||
}
|
||||
if (p->selected) {
|
||||
GRPC_SUBCHANNEL_UNREF(exec_ctx, p->selected, "picked_first");
|
||||
GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, p->selected, "picked_first");
|
||||
}
|
||||
grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
|
||||
gpr_free(p->subchannels);
|
||||
|
|
@ -114,16 +96,26 @@ void pf_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
|
|||
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
|
||||
pending_pick *pp;
|
||||
gpr_mu_lock(&p->mu);
|
||||
del_interested_parties_locked(exec_ctx, p);
|
||||
p->shutdown = 1;
|
||||
pp = p->pending_picks;
|
||||
p->pending_picks = NULL;
|
||||
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
|
||||
GRPC_CHANNEL_FATAL_FAILURE, "shutdown");
|
||||
/* cancel subscription */
|
||||
if (p->selected != NULL) {
|
||||
grpc_connected_subchannel_notify_on_state_change(
|
||||
exec_ctx, p->selected, NULL, NULL, &p->connectivity_changed);
|
||||
} else {
|
||||
grpc_subchannel_notify_on_state_change(
|
||||
exec_ctx, p->subchannels[p->checking_subchannel], NULL, NULL,
|
||||
&p->connectivity_changed);
|
||||
}
|
||||
gpr_mu_unlock(&p->mu);
|
||||
while (pp != NULL) {
|
||||
pending_pick *next = pp->next;
|
||||
*pp->target = NULL;
|
||||
grpc_pollset_set_del_pollset(exec_ctx, &p->base.interested_parties,
|
||||
pp->pollset);
|
||||
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, 1);
|
||||
gpr_free(pp);
|
||||
pp = next;
|
||||
|
|
@ -131,7 +123,7 @@ void pf_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
|
|||
}
|
||||
|
||||
static void pf_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
|
||||
grpc_subchannel **target) {
|
||||
grpc_connected_subchannel **target) {
|
||||
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
|
||||
pending_pick *pp;
|
||||
gpr_mu_lock(&p->mu);
|
||||
|
|
@ -140,8 +132,8 @@ static void pf_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
|
|||
while (pp != NULL) {
|
||||
pending_pick *next = pp->next;
|
||||
if (pp->target == target) {
|
||||
grpc_subchannel_del_interested_party(
|
||||
exec_ctx, p->subchannels[p->checking_subchannel], pp->pollset);
|
||||
grpc_pollset_set_del_pollset(exec_ctx, &p->base.interested_parties,
|
||||
pp->pollset);
|
||||
*target = NULL;
|
||||
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, 0);
|
||||
gpr_free(pp);
|
||||
|
|
@ -158,10 +150,11 @@ static void start_picking(grpc_exec_ctx *exec_ctx, pick_first_lb_policy *p) {
|
|||
p->started_picking = 1;
|
||||
p->checking_subchannel = 0;
|
||||
p->checking_connectivity = GRPC_CHANNEL_IDLE;
|
||||
GRPC_LB_POLICY_REF(&p->base, "pick_first_connectivity");
|
||||
GRPC_LB_POLICY_WEAK_REF(&p->base, "pick_first_connectivity");
|
||||
grpc_subchannel_notify_on_state_change(
|
||||
exec_ctx, p->subchannels[p->checking_subchannel],
|
||||
&p->checking_connectivity, &p->connectivity_changed);
|
||||
&p->base.interested_parties, &p->checking_connectivity,
|
||||
&p->connectivity_changed);
|
||||
}
|
||||
|
||||
void pf_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
|
||||
|
|
@ -174,8 +167,8 @@ void pf_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
|
|||
}
|
||||
|
||||
int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_pollset *pollset,
|
||||
grpc_metadata_batch *initial_metadata, grpc_subchannel **target,
|
||||
grpc_closure *on_complete) {
|
||||
grpc_metadata_batch *initial_metadata,
|
||||
grpc_connected_subchannel **target, grpc_closure *on_complete) {
|
||||
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
|
||||
pending_pick *pp;
|
||||
gpr_mu_lock(&p->mu);
|
||||
|
|
@ -187,8 +180,8 @@ int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_pollset *pollset,
|
|||
if (!p->started_picking) {
|
||||
start_picking(exec_ctx, p);
|
||||
}
|
||||
grpc_subchannel_add_interested_party(
|
||||
exec_ctx, p->subchannels[p->checking_subchannel], pollset);
|
||||
grpc_pollset_set_add_pollset(exec_ctx, &p->base.interested_parties,
|
||||
pollset);
|
||||
pp = gpr_malloc(sizeof(*pp));
|
||||
pp->next = p->pending_picks;
|
||||
pp->pollset = pollset;
|
||||
|
|
@ -204,25 +197,17 @@ static void destroy_subchannels(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
int iomgr_success) {
|
||||
pick_first_lb_policy *p = arg;
|
||||
size_t i;
|
||||
grpc_transport_op op;
|
||||
size_t num_subchannels = p->num_subchannels;
|
||||
grpc_subchannel **subchannels;
|
||||
grpc_subchannel *exclude_subchannel;
|
||||
|
||||
gpr_mu_lock(&p->mu);
|
||||
subchannels = p->subchannels;
|
||||
p->num_subchannels = 0;
|
||||
p->subchannels = NULL;
|
||||
exclude_subchannel = p->selected;
|
||||
gpr_mu_unlock(&p->mu);
|
||||
GRPC_LB_POLICY_UNREF(exec_ctx, &p->base, "destroy_subchannels");
|
||||
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "destroy_subchannels");
|
||||
|
||||
for (i = 0; i < num_subchannels; i++) {
|
||||
if (subchannels[i] != exclude_subchannel) {
|
||||
memset(&op, 0, sizeof(op));
|
||||
op.disconnect = 1;
|
||||
grpc_subchannel_process_transport_op(exec_ctx, subchannels[i], &op);
|
||||
}
|
||||
GRPC_SUBCHANNEL_UNREF(exec_ctx, subchannels[i], "pick_first");
|
||||
}
|
||||
|
||||
|
|
@ -232,23 +217,28 @@ static void destroy_subchannels(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
||||
int iomgr_success) {
|
||||
pick_first_lb_policy *p = arg;
|
||||
grpc_subchannel *selected_subchannel;
|
||||
pending_pick *pp;
|
||||
|
||||
gpr_mu_lock(&p->mu);
|
||||
|
||||
if (p->shutdown) {
|
||||
gpr_mu_unlock(&p->mu);
|
||||
GRPC_LB_POLICY_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
|
||||
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
|
||||
return;
|
||||
} else if (p->selected != NULL) {
|
||||
if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
|
||||
/* if the selected channel goes bad, we're done */
|
||||
p->checking_connectivity = GRPC_CHANNEL_FATAL_FAILURE;
|
||||
}
|
||||
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
|
||||
p->checking_connectivity, "selected_changed");
|
||||
if (p->checking_connectivity != GRPC_CHANNEL_FATAL_FAILURE) {
|
||||
grpc_subchannel_notify_on_state_change(exec_ctx, p->selected,
|
||||
&p->checking_connectivity,
|
||||
&p->connectivity_changed);
|
||||
grpc_connected_subchannel_notify_on_state_change(
|
||||
exec_ctx, p->selected, &p->base.interested_parties,
|
||||
&p->checking_connectivity, &p->connectivity_changed);
|
||||
} else {
|
||||
GRPC_LB_POLICY_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
|
||||
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
|
||||
}
|
||||
} else {
|
||||
loop:
|
||||
|
|
@ -256,39 +246,41 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
case GRPC_CHANNEL_READY:
|
||||
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
|
||||
GRPC_CHANNEL_READY, "connecting_ready");
|
||||
p->selected = p->subchannels[p->checking_subchannel];
|
||||
GRPC_SUBCHANNEL_REF(p->selected, "picked_first");
|
||||
selected_subchannel = p->subchannels[p->checking_subchannel];
|
||||
p->selected =
|
||||
grpc_subchannel_get_connected_subchannel(selected_subchannel);
|
||||
GPR_ASSERT(p->selected);
|
||||
GRPC_CONNECTED_SUBCHANNEL_REF(p->selected, "picked_first");
|
||||
/* drop the pick list: we are connected now */
|
||||
GRPC_LB_POLICY_REF(&p->base, "destroy_subchannels");
|
||||
GRPC_LB_POLICY_WEAK_REF(&p->base, "destroy_subchannels");
|
||||
grpc_exec_ctx_enqueue(exec_ctx,
|
||||
grpc_closure_create(destroy_subchannels, p), 1);
|
||||
/* update any calls that were waiting for a pick */
|
||||
while ((pp = p->pending_picks)) {
|
||||
p->pending_picks = pp->next;
|
||||
*pp->target = p->selected;
|
||||
grpc_subchannel_del_interested_party(exec_ctx, p->selected,
|
||||
pp->pollset);
|
||||
grpc_pollset_set_del_pollset(exec_ctx, &p->base.interested_parties,
|
||||
pp->pollset);
|
||||
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, 1);
|
||||
gpr_free(pp);
|
||||
}
|
||||
grpc_subchannel_notify_on_state_change(exec_ctx, p->selected,
|
||||
&p->checking_connectivity,
|
||||
&p->connectivity_changed);
|
||||
grpc_connected_subchannel_notify_on_state_change(
|
||||
exec_ctx, p->selected, &p->base.interested_parties,
|
||||
&p->checking_connectivity, &p->connectivity_changed);
|
||||
break;
|
||||
case GRPC_CHANNEL_TRANSIENT_FAILURE:
|
||||
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
|
||||
GRPC_CHANNEL_TRANSIENT_FAILURE,
|
||||
"connecting_transient_failure");
|
||||
del_interested_parties_locked(exec_ctx, p);
|
||||
p->checking_subchannel =
|
||||
(p->checking_subchannel + 1) % p->num_subchannels;
|
||||
p->checking_connectivity = grpc_subchannel_check_connectivity(
|
||||
p->subchannels[p->checking_subchannel]);
|
||||
add_interested_parties_locked(exec_ctx, p);
|
||||
if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
|
||||
grpc_subchannel_notify_on_state_change(
|
||||
exec_ctx, p->subchannels[p->checking_subchannel],
|
||||
&p->checking_connectivity, &p->connectivity_changed);
|
||||
&p->base.interested_parties, &p->checking_connectivity,
|
||||
&p->connectivity_changed);
|
||||
} else {
|
||||
goto loop;
|
||||
}
|
||||
|
|
@ -300,13 +292,13 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
"connecting_changed");
|
||||
grpc_subchannel_notify_on_state_change(
|
||||
exec_ctx, p->subchannels[p->checking_subchannel],
|
||||
&p->checking_connectivity, &p->connectivity_changed);
|
||||
&p->base.interested_parties, &p->checking_connectivity,
|
||||
&p->connectivity_changed);
|
||||
break;
|
||||
case GRPC_CHANNEL_FATAL_FAILURE:
|
||||
del_interested_parties_locked(exec_ctx, p);
|
||||
GPR_SWAP(grpc_subchannel *, p->subchannels[p->checking_subchannel],
|
||||
p->subchannels[p->num_subchannels - 1]);
|
||||
p->num_subchannels--;
|
||||
GPR_SWAP(grpc_subchannel *, p->subchannels[p->checking_subchannel],
|
||||
p->subchannels[p->num_subchannels]);
|
||||
GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[p->num_subchannels],
|
||||
"pick_first");
|
||||
if (p->num_subchannels == 0) {
|
||||
|
|
@ -319,7 +311,8 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, 1);
|
||||
gpr_free(pp);
|
||||
}
|
||||
GRPC_LB_POLICY_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
|
||||
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base,
|
||||
"pick_first_connectivity");
|
||||
} else {
|
||||
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
|
||||
GRPC_CHANNEL_TRANSIENT_FAILURE,
|
||||
|
|
@ -327,7 +320,6 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
p->checking_subchannel %= p->num_subchannels;
|
||||
p->checking_connectivity = grpc_subchannel_check_connectivity(
|
||||
p->subchannels[p->checking_subchannel]);
|
||||
add_interested_parties_locked(exec_ctx, p);
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
|
|
@ -336,39 +328,6 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
gpr_mu_unlock(&p->mu);
|
||||
}
|
||||
|
||||
static void pf_broadcast(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
|
||||
grpc_transport_op *op) {
|
||||
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
|
||||
size_t i;
|
||||
size_t n;
|
||||
grpc_subchannel **subchannels;
|
||||
grpc_subchannel *selected;
|
||||
|
||||
gpr_mu_lock(&p->mu);
|
||||
n = p->num_subchannels;
|
||||
subchannels = gpr_malloc(n * sizeof(*subchannels));
|
||||
selected = p->selected;
|
||||
if (selected) {
|
||||
GRPC_SUBCHANNEL_REF(selected, "pf_broadcast_to_selected");
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
subchannels[i] = p->subchannels[i];
|
||||
GRPC_SUBCHANNEL_REF(subchannels[i], "pf_broadcast");
|
||||
}
|
||||
gpr_mu_unlock(&p->mu);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (selected == subchannels[i]) continue;
|
||||
grpc_subchannel_process_transport_op(exec_ctx, subchannels[i], op);
|
||||
GRPC_SUBCHANNEL_UNREF(exec_ctx, subchannels[i], "pf_broadcast");
|
||||
}
|
||||
if (p->selected) {
|
||||
grpc_subchannel_process_transport_op(exec_ctx, selected, op);
|
||||
GRPC_SUBCHANNEL_UNREF(exec_ctx, selected, "pf_broadcast_to_selected");
|
||||
}
|
||||
gpr_free(subchannels);
|
||||
}
|
||||
|
||||
static grpc_connectivity_state pf_check_connectivity(grpc_exec_ctx *exec_ctx,
|
||||
grpc_lb_policy *pol) {
|
||||
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
|
||||
|
|
@ -389,9 +348,21 @@ void pf_notify_on_state_change(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
|
|||
gpr_mu_unlock(&p->mu);
|
||||
}
|
||||
|
||||
void pf_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
|
||||
grpc_closure *closure) {
|
||||
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
|
||||
gpr_mu_lock(&p->mu);
|
||||
if (p->selected) {
|
||||
grpc_connected_subchannel_ping(exec_ctx, p->selected, closure);
|
||||
} else {
|
||||
grpc_exec_ctx_enqueue(exec_ctx, closure, 0);
|
||||
}
|
||||
gpr_mu_unlock(&p->mu);
|
||||
}
|
||||
|
||||
static const grpc_lb_policy_vtable pick_first_lb_policy_vtable = {
|
||||
pf_destroy, pf_shutdown, pf_pick, pf_cancel_pick, pf_exit_idle,
|
||||
pf_broadcast, pf_check_connectivity, pf_notify_on_state_change};
|
||||
pf_destroy, pf_shutdown, pf_pick, pf_cancel_pick, pf_ping_one, pf_exit_idle,
|
||||
pf_check_connectivity, pf_notify_on_state_change};
|
||||
|
||||
static void pick_first_factory_ref(grpc_lb_policy_factory *factory) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@
|
|||
#include <grpc/support/alloc.h>
|
||||
#include "src/core/transport/connectivity_state.h"
|
||||
|
||||
typedef struct round_robin_lb_policy round_robin_lb_policy;
|
||||
|
||||
int grpc_lb_round_robin_trace = 0;
|
||||
|
||||
/** List of entities waiting for a pick.
|
||||
|
|
@ -46,7 +48,7 @@ int grpc_lb_round_robin_trace = 0;
|
|||
typedef struct pending_pick {
|
||||
struct pending_pick *next;
|
||||
grpc_pollset *pollset;
|
||||
grpc_subchannel **target;
|
||||
grpc_connected_subchannel **target;
|
||||
grpc_closure *on_complete;
|
||||
} pending_pick;
|
||||
|
||||
|
|
@ -58,22 +60,27 @@ typedef struct ready_list {
|
|||
} ready_list;
|
||||
|
||||
typedef struct {
|
||||
size_t subchannel_idx; /**< Index over p->subchannels */
|
||||
void *p; /**< round_robin_lb_policy instance */
|
||||
} connectivity_changed_cb_arg;
|
||||
/** index within policy->subchannels */
|
||||
size_t index;
|
||||
/** backpointer to owning policy */
|
||||
round_robin_lb_policy *policy;
|
||||
/** subchannel itself */
|
||||
grpc_subchannel *subchannel;
|
||||
/** notification that connectivity has changed on subchannel */
|
||||
grpc_closure connectivity_changed_closure;
|
||||
/** this subchannels current position in subchannel->ready_list */
|
||||
ready_list *ready_list_node;
|
||||
/** last observed connectivity */
|
||||
grpc_connectivity_state connectivity_state;
|
||||
} subchannel_data;
|
||||
|
||||
typedef struct {
|
||||
struct round_robin_lb_policy {
|
||||
/** base policy: must be first */
|
||||
grpc_lb_policy base;
|
||||
|
||||
/** all our subchannels */
|
||||
grpc_subchannel **subchannels;
|
||||
size_t num_subchannels;
|
||||
|
||||
/** Callbacks, one per subchannel being watched, to be called when their
|
||||
* respective connectivity changes */
|
||||
grpc_closure *connectivity_changed_cbs;
|
||||
connectivity_changed_cb_arg *cb_args;
|
||||
subchannel_data **subchannels;
|
||||
|
||||
/** mutex protecting remaining members */
|
||||
gpr_mu mu;
|
||||
|
|
@ -81,8 +88,6 @@ typedef struct {
|
|||
int started_picking;
|
||||
/** are we shutting down? */
|
||||
int shutdown;
|
||||
/** Connectivity state of the subchannels being watched */
|
||||
grpc_connectivity_state *subchannel_connectivity;
|
||||
/** List of picks that are waiting on connectivity */
|
||||
pending_pick *pending_picks;
|
||||
|
||||
|
|
@ -93,13 +98,7 @@ typedef struct {
|
|||
ready_list ready_list;
|
||||
/** Last pick from the ready list. */
|
||||
ready_list *ready_list_last_pick;
|
||||
|
||||
/** Subchannel index to ready_list node.
|
||||
*
|
||||
* Kept in order to remove nodes from the ready list associated with a
|
||||
* subchannel */
|
||||
ready_list **subchannel_index_to_readylist_node;
|
||||
} round_robin_lb_policy;
|
||||
};
|
||||
|
||||
/** Returns the next subchannel from the connected list or NULL if the list is
|
||||
* empty.
|
||||
|
|
@ -144,9 +143,9 @@ static void advance_last_picked_locked(round_robin_lb_policy *p) {
|
|||
/** Prepends (relative to the root at p->ready_list) the connected subchannel \a
|
||||
* csc to the list of ready subchannels. */
|
||||
static ready_list *add_connected_sc_locked(round_robin_lb_policy *p,
|
||||
grpc_subchannel *csc) {
|
||||
grpc_subchannel *sc) {
|
||||
ready_list *new_elem = gpr_malloc(sizeof(ready_list));
|
||||
new_elem->subchannel = csc;
|
||||
new_elem->subchannel = sc;
|
||||
if (p->ready_list.prev == NULL) {
|
||||
/* first element */
|
||||
new_elem->next = &p->ready_list;
|
||||
|
|
@ -160,7 +159,7 @@ static ready_list *add_connected_sc_locked(round_robin_lb_policy *p,
|
|||
p->ready_list.prev = new_elem;
|
||||
}
|
||||
if (grpc_lb_round_robin_trace) {
|
||||
gpr_log(GPR_DEBUG, "[READYLIST] ADDING NODE %p (SC %p)", new_elem, csc);
|
||||
gpr_log(GPR_DEBUG, "[READYLIST] ADDING NODE %p (SC %p)", new_elem, sc);
|
||||
}
|
||||
return new_elem;
|
||||
}
|
||||
|
|
@ -200,28 +199,15 @@ static void remove_disconnected_sc_locked(round_robin_lb_policy *p,
|
|||
gpr_free(node);
|
||||
}
|
||||
|
||||
static void del_interested_parties_locked(grpc_exec_ctx *exec_ctx,
|
||||
round_robin_lb_policy *p,
|
||||
const size_t subchannel_idx) {
|
||||
pending_pick *pp;
|
||||
for (pp = p->pending_picks; pp; pp = pp->next) {
|
||||
grpc_subchannel_del_interested_party(
|
||||
exec_ctx, p->subchannels[subchannel_idx], pp->pollset);
|
||||
}
|
||||
}
|
||||
|
||||
void rr_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
|
||||
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
|
||||
size_t i;
|
||||
ready_list *elem;
|
||||
for (i = 0; i < p->num_subchannels; i++) {
|
||||
del_interested_parties_locked(exec_ctx, p, i);
|
||||
subchannel_data *sd = p->subchannels[i];
|
||||
GRPC_SUBCHANNEL_UNREF(exec_ctx, sd->subchannel, "round_robin");
|
||||
gpr_free(sd);
|
||||
}
|
||||
for (i = 0; i < p->num_subchannels; i++) {
|
||||
GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[i], "round_robin");
|
||||
}
|
||||
gpr_free(p->connectivity_changed_cbs);
|
||||
gpr_free(p->subchannel_connectivity);
|
||||
|
||||
grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
|
||||
gpr_free(p->subchannels);
|
||||
|
|
@ -237,20 +223,15 @@ void rr_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
|
|||
gpr_free(elem);
|
||||
elem = tmp;
|
||||
}
|
||||
gpr_free(p->subchannel_index_to_readylist_node);
|
||||
gpr_free(p->cb_args);
|
||||
gpr_free(p);
|
||||
}
|
||||
|
||||
void rr_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
|
||||
size_t i;
|
||||
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
|
||||
pending_pick *pp;
|
||||
gpr_mu_lock(&p->mu);
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < p->num_subchannels; i++) {
|
||||
del_interested_parties_locked(exec_ctx, p, i);
|
||||
}
|
||||
gpr_mu_lock(&p->mu);
|
||||
|
||||
p->shutdown = 1;
|
||||
while ((pp = p->pending_picks)) {
|
||||
|
|
@ -261,24 +242,26 @@ void rr_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
|
|||
}
|
||||
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
|
||||
GRPC_CHANNEL_FATAL_FAILURE, "shutdown");
|
||||
for (i = 0; i < p->num_subchannels; i++) {
|
||||
subchannel_data *sd = p->subchannels[i];
|
||||
grpc_subchannel_notify_on_state_change(exec_ctx, sd->subchannel, NULL, NULL,
|
||||
&sd->connectivity_changed_closure);
|
||||
}
|
||||
gpr_mu_unlock(&p->mu);
|
||||
}
|
||||
|
||||
static void rr_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
|
||||
grpc_subchannel **target) {
|
||||
grpc_connected_subchannel **target) {
|
||||
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
|
||||
pending_pick *pp;
|
||||
size_t i;
|
||||
gpr_mu_lock(&p->mu);
|
||||
pp = p->pending_picks;
|
||||
p->pending_picks = NULL;
|
||||
while (pp != NULL) {
|
||||
pending_pick *next = pp->next;
|
||||
if (pp->target == target) {
|
||||
for (i = 0; i < p->num_subchannels; i++) {
|
||||
grpc_subchannel_add_interested_party(exec_ctx, p->subchannels[i],
|
||||
pp->pollset);
|
||||
}
|
||||
grpc_pollset_set_del_pollset(exec_ctx, &p->base.interested_parties,
|
||||
pp->pollset);
|
||||
*target = NULL;
|
||||
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, 0);
|
||||
gpr_free(pp);
|
||||
|
|
@ -295,12 +278,16 @@ static void start_picking(grpc_exec_ctx *exec_ctx, round_robin_lb_policy *p) {
|
|||
size_t i;
|
||||
p->started_picking = 1;
|
||||
|
||||
gpr_log(GPR_DEBUG, "LB_POLICY: p=%p num_subchannels=%d", p,
|
||||
p->num_subchannels);
|
||||
|
||||
for (i = 0; i < p->num_subchannels; i++) {
|
||||
p->subchannel_connectivity[i] = GRPC_CHANNEL_IDLE;
|
||||
grpc_subchannel_notify_on_state_change(exec_ctx, p->subchannels[i],
|
||||
&p->subchannel_connectivity[i],
|
||||
&p->connectivity_changed_cbs[i]);
|
||||
GRPC_LB_POLICY_REF(&p->base, "round_robin_connectivity");
|
||||
subchannel_data *sd = p->subchannels[i];
|
||||
sd->connectivity_state = GRPC_CHANNEL_IDLE;
|
||||
grpc_subchannel_notify_on_state_change(
|
||||
exec_ctx, sd->subchannel, &p->base.interested_parties,
|
||||
&sd->connectivity_state, &sd->connectivity_changed_closure);
|
||||
GRPC_LB_POLICY_WEAK_REF(&p->base, "round_robin_connectivity");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -314,18 +301,18 @@ void rr_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
|
|||
}
|
||||
|
||||
int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_pollset *pollset,
|
||||
grpc_metadata_batch *initial_metadata, grpc_subchannel **target,
|
||||
grpc_closure *on_complete) {
|
||||
size_t i;
|
||||
grpc_metadata_batch *initial_metadata,
|
||||
grpc_connected_subchannel **target, grpc_closure *on_complete) {
|
||||
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
|
||||
pending_pick *pp;
|
||||
ready_list *selected;
|
||||
gpr_mu_lock(&p->mu);
|
||||
if ((selected = peek_next_connected_locked(p))) {
|
||||
gpr_mu_unlock(&p->mu);
|
||||
*target = selected->subchannel;
|
||||
*target = grpc_subchannel_get_connected_subchannel(selected->subchannel);
|
||||
if (grpc_lb_round_robin_trace) {
|
||||
gpr_log(GPR_DEBUG, "[RR PICK] TARGET <-- SUBCHANNEL %p (NODE %p)",
|
||||
gpr_log(GPR_DEBUG,
|
||||
"[RR PICK] TARGET <-- CONNECTED SUBCHANNEL %p (NODE %p)",
|
||||
selected->subchannel, selected);
|
||||
}
|
||||
/* only advance the last picked pointer if the selection was used */
|
||||
|
|
@ -335,10 +322,8 @@ int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_pollset *pollset,
|
|||
if (!p->started_picking) {
|
||||
start_picking(exec_ctx, p);
|
||||
}
|
||||
for (i = 0; i < p->num_subchannels; i++) {
|
||||
grpc_subchannel_add_interested_party(exec_ctx, p->subchannels[i],
|
||||
pollset);
|
||||
}
|
||||
grpc_pollset_set_add_pollset(exec_ctx, &p->base.interested_parties,
|
||||
pollset);
|
||||
pp = gpr_malloc(sizeof(*pp));
|
||||
pp->next = p->pending_picks;
|
||||
pp->pollset = pollset;
|
||||
|
|
@ -352,33 +337,25 @@ int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_pollset *pollset,
|
|||
|
||||
static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
||||
int iomgr_success) {
|
||||
connectivity_changed_cb_arg *cb_arg = arg;
|
||||
round_robin_lb_policy *p = cb_arg->p;
|
||||
/* index over p->subchannels of this cb's subchannel */
|
||||
const size_t this_idx = cb_arg->subchannel_idx;
|
||||
subchannel_data *sd = arg;
|
||||
round_robin_lb_policy *p = sd->policy;
|
||||
pending_pick *pp;
|
||||
ready_list *selected;
|
||||
|
||||
int unref = 0;
|
||||
|
||||
/* connectivity state of this cb's subchannel */
|
||||
grpc_connectivity_state *this_connectivity;
|
||||
|
||||
gpr_mu_lock(&p->mu);
|
||||
|
||||
this_connectivity = &p->subchannel_connectivity[this_idx];
|
||||
|
||||
if (p->shutdown) {
|
||||
unref = 1;
|
||||
} else {
|
||||
switch (*this_connectivity) {
|
||||
switch (sd->connectivity_state) {
|
||||
case GRPC_CHANNEL_READY:
|
||||
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
|
||||
GRPC_CHANNEL_READY, "connecting_ready");
|
||||
/* add the newly connected subchannel to the list of connected ones.
|
||||
* Note that it goes to the "end of the line". */
|
||||
p->subchannel_index_to_readylist_node[this_idx] =
|
||||
add_connected_sc_locked(p, p->subchannels[this_idx]);
|
||||
sd->ready_list_node = add_connected_sc_locked(p, sd->subchannel);
|
||||
/* at this point we know there's at least one suitable subchannel. Go
|
||||
* ahead and pick one and notify the pending suitors in
|
||||
* p->pending_picks. This preemtively replicates rr_pick()'s actions. */
|
||||
|
|
@ -390,60 +367,60 @@ static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
}
|
||||
while ((pp = p->pending_picks)) {
|
||||
p->pending_picks = pp->next;
|
||||
*pp->target = selected->subchannel;
|
||||
*pp->target =
|
||||
grpc_subchannel_get_connected_subchannel(selected->subchannel);
|
||||
if (grpc_lb_round_robin_trace) {
|
||||
gpr_log(GPR_DEBUG,
|
||||
"[RR CONN CHANGED] TARGET <-- SUBCHANNEL %p (NODE %p)",
|
||||
selected->subchannel, selected);
|
||||
}
|
||||
grpc_subchannel_del_interested_party(exec_ctx, selected->subchannel,
|
||||
pp->pollset);
|
||||
grpc_pollset_set_del_pollset(exec_ctx, &p->base.interested_parties,
|
||||
pp->pollset);
|
||||
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, 1);
|
||||
gpr_free(pp);
|
||||
}
|
||||
grpc_subchannel_notify_on_state_change(
|
||||
exec_ctx, p->subchannels[this_idx], this_connectivity,
|
||||
&p->connectivity_changed_cbs[this_idx]);
|
||||
exec_ctx, sd->subchannel, &p->base.interested_parties,
|
||||
&sd->connectivity_state, &sd->connectivity_changed_closure);
|
||||
break;
|
||||
case GRPC_CHANNEL_CONNECTING:
|
||||
case GRPC_CHANNEL_IDLE:
|
||||
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
|
||||
*this_connectivity, "connecting_changed");
|
||||
sd->connectivity_state,
|
||||
"connecting_changed");
|
||||
grpc_subchannel_notify_on_state_change(
|
||||
exec_ctx, p->subchannels[this_idx], this_connectivity,
|
||||
&p->connectivity_changed_cbs[this_idx]);
|
||||
exec_ctx, sd->subchannel, &p->base.interested_parties,
|
||||
&sd->connectivity_state, &sd->connectivity_changed_closure);
|
||||
break;
|
||||
case GRPC_CHANNEL_TRANSIENT_FAILURE:
|
||||
del_interested_parties_locked(exec_ctx, p, this_idx);
|
||||
/* renew state notification */
|
||||
grpc_subchannel_notify_on_state_change(
|
||||
exec_ctx, p->subchannels[this_idx], this_connectivity,
|
||||
&p->connectivity_changed_cbs[this_idx]);
|
||||
exec_ctx, sd->subchannel, &p->base.interested_parties,
|
||||
&sd->connectivity_state, &sd->connectivity_changed_closure);
|
||||
|
||||
/* remove from ready list if still present */
|
||||
if (p->subchannel_index_to_readylist_node[this_idx] != NULL) {
|
||||
remove_disconnected_sc_locked(
|
||||
p, p->subchannel_index_to_readylist_node[this_idx]);
|
||||
p->subchannel_index_to_readylist_node[this_idx] = NULL;
|
||||
if (sd->ready_list_node != NULL) {
|
||||
remove_disconnected_sc_locked(p, sd->ready_list_node);
|
||||
sd->ready_list_node = NULL;
|
||||
}
|
||||
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
|
||||
GRPC_CHANNEL_TRANSIENT_FAILURE,
|
||||
"connecting_transient_failure");
|
||||
break;
|
||||
case GRPC_CHANNEL_FATAL_FAILURE:
|
||||
del_interested_parties_locked(exec_ctx, p, this_idx);
|
||||
if (p->subchannel_index_to_readylist_node[this_idx] != NULL) {
|
||||
remove_disconnected_sc_locked(
|
||||
p, p->subchannel_index_to_readylist_node[this_idx]);
|
||||
p->subchannel_index_to_readylist_node[this_idx] = NULL;
|
||||
if (sd->ready_list_node != NULL) {
|
||||
remove_disconnected_sc_locked(p, sd->ready_list_node);
|
||||
sd->ready_list_node = NULL;
|
||||
}
|
||||
|
||||
GPR_SWAP(grpc_subchannel *, p->subchannels[this_idx],
|
||||
p->subchannels[p->num_subchannels - 1]);
|
||||
p->num_subchannels--;
|
||||
GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[p->num_subchannels],
|
||||
"round_robin");
|
||||
GPR_SWAP(subchannel_data *, p->subchannels[sd->index],
|
||||
p->subchannels[p->num_subchannels]);
|
||||
GRPC_SUBCHANNEL_UNREF(exec_ctx, sd->subchannel, "round_robin");
|
||||
p->subchannels[sd->index]->index = sd->index;
|
||||
gpr_free(sd);
|
||||
|
||||
unref = 1;
|
||||
if (p->num_subchannels == 0) {
|
||||
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
|
||||
GRPC_CHANNEL_FATAL_FAILURE,
|
||||
|
|
@ -454,7 +431,6 @@ static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, 1);
|
||||
gpr_free(pp);
|
||||
}
|
||||
unref = 1;
|
||||
} else {
|
||||
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
|
||||
GRPC_CHANNEL_TRANSIENT_FAILURE,
|
||||
|
|
@ -466,33 +442,10 @@ static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
|
|||
gpr_mu_unlock(&p->mu);
|
||||
|
||||
if (unref) {
|
||||
GRPC_LB_POLICY_UNREF(exec_ctx, &p->base, "round_robin_connectivity");
|
||||
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "round_robin_connectivity");
|
||||
}
|
||||
}
|
||||
|
||||
static void rr_broadcast(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
|
||||
grpc_transport_op *op) {
|
||||
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
|
||||
size_t i;
|
||||
size_t n;
|
||||
grpc_subchannel **subchannels;
|
||||
|
||||
gpr_mu_lock(&p->mu);
|
||||
n = p->num_subchannels;
|
||||
subchannels = gpr_malloc(n * sizeof(*subchannels));
|
||||
for (i = 0; i < n; i++) {
|
||||
subchannels[i] = p->subchannels[i];
|
||||
GRPC_SUBCHANNEL_REF(subchannels[i], "rr_broadcast");
|
||||
}
|
||||
gpr_mu_unlock(&p->mu);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
grpc_subchannel_process_transport_op(exec_ctx, subchannels[i], op);
|
||||
GRPC_SUBCHANNEL_UNREF(exec_ctx, subchannels[i], "rr_broadcast");
|
||||
}
|
||||
gpr_free(subchannels);
|
||||
}
|
||||
|
||||
static grpc_connectivity_state rr_check_connectivity(grpc_exec_ctx *exec_ctx,
|
||||
grpc_lb_policy *pol) {
|
||||
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
|
||||
|
|
@ -514,9 +467,25 @@ static void rr_notify_on_state_change(grpc_exec_ctx *exec_ctx,
|
|||
gpr_mu_unlock(&p->mu);
|
||||
}
|
||||
|
||||
static void rr_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
|
||||
grpc_closure *closure) {
|
||||
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
|
||||
ready_list *selected;
|
||||
grpc_connected_subchannel *target;
|
||||
gpr_mu_lock(&p->mu);
|
||||
if ((selected = peek_next_connected_locked(p))) {
|
||||
gpr_mu_unlock(&p->mu);
|
||||
target = grpc_subchannel_get_connected_subchannel(selected->subchannel);
|
||||
grpc_connected_subchannel_ping(exec_ctx, target, closure);
|
||||
} else {
|
||||
gpr_mu_unlock(&p->mu);
|
||||
grpc_exec_ctx_enqueue(exec_ctx, closure, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static const grpc_lb_policy_vtable round_robin_lb_policy_vtable = {
|
||||
rr_destroy, rr_shutdown, rr_pick, rr_cancel_pick, rr_exit_idle,
|
||||
rr_broadcast, rr_check_connectivity, rr_notify_on_state_change};
|
||||
rr_destroy, rr_shutdown, rr_pick, rr_cancel_pick, rr_ping_one, rr_exit_idle,
|
||||
rr_check_connectivity, rr_notify_on_state_change};
|
||||
|
||||
static void round_robin_factory_ref(grpc_lb_policy_factory *factory) {}
|
||||
|
||||
|
|
@ -529,27 +498,22 @@ static grpc_lb_policy *create_round_robin(grpc_lb_policy_factory *factory,
|
|||
GPR_ASSERT(args->num_subchannels > 0);
|
||||
memset(p, 0, sizeof(*p));
|
||||
grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable);
|
||||
p->subchannels =
|
||||
gpr_malloc(sizeof(grpc_subchannel *) * args->num_subchannels);
|
||||
p->num_subchannels = args->num_subchannels;
|
||||
p->subchannels = gpr_malloc(sizeof(*p->subchannels) * p->num_subchannels);
|
||||
memset(p->subchannels, 0, sizeof(*p->subchannels) * p->num_subchannels);
|
||||
grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE,
|
||||
"round_robin");
|
||||
memcpy(p->subchannels, args->subchannels,
|
||||
sizeof(grpc_subchannel *) * args->num_subchannels);
|
||||
|
||||
gpr_mu_init(&p->mu);
|
||||
p->connectivity_changed_cbs =
|
||||
gpr_malloc(sizeof(grpc_closure) * args->num_subchannels);
|
||||
p->subchannel_connectivity =
|
||||
gpr_malloc(sizeof(grpc_connectivity_state) * args->num_subchannels);
|
||||
|
||||
p->cb_args =
|
||||
gpr_malloc(sizeof(connectivity_changed_cb_arg) * args->num_subchannels);
|
||||
for (i = 0; i < args->num_subchannels; i++) {
|
||||
p->cb_args[i].subchannel_idx = i;
|
||||
p->cb_args[i].p = p;
|
||||
grpc_closure_init(&p->connectivity_changed_cbs[i], rr_connectivity_changed,
|
||||
&p->cb_args[i]);
|
||||
subchannel_data *sd = gpr_malloc(sizeof(*sd));
|
||||
memset(sd, 0, sizeof(*sd));
|
||||
p->subchannels[i] = sd;
|
||||
sd->policy = p;
|
||||
sd->index = i;
|
||||
sd->subchannel = args->subchannels[i];
|
||||
grpc_closure_init(&sd->connectivity_changed_closure,
|
||||
rr_connectivity_changed, sd);
|
||||
}
|
||||
|
||||
/* The (dummy node) root of the ready list */
|
||||
|
|
@ -558,10 +522,6 @@ static grpc_lb_policy *create_round_robin(grpc_lb_policy_factory *factory,
|
|||
p->ready_list.next = NULL;
|
||||
p->ready_list_last_pick = &p->ready_list;
|
||||
|
||||
p->subchannel_index_to_readylist_node =
|
||||
gpr_malloc(sizeof(grpc_subchannel *) * args->num_subchannels);
|
||||
memset(p->subchannel_index_to_readylist_node, 0,
|
||||
sizeof(grpc_subchannel *) * args->num_subchannels);
|
||||
return &p->base;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,63 +33,94 @@
|
|||
|
||||
#include "src/core/client_config/lb_policy.h"
|
||||
|
||||
#define WEAK_REF_BITS 16
|
||||
|
||||
void grpc_lb_policy_init(grpc_lb_policy *policy,
|
||||
const grpc_lb_policy_vtable *vtable) {
|
||||
policy->vtable = vtable;
|
||||
gpr_ref_init(&policy->refs, 1);
|
||||
gpr_atm_no_barrier_store(&policy->ref_pair, 1 << WEAK_REF_BITS);
|
||||
grpc_pollset_set_init(&policy->interested_parties);
|
||||
}
|
||||
|
||||
#ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG
|
||||
void grpc_lb_policy_ref(grpc_lb_policy *policy, const char *file, int line,
|
||||
const char *reason) {
|
||||
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "LB_POLICY:%p ref %d -> %d %s",
|
||||
policy, (int)policy->refs.count, (int)policy->refs.count + 1, reason);
|
||||
#define REF_FUNC_EXTRA_ARGS , const char *file, int line, const char *reason
|
||||
#define REF_MUTATE_EXTRA_ARGS REF_FUNC_EXTRA_ARGS, const char *purpose
|
||||
#define REF_FUNC_PASS_ARGS(new_reason) , file, line, new_reason
|
||||
#define REF_MUTATE_PASS_ARGS(purpose) , file, line, reason, purpose
|
||||
#else
|
||||
void grpc_lb_policy_ref(grpc_lb_policy *policy) {
|
||||
#define REF_FUNC_EXTRA_ARGS
|
||||
#define REF_MUTATE_EXTRA_ARGS
|
||||
#define REF_FUNC_PASS_ARGS(new_reason)
|
||||
#define REF_MUTATE_PASS_ARGS(x)
|
||||
#endif
|
||||
gpr_ref(&policy->refs);
|
||||
|
||||
static gpr_atm ref_mutate(grpc_lb_policy *c, gpr_atm delta,
|
||||
int barrier REF_MUTATE_EXTRA_ARGS) {
|
||||
gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta)
|
||||
: gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta);
|
||||
#ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG
|
||||
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
|
||||
"LB_POLICY: %p % 12s 0x%08x -> 0x%08x [%s]", c, purpose, old_val,
|
||||
old_val + delta, reason);
|
||||
#endif
|
||||
return old_val;
|
||||
}
|
||||
|
||||
#ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG
|
||||
void grpc_lb_policy_unref(grpc_lb_policy *policy,
|
||||
grpc_closure_list *closure_list, const char *file,
|
||||
int line, const char *reason) {
|
||||
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "LB_POLICY:%p unref %d -> %d %s",
|
||||
policy, (int)policy->refs.count, (int)policy->refs.count - 1, reason);
|
||||
#else
|
||||
void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) {
|
||||
#endif
|
||||
if (gpr_unref(&policy->refs)) {
|
||||
void grpc_lb_policy_ref(grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) {
|
||||
ref_mutate(policy, 1 << WEAK_REF_BITS, 0 REF_MUTATE_PASS_ARGS("STRONG_REF"));
|
||||
}
|
||||
|
||||
void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx,
|
||||
grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) {
|
||||
gpr_atm old_val =
|
||||
ref_mutate(policy, (gpr_atm)1 - (gpr_atm)(1 << WEAK_REF_BITS),
|
||||
1 REF_MUTATE_PASS_ARGS("STRONG_UNREF"));
|
||||
gpr_atm mask = ~(gpr_atm)((1 << WEAK_REF_BITS) - 1);
|
||||
gpr_atm check = 1 << WEAK_REF_BITS;
|
||||
if ((old_val & mask) == check) {
|
||||
policy->vtable->shutdown(exec_ctx, policy);
|
||||
}
|
||||
grpc_lb_policy_weak_unref(exec_ctx,
|
||||
policy REF_FUNC_PASS_ARGS("strong-unref"));
|
||||
}
|
||||
|
||||
void grpc_lb_policy_weak_ref(grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) {
|
||||
ref_mutate(policy, 1, 0 REF_MUTATE_PASS_ARGS("WEAK_REF"));
|
||||
}
|
||||
|
||||
void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx,
|
||||
grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) {
|
||||
gpr_atm old_val =
|
||||
ref_mutate(policy, -(gpr_atm)1, 1 REF_MUTATE_PASS_ARGS("WEAK_UNREF"));
|
||||
if (old_val == 1) {
|
||||
grpc_pollset_set_destroy(&policy->interested_parties);
|
||||
policy->vtable->destroy(exec_ctx, policy);
|
||||
}
|
||||
}
|
||||
|
||||
void grpc_lb_policy_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) {
|
||||
policy->vtable->shutdown(exec_ctx, policy);
|
||||
}
|
||||
|
||||
int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
|
||||
grpc_pollset *pollset,
|
||||
grpc_metadata_batch *initial_metadata,
|
||||
grpc_subchannel **target, grpc_closure *on_complete) {
|
||||
grpc_connected_subchannel **target,
|
||||
grpc_closure *on_complete) {
|
||||
return policy->vtable->pick(exec_ctx, policy, pollset, initial_metadata,
|
||||
target, on_complete);
|
||||
}
|
||||
|
||||
void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
|
||||
grpc_subchannel **target) {
|
||||
grpc_connected_subchannel **target) {
|
||||
policy->vtable->cancel_pick(exec_ctx, policy, target);
|
||||
}
|
||||
|
||||
void grpc_lb_policy_broadcast(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
|
||||
grpc_transport_op *op) {
|
||||
policy->vtable->broadcast(exec_ctx, policy, op);
|
||||
}
|
||||
|
||||
void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) {
|
||||
policy->vtable->exit_idle(exec_ctx, policy);
|
||||
}
|
||||
|
||||
void grpc_lb_policy_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
|
||||
grpc_closure *closure) {
|
||||
policy->vtable->ping_one(exec_ctx, policy, closure);
|
||||
}
|
||||
|
||||
void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx,
|
||||
grpc_lb_policy *policy,
|
||||
grpc_connectivity_state *state,
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ typedef void (*grpc_lb_completion)(void *cb_arg, grpc_subchannel *subchannel,
|
|||
|
||||
struct grpc_lb_policy {
|
||||
const grpc_lb_policy_vtable *vtable;
|
||||
gpr_refcount refs;
|
||||
gpr_atm ref_pair;
|
||||
grpc_pollset_set interested_parties;
|
||||
};
|
||||
|
||||
struct grpc_lb_policy_vtable {
|
||||
|
|
@ -58,17 +59,16 @@ struct grpc_lb_policy_vtable {
|
|||
/** implement grpc_lb_policy_pick */
|
||||
int (*pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
|
||||
grpc_pollset *pollset, grpc_metadata_batch *initial_metadata,
|
||||
grpc_subchannel **target, grpc_closure *on_complete);
|
||||
grpc_connected_subchannel **target, grpc_closure *on_complete);
|
||||
void (*cancel_pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
|
||||
grpc_subchannel **target);
|
||||
grpc_connected_subchannel **target);
|
||||
|
||||
void (*ping_one)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
|
||||
grpc_closure *closure);
|
||||
|
||||
/** try to enter a READY connectivity state */
|
||||
void (*exit_idle)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
|
||||
|
||||
/** broadcast a transport op to all subchannels */
|
||||
void (*broadcast)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
|
||||
grpc_transport_op *op);
|
||||
|
||||
/** check the current connectivity of the lb_policy */
|
||||
grpc_connectivity_state (*check_connectivity)(grpc_exec_ctx *exec_ctx,
|
||||
grpc_lb_policy *policy);
|
||||
|
|
@ -81,29 +81,39 @@ struct grpc_lb_policy_vtable {
|
|||
grpc_closure *closure);
|
||||
};
|
||||
|
||||
/*#define GRPC_LB_POLICY_REFCOUNT_DEBUG*/
|
||||
#ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG
|
||||
#define GRPC_LB_POLICY_REF(p, r) \
|
||||
grpc_lb_policy_ref((p), __FILE__, __LINE__, (r))
|
||||
#define GRPC_LB_POLICY_UNREF(exec_ctx, p, r) \
|
||||
grpc_lb_policy_unref((exec_ctx), (p), __FILE__, __LINE__, (r))
|
||||
#define GRPC_LB_POLICY_WEAK_REF(p, r) \
|
||||
grpc_lb_policy_weak_ref((p), __FILE__, __LINE__, (r))
|
||||
#define GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, p, r) \
|
||||
grpc_lb_policy_weak_unref((exec_ctx), (p), __FILE__, __LINE__, (r))
|
||||
void grpc_lb_policy_ref(grpc_lb_policy *policy, const char *file, int line,
|
||||
const char *reason);
|
||||
void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
|
||||
const char *file, int line, const char *reason);
|
||||
void grpc_lb_policy_weak_ref(grpc_lb_policy *policy, const char *file, int line,
|
||||
const char *reason);
|
||||
void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
|
||||
const char *file, int line, const char *reason);
|
||||
#else
|
||||
#define GRPC_LB_POLICY_REF(p, r) grpc_lb_policy_ref((p))
|
||||
#define GRPC_LB_POLICY_UNREF(cl, p, r) grpc_lb_policy_unref((cl), (p))
|
||||
#define GRPC_LB_POLICY_WEAK_REF(p, r) grpc_lb_policy_weak_ref((p))
|
||||
#define GRPC_LB_POLICY_WEAK_UNREF(cl, p, r) grpc_lb_policy_weak_unref((cl), (p))
|
||||
void grpc_lb_policy_ref(grpc_lb_policy *policy);
|
||||
void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
|
||||
void grpc_lb_policy_weak_ref(grpc_lb_policy *policy);
|
||||
void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
|
||||
#endif
|
||||
|
||||
/** called by concrete implementations to initialize the base struct */
|
||||
void grpc_lb_policy_init(grpc_lb_policy *policy,
|
||||
const grpc_lb_policy_vtable *vtable);
|
||||
|
||||
/** Start shutting down (fail any pending picks) */
|
||||
void grpc_lb_policy_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
|
||||
|
||||
/** Given initial metadata in \a initial_metadata, find an appropriate
|
||||
target for this rpc, and 'return' it by calling \a on_complete after setting
|
||||
\a target.
|
||||
|
|
@ -111,13 +121,14 @@ void grpc_lb_policy_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
|
|||
int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
|
||||
grpc_pollset *pollset,
|
||||
grpc_metadata_batch *initial_metadata,
|
||||
grpc_subchannel **target, grpc_closure *on_complete);
|
||||
grpc_connected_subchannel **target,
|
||||
grpc_closure *on_complete);
|
||||
|
||||
void grpc_lb_policy_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
|
||||
grpc_closure *closure);
|
||||
|
||||
void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
|
||||
grpc_subchannel **target);
|
||||
|
||||
void grpc_lb_policy_broadcast(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
|
||||
grpc_transport_op *op);
|
||||
grpc_connected_subchannel **target);
|
||||
|
||||
void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
|
||||
|
||||
|
|
|
|||
|
|
@ -71,11 +71,8 @@ void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
|
|||
}
|
||||
|
||||
void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
|
||||
grpc_resolver *resolver,
|
||||
struct sockaddr *failing_address,
|
||||
int failing_address_len) {
|
||||
resolver->vtable->channel_saw_error(exec_ctx, resolver, failing_address,
|
||||
failing_address_len);
|
||||
grpc_resolver *resolver) {
|
||||
resolver->vtable->channel_saw_error(exec_ctx, resolver);
|
||||
}
|
||||
|
||||
void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@
|
|||
#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_RESOLVER_H
|
||||
|
||||
#include "src/core/client_config/client_config.h"
|
||||
#include "src/core/client_config/subchannel.h"
|
||||
#include "src/core/iomgr/iomgr.h"
|
||||
#include "src/core/iomgr/sockaddr.h"
|
||||
|
||||
typedef struct grpc_resolver grpc_resolver;
|
||||
typedef struct grpc_resolver_vtable grpc_resolver_vtable;
|
||||
|
|
@ -51,9 +51,7 @@ struct grpc_resolver {
|
|||
struct grpc_resolver_vtable {
|
||||
void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
|
||||
void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
|
||||
void (*channel_saw_error)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
|
||||
struct sockaddr *failing_address,
|
||||
int failing_address_len);
|
||||
void (*channel_saw_error)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
|
||||
void (*next)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
|
||||
grpc_client_config **target_config, grpc_closure *on_complete);
|
||||
};
|
||||
|
|
@ -81,9 +79,7 @@ void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
|
|||
/** Notification that the channel has seen an error on some address.
|
||||
Can be used as a hint that re-resolution is desirable soon. */
|
||||
void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
|
||||
grpc_resolver *resolver,
|
||||
struct sockaddr *failing_address,
|
||||
int failing_address_len);
|
||||
grpc_resolver *resolver);
|
||||
|
||||
/** Get the next client config. Called by the channel to fetch a new
|
||||
configuration. Expected to set *target_config with a new configuration,
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@
|
|||
#include <grpc/support/string_util.h>
|
||||
|
||||
#include "src/core/client_config/lb_policy_registry.h"
|
||||
#include "src/core/client_config/subchannel_factory_decorators/add_channel_arg.h"
|
||||
#include "src/core/iomgr/resolve_address.h"
|
||||
#include "src/core/support/string.h"
|
||||
|
||||
|
|
@ -81,9 +80,7 @@ static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
|
|||
dns_resolver *r);
|
||||
|
||||
static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
|
||||
static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
|
||||
struct sockaddr *failing_address,
|
||||
int failing_address_len);
|
||||
static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
|
||||
static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
|
||||
grpc_client_config **target_config,
|
||||
grpc_closure *on_complete);
|
||||
|
|
@ -103,8 +100,7 @@ static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
|
|||
}
|
||||
|
||||
static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx,
|
||||
grpc_resolver *resolver, struct sockaddr *sa,
|
||||
int len) {
|
||||
grpc_resolver *resolver) {
|
||||
dns_resolver *r = (dns_resolver *)resolver;
|
||||
gpr_mu_lock(&r->mu);
|
||||
if (!r->resolving) {
|
||||
|
|
|
|||
|
|
@ -83,9 +83,7 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
|
|||
|
||||
static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
|
||||
static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
|
||||
grpc_resolver *r,
|
||||
struct sockaddr *failing_address,
|
||||
int failing_address_len);
|
||||
grpc_resolver *r);
|
||||
static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
|
||||
grpc_client_config **target_config,
|
||||
grpc_closure *on_complete);
|
||||
|
|
@ -107,8 +105,13 @@ static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx,
|
|||
}
|
||||
|
||||
static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
|
||||
grpc_resolver *resolver,
|
||||
struct sockaddr *sa, int len) {}
|
||||
grpc_resolver *resolver) {
|
||||
sockaddr_resolver *r = (sockaddr_resolver *)resolver;
|
||||
gpr_mu_lock(&r->mu);
|
||||
r->published = 0;
|
||||
sockaddr_maybe_finish_next_locked(exec_ctx, r);
|
||||
gpr_mu_unlock(&r->mu);
|
||||
}
|
||||
|
||||
static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
|
||||
grpc_client_config **target_config,
|
||||
|
|
@ -344,6 +347,9 @@ static grpc_resolver *sockaddr_create(
|
|||
gpr_slice_buffer_destroy(&path_parts);
|
||||
gpr_slice_unref(path_slice);
|
||||
if (errors_found) {
|
||||
gpr_free(r->lb_policy_name);
|
||||
gpr_free(r->addrs);
|
||||
gpr_free(r->addrs_len);
|
||||
gpr_free(r);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,9 +96,7 @@ static void zookeeper_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
|
|||
|
||||
static void zookeeper_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
|
||||
static void zookeeper_channel_saw_error(grpc_exec_ctx *exec_ctx,
|
||||
grpc_resolver *r,
|
||||
struct sockaddr *failing_address,
|
||||
int failing_address_len);
|
||||
grpc_resolver *r);
|
||||
static void zookeeper_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
|
||||
grpc_client_config **target_config,
|
||||
grpc_closure *on_complete);
|
||||
|
|
@ -125,8 +123,7 @@ static void zookeeper_shutdown(grpc_exec_ctx *exec_ctx,
|
|||
}
|
||||
|
||||
static void zookeeper_channel_saw_error(grpc_exec_ctx *exec_ctx,
|
||||
grpc_resolver *resolver,
|
||||
struct sockaddr *sa, int len) {
|
||||
grpc_resolver *resolver) {
|
||||
zookeeper_resolver *r = (zookeeper_resolver *)resolver;
|
||||
gpr_mu_lock(&r->mu);
|
||||
if (r->resolving == 0) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -41,6 +41,7 @@
|
|||
/** A (sub-)channel that knows how to connect to exactly one target
|
||||
address. Provides a target for load balancing. */
|
||||
typedef struct grpc_subchannel grpc_subchannel;
|
||||
typedef struct grpc_connected_subchannel grpc_connected_subchannel;
|
||||
typedef struct grpc_subchannel_call grpc_subchannel_call;
|
||||
typedef struct grpc_subchannel_args grpc_subchannel_args;
|
||||
|
||||
|
|
@ -49,6 +50,14 @@ typedef struct grpc_subchannel_args grpc_subchannel_args;
|
|||
grpc_subchannel_ref((p), __FILE__, __LINE__, (r))
|
||||
#define GRPC_SUBCHANNEL_UNREF(cl, p, r) \
|
||||
grpc_subchannel_unref((cl), (p), __FILE__, __LINE__, (r))
|
||||
#define GRPC_SUBCHANNEL_WEAK_REF(p, r) \
|
||||
grpc_subchannel_weak_ref((p), __FILE__, __LINE__, (r))
|
||||
#define GRPC_SUBCHANNEL_WEAK_UNREF(cl, p, r) \
|
||||
grpc_subchannel_weak_unref((cl), (p), __FILE__, __LINE__, (r))
|
||||
#define GRPC_CONNECTED_SUBCHANNEL_REF(p, r) \
|
||||
grpc_connected_subchannel_ref((p), __FILE__, __LINE__, (r))
|
||||
#define GRPC_CONNECTED_SUBCHANNEL_UNREF(cl, p, r) \
|
||||
grpc_connected_subchannel_unref((cl), (p), __FILE__, __LINE__, (r))
|
||||
#define GRPC_SUBCHANNEL_CALL_REF(p, r) \
|
||||
grpc_subchannel_call_ref((p), __FILE__, __LINE__, (r))
|
||||
#define GRPC_SUBCHANNEL_CALL_UNREF(cl, p, r) \
|
||||
|
|
@ -58,6 +67,12 @@ typedef struct grpc_subchannel_args grpc_subchannel_args;
|
|||
#else
|
||||
#define GRPC_SUBCHANNEL_REF(p, r) grpc_subchannel_ref((p))
|
||||
#define GRPC_SUBCHANNEL_UNREF(cl, p, r) grpc_subchannel_unref((cl), (p))
|
||||
#define GRPC_SUBCHANNEL_WEAK_REF(p, r) grpc_subchannel_weak_ref((p))
|
||||
#define GRPC_SUBCHANNEL_WEAK_UNREF(cl, p, r) \
|
||||
grpc_subchannel_weak_unref((cl), (p))
|
||||
#define GRPC_CONNECTED_SUBCHANNEL_REF(p, r) grpc_connected_subchannel_ref((p))
|
||||
#define GRPC_CONNECTED_SUBCHANNEL_UNREF(cl, p, r) \
|
||||
grpc_connected_subchannel_unref((cl), (p))
|
||||
#define GRPC_SUBCHANNEL_CALL_REF(p, r) grpc_subchannel_call_ref((p))
|
||||
#define GRPC_SUBCHANNEL_CALL_UNREF(cl, p, r) \
|
||||
grpc_subchannel_call_unref((cl), (p))
|
||||
|
|
@ -69,33 +84,31 @@ void grpc_subchannel_ref(grpc_subchannel *channel
|
|||
void grpc_subchannel_unref(grpc_exec_ctx *exec_ctx,
|
||||
grpc_subchannel *channel
|
||||
GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
|
||||
void grpc_subchannel_weak_ref(grpc_subchannel *channel
|
||||
GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
|
||||
void grpc_subchannel_weak_unref(grpc_exec_ctx *exec_ctx,
|
||||
grpc_subchannel *channel
|
||||
GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
|
||||
void grpc_connected_subchannel_ref(grpc_connected_subchannel *channel
|
||||
GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
|
||||
void grpc_connected_subchannel_unref(grpc_exec_ctx *exec_ctx,
|
||||
grpc_connected_subchannel *channel
|
||||
GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
|
||||
void grpc_subchannel_call_ref(grpc_subchannel_call *call
|
||||
GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
|
||||
void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx,
|
||||
grpc_subchannel_call *call
|
||||
GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
|
||||
|
||||
/** construct a subchannel call (possibly asynchronously).
|
||||
*
|
||||
* If the returned status is 1, the call will return immediately and \a target
|
||||
* will point to a connected \a subchannel_call instance. Note that \a notify
|
||||
* will \em not be invoked in this case.
|
||||
* Otherwise, if the returned status is 0, the subchannel call will be created
|
||||
* asynchronously, invoking the \a notify callback upon completion. */
|
||||
int grpc_subchannel_create_call(grpc_exec_ctx *exec_ctx,
|
||||
grpc_subchannel *subchannel,
|
||||
grpc_pollset *pollset, gpr_atm *target,
|
||||
grpc_closure *notify);
|
||||
|
||||
/** cancel \a call in the waiting state. */
|
||||
void grpc_subchannel_cancel_create_call(grpc_exec_ctx *exec_ctx,
|
||||
grpc_subchannel *subchannel,
|
||||
gpr_atm *target);
|
||||
/** construct a subchannel call */
|
||||
grpc_subchannel_call *grpc_connected_subchannel_create_call(
|
||||
grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *connected_subchannel,
|
||||
grpc_pollset *pollset);
|
||||
|
||||
/** process a transport level op */
|
||||
void grpc_subchannel_process_transport_op(grpc_exec_ctx *exec_ctx,
|
||||
grpc_subchannel *subchannel,
|
||||
grpc_transport_op *op);
|
||||
void grpc_connected_subchannel_process_transport_op(
|
||||
grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *subchannel,
|
||||
grpc_transport_op *op);
|
||||
|
||||
/** poll the current connectivity state of a channel */
|
||||
grpc_connectivity_state grpc_subchannel_check_connectivity(
|
||||
|
|
@ -103,26 +116,22 @@ grpc_connectivity_state grpc_subchannel_check_connectivity(
|
|||
|
||||
/** call notify when the connectivity state of a channel changes 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_connectivity_state *state,
|
||||
grpc_closure *notify);
|
||||
void grpc_subchannel_notify_on_state_change(
|
||||
grpc_exec_ctx *exec_ctx, grpc_subchannel *channel,
|
||||
grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
|
||||
grpc_closure *notify);
|
||||
void grpc_connected_subchannel_notify_on_state_change(
|
||||
grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *channel,
|
||||
grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
|
||||
grpc_closure *notify);
|
||||
void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx,
|
||||
grpc_connected_subchannel *channel,
|
||||
grpc_closure *notify);
|
||||
|
||||
/** Remove \a subscribed_notify from the list of closures to be called on a
|
||||
* state change if present, returning 1. Otherwise, nothing is done and return
|
||||
* 0. */
|
||||
int grpc_subchannel_state_change_unsubscribe(grpc_exec_ctx *exec_ctx,
|
||||
grpc_subchannel *channel,
|
||||
grpc_closure *subscribed_notify);
|
||||
|
||||
/** express interest in \a channel's activities through \a pollset. */
|
||||
void grpc_subchannel_add_interested_party(grpc_exec_ctx *exec_ctx,
|
||||
grpc_subchannel *channel,
|
||||
grpc_pollset *pollset);
|
||||
/** stop following \a channel's activity through \a pollset. */
|
||||
void grpc_subchannel_del_interested_party(grpc_exec_ctx *exec_ctx,
|
||||
grpc_subchannel *channel,
|
||||
grpc_pollset *pollset);
|
||||
/** retrieve the grpc_connected_subchannel - or NULL if called before
|
||||
the subchannel becomes connected */
|
||||
grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel(
|
||||
grpc_subchannel *subchannel);
|
||||
|
||||
/** continue processing a transport op */
|
||||
void grpc_subchannel_call_process_op(grpc_exec_ctx *exec_ctx,
|
||||
|
|
@ -147,20 +156,10 @@ struct grpc_subchannel_args {
|
|||
/** Address to connect to */
|
||||
struct sockaddr *addr;
|
||||
size_t addr_len;
|
||||
/** metadata context to use */
|
||||
grpc_mdctx *mdctx;
|
||||
/** master channel */
|
||||
grpc_channel *master;
|
||||
};
|
||||
|
||||
/** create a subchannel given a connector */
|
||||
grpc_subchannel *grpc_subchannel_create(grpc_connector *connector,
|
||||
grpc_subchannel_args *args);
|
||||
|
||||
/** Return the metadata context associated with the subchannel */
|
||||
grpc_mdctx *grpc_subchannel_get_mdctx(grpc_subchannel *subchannel);
|
||||
|
||||
/** Return the master channel associated with the subchannel */
|
||||
grpc_channel *grpc_subchannel_get_master(grpc_subchannel *subchannel);
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_H */
|
||||
|
|
|
|||
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "src/core/client_config/subchannel_factory_decorators/merge_channel_args.h"
|
||||
#include <grpc/support/alloc.h>
|
||||
#include "src/core/channel/channel_args.h"
|
||||
|
||||
typedef struct {
|
||||
grpc_subchannel_factory base;
|
||||
gpr_refcount refs;
|
||||
grpc_subchannel_factory *wrapped;
|
||||
grpc_channel_args *merge_args;
|
||||
} merge_args_factory;
|
||||
|
||||
static void merge_args_factory_ref(grpc_subchannel_factory *scf) {
|
||||
merge_args_factory *f = (merge_args_factory *)scf;
|
||||
gpr_ref(&f->refs);
|
||||
}
|
||||
|
||||
static void merge_args_factory_unref(grpc_exec_ctx *exec_ctx,
|
||||
grpc_subchannel_factory *scf) {
|
||||
merge_args_factory *f = (merge_args_factory *)scf;
|
||||
if (gpr_unref(&f->refs)) {
|
||||
grpc_subchannel_factory_unref(exec_ctx, f->wrapped);
|
||||
grpc_channel_args_destroy(f->merge_args);
|
||||
gpr_free(f);
|
||||
}
|
||||
}
|
||||
|
||||
static grpc_subchannel *merge_args_factory_create_subchannel(
|
||||
grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf,
|
||||
grpc_subchannel_args *args) {
|
||||
merge_args_factory *f = (merge_args_factory *)scf;
|
||||
grpc_channel_args *final_args =
|
||||
grpc_channel_args_merge(args->args, f->merge_args);
|
||||
grpc_subchannel *s;
|
||||
args->args = final_args;
|
||||
s = grpc_subchannel_factory_create_subchannel(exec_ctx, f->wrapped, args);
|
||||
grpc_channel_args_destroy(final_args);
|
||||
return s;
|
||||
}
|
||||
|
||||
static const grpc_subchannel_factory_vtable merge_args_factory_vtable = {
|
||||
merge_args_factory_ref, merge_args_factory_unref,
|
||||
merge_args_factory_create_subchannel};
|
||||
|
||||
grpc_subchannel_factory *grpc_subchannel_factory_merge_channel_args(
|
||||
grpc_subchannel_factory *input, const grpc_channel_args *args) {
|
||||
merge_args_factory *f = gpr_malloc(sizeof(*f));
|
||||
f->base.vtable = &merge_args_factory_vtable;
|
||||
gpr_ref_init(&f->refs, 1);
|
||||
grpc_subchannel_factory_ref(input);
|
||||
f->wrapped = input;
|
||||
f->merge_args = grpc_channel_args_copy(args);
|
||||
return &f->base;
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_MERGE_CHANNEL_ARGS_H
|
||||
#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_MERGE_CHANNEL_ARGS_H
|
||||
|
||||
#include "src/core/client_config/subchannel_factory.h"
|
||||
|
||||
/** Takes a subchannel factory, returns a new one that mutates incoming
|
||||
channel_args by adding a new argument; ownership of input, args is retained
|
||||
by the caller. */
|
||||
grpc_subchannel_factory *grpc_subchannel_factory_merge_channel_args(
|
||||
grpc_subchannel_factory *input, const grpc_channel_args *args);
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_MERGE_CHANNEL_ARGS_H \
|
||||
*/
|
||||
|
|
@ -37,7 +37,9 @@
|
|||
#include <grpc/compression.h>
|
||||
#include <grpc/support/useful.h>
|
||||
|
||||
#include "src/core/compression/algorithm_metadata.h"
|
||||
#include "src/core/surface/api_trace.h"
|
||||
#include "src/core/transport/static_metadata.h"
|
||||
|
||||
int grpc_compression_algorithm_parse(const char *name, size_t name_length,
|
||||
grpc_compression_algorithm *algorithm) {
|
||||
|
|
@ -72,17 +74,55 @@ int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
|
|||
switch (algorithm) {
|
||||
case GRPC_COMPRESS_NONE:
|
||||
*name = "identity";
|
||||
break;
|
||||
return 1;
|
||||
case GRPC_COMPRESS_DEFLATE:
|
||||
*name = "deflate";
|
||||
break;
|
||||
return 1;
|
||||
case GRPC_COMPRESS_GZIP:
|
||||
*name = "gzip";
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
case GRPC_COMPRESS_ALGORITHMS_COUNT:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
|
||||
grpc_mdstr *str) {
|
||||
if (str == GRPC_MDSTR_IDENTITY) return GRPC_COMPRESS_NONE;
|
||||
if (str == GRPC_MDSTR_DEFLATE) return GRPC_COMPRESS_DEFLATE;
|
||||
if (str == GRPC_MDSTR_GZIP) return GRPC_COMPRESS_GZIP;
|
||||
return GRPC_COMPRESS_ALGORITHMS_COUNT;
|
||||
}
|
||||
|
||||
grpc_mdstr *grpc_compression_algorithm_mdstr(
|
||||
grpc_compression_algorithm algorithm) {
|
||||
switch (algorithm) {
|
||||
case GRPC_COMPRESS_NONE:
|
||||
return GRPC_MDSTR_IDENTITY;
|
||||
case GRPC_COMPRESS_DEFLATE:
|
||||
return GRPC_MDSTR_DEFLATE;
|
||||
case GRPC_COMPRESS_GZIP:
|
||||
return GRPC_MDSTR_GZIP;
|
||||
case GRPC_COMPRESS_ALGORITHMS_COUNT:
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
grpc_mdelem *grpc_compression_encoding_mdelem(
|
||||
grpc_compression_algorithm algorithm) {
|
||||
switch (algorithm) {
|
||||
case GRPC_COMPRESS_NONE:
|
||||
return GRPC_MDELEM_GRPC_ENCODING_IDENTITY;
|
||||
case GRPC_COMPRESS_DEFLATE:
|
||||
return GRPC_MDELEM_GRPC_ENCODING_DEFLATE;
|
||||
case GRPC_COMPRESS_GZIP:
|
||||
return GRPC_MDELEM_GRPC_ENCODING_GZIP;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* TODO(dgq): Add the ability to specify parameters to the individual
|
||||
|
|
@ -99,25 +139,9 @@ grpc_compression_algorithm grpc_compression_algorithm_for_level(
|
|||
case GRPC_COMPRESS_LEVEL_HIGH:
|
||||
return GRPC_COMPRESS_DEFLATE;
|
||||
default:
|
||||
/* we shouldn't be making it here */
|
||||
abort();
|
||||
return GRPC_COMPRESS_NONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
grpc_compression_level grpc_compression_level_for_algorithm(
|
||||
grpc_compression_algorithm algorithm) {
|
||||
grpc_compression_level clevel;
|
||||
GRPC_API_TRACE("grpc_compression_level_for_algorithm(algorithm=%d)", 1,
|
||||
((int)algorithm));
|
||||
for (clevel = GRPC_COMPRESS_LEVEL_NONE; clevel < GRPC_COMPRESS_LEVEL_COUNT;
|
||||
++clevel) {
|
||||
if (grpc_compression_algorithm_for_level(clevel) == algorithm) {
|
||||
return clevel;
|
||||
}
|
||||
}
|
||||
abort();
|
||||
return GRPC_COMPRESS_LEVEL_NONE;
|
||||
GPR_UNREACHABLE_CODE(return GRPC_COMPRESS_NONE);
|
||||
}
|
||||
|
||||
void grpc_compression_options_init(grpc_compression_options *opts) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRPC_INTERNAL_CORE_COMPRESSION_ALGORITHM_METADATA_H
|
||||
#define GRPC_INTERNAL_CORE_COMPRESSION_ALGORITHM_METADATA_H
|
||||
|
||||
#include <grpc/compression.h>
|
||||
#include "src/core/transport/metadata.h"
|
||||
|
||||
/** Return compression algorithm based metadata value */
|
||||
grpc_mdstr *grpc_compression_algorithm_mdstr(
|
||||
grpc_compression_algorithm algorithm);
|
||||
|
||||
/** Return compression algorithm based metadata element (grpc-encoding: xxx) */
|
||||
grpc_mdelem *grpc_compression_encoding_mdelem(
|
||||
grpc_compression_algorithm algorithm);
|
||||
|
||||
/** Find compression algorithm based on passed in mdstr - returns
|
||||
* GRPC_COMPRESS_ALGORITHM_COUNT on failure */
|
||||
grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
|
||||
grpc_mdstr *str);
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_COMPRESSION_ALGORITHM_METADATA_H */
|
||||
|
|
@ -69,8 +69,8 @@ static int zlib_body(z_stream* zs, gpr_slice_buffer* input,
|
|||
zs->next_out = GPR_SLICE_START_PTR(outbuf);
|
||||
}
|
||||
r = flate(zs, flush);
|
||||
if (r == Z_STREAM_ERROR) {
|
||||
gpr_log(GPR_INFO, "zlib: stream error");
|
||||
if (r < 0 && r != Z_BUF_ERROR /* not fatal */) {
|
||||
gpr_log(GPR_INFO, "zlib error (%d)", r);
|
||||
goto error;
|
||||
}
|
||||
} while (zs->avail_out == 0);
|
||||
|
|
@ -91,6 +91,12 @@ error:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void* zalloc_gpr(void* opaque, unsigned int items, unsigned int size) {
|
||||
return gpr_malloc(items * size);
|
||||
}
|
||||
|
||||
static void zfree_gpr(void* opaque, void* address) { gpr_free(address); }
|
||||
|
||||
static int zlib_compress(gpr_slice_buffer* input, gpr_slice_buffer* output,
|
||||
int gzip) {
|
||||
z_stream zs;
|
||||
|
|
@ -99,12 +105,11 @@ static int zlib_compress(gpr_slice_buffer* input, gpr_slice_buffer* output,
|
|||
size_t count_before = output->count;
|
||||
size_t length_before = output->length;
|
||||
memset(&zs, 0, sizeof(zs));
|
||||
zs.zalloc = zalloc_gpr;
|
||||
zs.zfree = zfree_gpr;
|
||||
r = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 | (gzip ? 16 : 0),
|
||||
8, Z_DEFAULT_STRATEGY);
|
||||
if (r != Z_OK) {
|
||||
gpr_log(GPR_ERROR, "deflateInit2 returns %d", r);
|
||||
return 0;
|
||||
}
|
||||
GPR_ASSERT(r == Z_OK);
|
||||
r = zlib_body(&zs, input, output, deflate) && output->length < input->length;
|
||||
if (!r) {
|
||||
for (i = count_before; i < output->count; i++) {
|
||||
|
|
@ -125,11 +130,10 @@ static int zlib_decompress(gpr_slice_buffer* input, gpr_slice_buffer* output,
|
|||
size_t count_before = output->count;
|
||||
size_t length_before = output->length;
|
||||
memset(&zs, 0, sizeof(zs));
|
||||
zs.zalloc = zalloc_gpr;
|
||||
zs.zfree = zfree_gpr;
|
||||
r = inflateInit2(&zs, 15 | (gzip ? 16 : 0));
|
||||
if (r != Z_OK) {
|
||||
gpr_log(GPR_ERROR, "inflateInit2 returns %d", r);
|
||||
return 0;
|
||||
}
|
||||
GPR_ASSERT(r == Z_OK);
|
||||
r = zlib_body(&zs, input, output, inflate);
|
||||
if (!r) {
|
||||
for (i = count_before; i < output->count; i++) {
|
||||
|
|
@ -150,8 +154,8 @@ static int copy(gpr_slice_buffer* input, gpr_slice_buffer* output) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int compress_inner(grpc_compression_algorithm algorithm,
|
||||
gpr_slice_buffer* input, gpr_slice_buffer* output) {
|
||||
static int compress_inner(grpc_compression_algorithm algorithm,
|
||||
gpr_slice_buffer* input, gpr_slice_buffer* output) {
|
||||
switch (algorithm) {
|
||||
case GRPC_COMPRESS_NONE:
|
||||
/* the fallback path always needs to be send uncompressed: we simply
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ typedef struct {
|
|||
size_t next_address;
|
||||
grpc_endpoint *ep;
|
||||
char *host;
|
||||
char *ssl_host_override;
|
||||
gpr_timespec deadline;
|
||||
int have_read_byte;
|
||||
const grpc_httpcli_handshaker *handshaker;
|
||||
|
|
@ -106,6 +107,7 @@ static void finish(grpc_exec_ctx *exec_ctx, internal_request *req,
|
|||
}
|
||||
gpr_slice_unref(req->request_text);
|
||||
gpr_free(req->host);
|
||||
gpr_free(req->ssl_host_override);
|
||||
grpc_iomgr_unregister_object(&req->iomgr_obj);
|
||||
gpr_slice_buffer_destroy(&req->incoming);
|
||||
gpr_slice_buffer_destroy(&req->outgoing);
|
||||
|
|
@ -180,8 +182,10 @@ static void on_connected(grpc_exec_ctx *exec_ctx, void *arg, int success) {
|
|||
next_address(exec_ctx, req);
|
||||
return;
|
||||
}
|
||||
req->handshaker->handshake(exec_ctx, req, req->ep, req->host,
|
||||
on_handshake_done);
|
||||
req->handshaker->handshake(
|
||||
exec_ctx, req, req->ep,
|
||||
req->ssl_host_override ? req->ssl_host_override : req->host,
|
||||
on_handshake_done);
|
||||
}
|
||||
|
||||
static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req) {
|
||||
|
|
@ -231,6 +235,7 @@ static void internal_request_begin(
|
|||
gpr_slice_buffer_init(&req->outgoing);
|
||||
grpc_iomgr_register_object(&req->iomgr_obj, name);
|
||||
req->host = gpr_strdup(request->host);
|
||||
req->ssl_host_override = gpr_strdup(request->ssl_host_override);
|
||||
|
||||
grpc_pollset_set_add_pollset(exec_ctx, &req->context->pollset_set,
|
||||
req->pollset);
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ extern const grpc_httpcli_handshaker grpc_httpcli_ssl;
|
|||
typedef struct grpc_httpcli_request {
|
||||
/* The host name to connect to */
|
||||
char *host;
|
||||
/* The host to verify in the SSL handshake (or NULL) */
|
||||
char *ssl_host_override;
|
||||
/* The path of the resource to fetch */
|
||||
char *path;
|
||||
/* Additional headers: count and key/values; the following are supplied
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ static void httpcli_ssl_do_handshake(grpc_exec_ctx *exec_ctx,
|
|||
tsi_result result = TSI_OK;
|
||||
tsi_handshaker *handshaker;
|
||||
if (c->handshaker_factory == NULL) {
|
||||
cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, nonsecure_endpoint, NULL);
|
||||
cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
|
||||
return;
|
||||
}
|
||||
result = tsi_ssl_handshaker_factory_create_handshaker(
|
||||
|
|
@ -76,17 +76,18 @@ static void httpcli_ssl_do_handshake(grpc_exec_ctx *exec_ctx,
|
|||
if (result != TSI_OK) {
|
||||
gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
|
||||
tsi_result_to_string(result));
|
||||
cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, nonsecure_endpoint, NULL);
|
||||
cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
|
||||
} else {
|
||||
grpc_do_security_handshake(exec_ctx, handshaker, sc, nonsecure_endpoint, cb,
|
||||
user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static grpc_security_status httpcli_ssl_check_peer(grpc_security_connector *sc,
|
||||
tsi_peer peer,
|
||||
grpc_security_check_cb cb,
|
||||
void *user_data) {
|
||||
static void httpcli_ssl_check_peer(grpc_exec_ctx *exec_ctx,
|
||||
grpc_security_connector *sc,
|
||||
tsi_peer peer,
|
||||
grpc_security_peer_check_cb cb,
|
||||
void *user_data) {
|
||||
grpc_httpcli_ssl_channel_security_connector *c =
|
||||
(grpc_httpcli_ssl_channel_security_connector *)sc;
|
||||
grpc_security_status status = GRPC_SECURITY_OK;
|
||||
|
|
@ -98,8 +99,8 @@ static grpc_security_status httpcli_ssl_check_peer(grpc_security_connector *sc,
|
|||
c->secure_peer_name);
|
||||
status = GRPC_SECURITY_ERROR;
|
||||
}
|
||||
cb(exec_ctx, user_data, status, NULL);
|
||||
tsi_peer_destruct(&peer);
|
||||
return status;
|
||||
}
|
||||
|
||||
static grpc_security_connector_vtable httpcli_ssl_vtable = {
|
||||
|
|
@ -149,8 +150,8 @@ typedef struct {
|
|||
|
||||
static void on_secure_transport_setup_done(grpc_exec_ctx *exec_ctx, void *rp,
|
||||
grpc_security_status status,
|
||||
grpc_endpoint *wrapped_endpoint,
|
||||
grpc_endpoint *secure_endpoint) {
|
||||
grpc_endpoint *secure_endpoint,
|
||||
grpc_auth_context *auth_context) {
|
||||
on_done_closure *c = rp;
|
||||
if (status != GRPC_SECURITY_OK) {
|
||||
gpr_log(GPR_ERROR, "Secure transport setup failed with error %d.", status);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#ifdef GPR_POSIX_SOCKET
|
||||
|
||||
#include "src/core/iomgr/endpoint_pair.h"
|
||||
#include "src/core/iomgr/socket_utils_posix.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
|
@ -56,6 +57,8 @@ static void create_sockets(int sv[2]) {
|
|||
GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0);
|
||||
flags = fcntl(sv[1], F_GETFL, 0);
|
||||
GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0);
|
||||
GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[0]));
|
||||
GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[1]));
|
||||
}
|
||||
|
||||
grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name,
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
#include <grpc/support/alloc.h>
|
||||
#include <grpc/support/log.h>
|
||||
#include <grpc/support/string_util.h>
|
||||
#include <grpc/support/useful.h>
|
||||
|
||||
#define CLOSURE_NOT_READY ((grpc_closure *)0)
|
||||
|
|
@ -158,7 +159,10 @@ void grpc_fd_global_shutdown(void) {
|
|||
|
||||
grpc_fd *grpc_fd_create(int fd, const char *name) {
|
||||
grpc_fd *r = alloc_fd(fd);
|
||||
grpc_iomgr_register_object(&r->iomgr_object, name);
|
||||
char *name2;
|
||||
gpr_asprintf(&name2, "%s fd=%d", name, fd);
|
||||
grpc_iomgr_register_object(&r->iomgr_object, name2);
|
||||
gpr_free(name2);
|
||||
#ifdef GRPC_FD_REF_COUNT_DEBUG
|
||||
gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, r, name);
|
||||
#endif
|
||||
|
|
@ -207,14 +211,21 @@ static int has_watchers(grpc_fd *fd) {
|
|||
}
|
||||
|
||||
void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
|
||||
const char *reason) {
|
||||
int *release_fd, const char *reason) {
|
||||
fd->on_done_closure = on_done;
|
||||
shutdown(fd->fd, SHUT_RDWR);
|
||||
fd->released = release_fd != NULL;
|
||||
if (!fd->released) {
|
||||
shutdown(fd->fd, SHUT_RDWR);
|
||||
} else {
|
||||
*release_fd = fd->fd;
|
||||
}
|
||||
gpr_mu_lock(&fd->mu);
|
||||
REF_BY(fd, 1, reason); /* remove active status, but keep referenced */
|
||||
if (!has_watchers(fd)) {
|
||||
fd->closed = 1;
|
||||
close(fd->fd);
|
||||
if (!fd->released) {
|
||||
close(fd->fd);
|
||||
}
|
||||
grpc_exec_ctx_enqueue(exec_ctx, fd->on_done_closure, 1);
|
||||
} else {
|
||||
wake_all_watchers_locked(fd);
|
||||
|
|
@ -406,7 +417,9 @@ void grpc_fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *watcher,
|
|||
}
|
||||
if (grpc_fd_is_orphaned(fd) && !has_watchers(fd) && !fd->closed) {
|
||||
fd->closed = 1;
|
||||
close(fd->fd);
|
||||
if (!fd->released) {
|
||||
close(fd->fd);
|
||||
}
|
||||
grpc_exec_ctx_enqueue(exec_ctx, fd->on_done_closure, 1);
|
||||
}
|
||||
gpr_mu_unlock(&fd->mu);
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ struct grpc_fd {
|
|||
gpr_mu mu;
|
||||
int shutdown;
|
||||
int closed;
|
||||
int released;
|
||||
|
||||
/* The watcher list.
|
||||
|
||||
|
|
@ -107,11 +108,12 @@ grpc_fd *grpc_fd_create(int fd, const char *name);
|
|||
/* Releases fd to be asynchronously destroyed.
|
||||
on_done is called when the underlying file descriptor is definitely close()d.
|
||||
If on_done is NULL, no callback will be made.
|
||||
If release_fd is not NULL, it's set to fd and fd will not be closed.
|
||||
Requires: *fd initialized; no outstanding notify_on_read or
|
||||
notify_on_write.
|
||||
MUST NOT be called with a pollset lock taken */
|
||||
void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
|
||||
const char *reason);
|
||||
int *release_fd, const char *reason);
|
||||
|
||||
/* Begin polling on an fd.
|
||||
Registers that the given pollset is interested in this fd - so that if read
|
||||
|
|
@ -168,6 +170,7 @@ void grpc_fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd);
|
|||
void grpc_fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd);
|
||||
|
||||
/* Reference counting for fds */
|
||||
/*#define GRPC_FD_REF_COUNT_DEBUG*/
|
||||
#ifdef GRPC_FD_REF_COUNT_DEBUG
|
||||
void grpc_fd_ref(grpc_fd *fd, const char *reason, const char *file, int line);
|
||||
void grpc_fd_unref(grpc_fd *fd, const char *reason, const char *file, int line);
|
||||
|
|
|
|||
|
|
@ -123,26 +123,6 @@ static void multipoll_with_epoll_pollset_add_fd(grpc_exec_ctx *exec_ctx,
|
|||
}
|
||||
}
|
||||
|
||||
static void multipoll_with_epoll_pollset_del_fd(grpc_exec_ctx *exec_ctx,
|
||||
grpc_pollset *pollset,
|
||||
grpc_fd *fd,
|
||||
int and_unlock_pollset) {
|
||||
pollset_hdr *h = pollset->data.ptr;
|
||||
int err;
|
||||
|
||||
if (and_unlock_pollset) {
|
||||
gpr_mu_unlock(&pollset->mu);
|
||||
}
|
||||
|
||||
/* Note that this can race with concurrent poll, but that should be fine since
|
||||
* at worst it creates a spurious read event on a reused grpc_fd object. */
|
||||
err = epoll_ctl(h->epoll_fd, EPOLL_CTL_DEL, fd->fd, NULL);
|
||||
if (err < 0) {
|
||||
gpr_log(GPR_ERROR, "epoll_ctl del for %d failed: %s", fd->fd,
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO(klempner): We probably want to turn this down a bit */
|
||||
#define GRPC_EPOLL_MAX_EVENTS 1000
|
||||
|
||||
|
|
@ -235,7 +215,7 @@ static void multipoll_with_epoll_pollset_destroy(grpc_pollset *pollset) {
|
|||
}
|
||||
|
||||
static const grpc_pollset_vtable multipoll_with_epoll_pollset = {
|
||||
multipoll_with_epoll_pollset_add_fd, multipoll_with_epoll_pollset_del_fd,
|
||||
multipoll_with_epoll_pollset_add_fd,
|
||||
multipoll_with_epoll_pollset_maybe_work_and_unlock,
|
||||
multipoll_with_epoll_pollset_finish_shutdown,
|
||||
multipoll_with_epoll_pollset_destroy};
|
||||
|
|
|
|||
|
|
@ -82,23 +82,6 @@ exit:
|
|||
}
|
||||
}
|
||||
|
||||
static void multipoll_with_poll_pollset_del_fd(grpc_exec_ctx *exec_ctx,
|
||||
grpc_pollset *pollset,
|
||||
grpc_fd *fd,
|
||||
int and_unlock_pollset) {
|
||||
/* will get removed next poll cycle */
|
||||
pollset_hdr *h = pollset->data.ptr;
|
||||
if (h->del_count == h->del_capacity) {
|
||||
h->del_capacity = GPR_MAX(h->del_capacity + 8, h->del_count * 3 / 2);
|
||||
h->dels = gpr_realloc(h->dels, sizeof(grpc_fd *) * h->del_capacity);
|
||||
}
|
||||
h->dels[h->del_count++] = fd;
|
||||
GRPC_FD_REF(fd, "multipoller_del");
|
||||
if (and_unlock_pollset) {
|
||||
gpr_mu_unlock(&pollset->mu);
|
||||
}
|
||||
}
|
||||
|
||||
static void multipoll_with_poll_pollset_maybe_work_and_unlock(
|
||||
grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker,
|
||||
gpr_timespec deadline, gpr_timespec now) {
|
||||
|
|
@ -212,7 +195,7 @@ static void multipoll_with_poll_pollset_destroy(grpc_pollset *pollset) {
|
|||
}
|
||||
|
||||
static const grpc_pollset_vtable multipoll_with_poll_pollset = {
|
||||
multipoll_with_poll_pollset_add_fd, multipoll_with_poll_pollset_del_fd,
|
||||
multipoll_with_poll_pollset_add_fd,
|
||||
multipoll_with_poll_pollset_maybe_work_and_unlock,
|
||||
multipoll_with_poll_pollset_finish_shutdown,
|
||||
multipoll_with_poll_pollset_destroy};
|
||||
|
|
|
|||
|
|
@ -232,21 +232,7 @@ void grpc_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
|
|||
gpr_mu_lock(&pollset->mu);
|
||||
pollset->vtable->add_fd(exec_ctx, pollset, fd, 1);
|
||||
/* the following (enabled only in debug) will reacquire and then release
|
||||
our lock - meaning that if the unlocking flag passed to del_fd above is
|
||||
not respected, the code will deadlock (in a way that we have a chance of
|
||||
debugging) */
|
||||
#ifndef NDEBUG
|
||||
gpr_mu_lock(&pollset->mu);
|
||||
gpr_mu_unlock(&pollset->mu);
|
||||
#endif
|
||||
}
|
||||
|
||||
void grpc_pollset_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
|
||||
grpc_fd *fd) {
|
||||
gpr_mu_lock(&pollset->mu);
|
||||
pollset->vtable->del_fd(exec_ctx, pollset, fd, 1);
|
||||
/* the following (enabled only in debug) will reacquire and then release
|
||||
our lock - meaning that if the unlocking flag passed to del_fd above is
|
||||
our lock - meaning that if the unlocking flag passed to add_fd above is
|
||||
not respected, the code will deadlock (in a way that we have a chance of
|
||||
debugging) */
|
||||
#ifndef NDEBUG
|
||||
|
|
@ -547,19 +533,6 @@ exit:
|
|||
}
|
||||
}
|
||||
|
||||
static void basic_pollset_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
|
||||
grpc_fd *fd, int and_unlock_pollset) {
|
||||
GPR_ASSERT(fd);
|
||||
if (fd == pollset->data.ptr) {
|
||||
GRPC_FD_UNREF(pollset->data.ptr, "basicpoll");
|
||||
pollset->data.ptr = NULL;
|
||||
}
|
||||
|
||||
if (and_unlock_pollset) {
|
||||
gpr_mu_unlock(&pollset->mu);
|
||||
}
|
||||
}
|
||||
|
||||
static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx,
|
||||
grpc_pollset *pollset,
|
||||
grpc_pollset_worker *worker,
|
||||
|
|
@ -613,7 +586,9 @@ static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx,
|
|||
GPR_TIMER_END("poll", 0);
|
||||
|
||||
if (r < 0) {
|
||||
gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
|
||||
if (errno != EINTR) {
|
||||
gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
|
||||
}
|
||||
if (fd) {
|
||||
grpc_fd_end_poll(exec_ctx, &fd_watcher, 0, 0);
|
||||
}
|
||||
|
|
@ -649,9 +624,8 @@ static void basic_pollset_destroy(grpc_pollset *pollset) {
|
|||
}
|
||||
|
||||
static const grpc_pollset_vtable basic_pollset = {
|
||||
basic_pollset_add_fd, basic_pollset_del_fd,
|
||||
basic_pollset_maybe_work_and_unlock, basic_pollset_destroy,
|
||||
basic_pollset_destroy};
|
||||
basic_pollset_add_fd, basic_pollset_maybe_work_and_unlock,
|
||||
basic_pollset_destroy, basic_pollset_destroy};
|
||||
|
||||
static void become_basic_pollset(grpc_pollset *pollset, grpc_fd *fd_or_null) {
|
||||
pollset->vtable = &basic_pollset;
|
||||
|
|
|
|||
|
|
@ -86,8 +86,6 @@ typedef struct grpc_pollset {
|
|||
struct grpc_pollset_vtable {
|
||||
void (*add_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
|
||||
struct grpc_fd *fd, int and_unlock_pollset);
|
||||
void (*del_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
|
||||
struct grpc_fd *fd, int and_unlock_pollset);
|
||||
void (*maybe_work_and_unlock)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
|
||||
grpc_pollset_worker *worker,
|
||||
gpr_timespec deadline, gpr_timespec now);
|
||||
|
|
@ -100,10 +98,6 @@ struct grpc_pollset_vtable {
|
|||
/* Add an fd to a pollset */
|
||||
void grpc_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
|
||||
struct grpc_fd *fd);
|
||||
/* Force remove an fd from a pollset (normally they are removed on the next
|
||||
poll after an fd is orphaned) */
|
||||
void grpc_pollset_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
|
||||
struct grpc_fd *fd);
|
||||
|
||||
/* Returns the fd to listen on for kicks */
|
||||
int grpc_kick_read_fd(grpc_pollset *p);
|
||||
|
|
|
|||
|
|
@ -49,13 +49,19 @@
|
|||
#include "src/core/iomgr/pollset_set_windows.h"
|
||||
#endif
|
||||
|
||||
void grpc_pollset_set_init(grpc_pollset_set* pollset_set);
|
||||
void grpc_pollset_set_destroy(grpc_pollset_set* pollset_set);
|
||||
void grpc_pollset_set_add_pollset(grpc_exec_ctx* exec_ctx,
|
||||
grpc_pollset_set* pollset_set,
|
||||
grpc_pollset* pollset);
|
||||
void grpc_pollset_set_del_pollset(grpc_exec_ctx* exec_ctx,
|
||||
grpc_pollset_set* pollset_set,
|
||||
grpc_pollset* pollset);
|
||||
void grpc_pollset_set_init(grpc_pollset_set *pollset_set);
|
||||
void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set);
|
||||
void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
|
||||
grpc_pollset_set *pollset_set,
|
||||
grpc_pollset *pollset);
|
||||
void grpc_pollset_set_del_pollset(grpc_exec_ctx *exec_ctx,
|
||||
grpc_pollset_set *pollset_set,
|
||||
grpc_pollset *pollset);
|
||||
void grpc_pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx,
|
||||
grpc_pollset_set *bag,
|
||||
grpc_pollset_set *item);
|
||||
void grpc_pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx,
|
||||
grpc_pollset_set *bag,
|
||||
grpc_pollset_set *item);
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_IOMGR_POLLSET_H */
|
||||
|
|
|
|||
|
|
@ -52,9 +52,10 @@ void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set) {
|
|||
size_t i;
|
||||
gpr_mu_destroy(&pollset_set->mu);
|
||||
for (i = 0; i < pollset_set->fd_count; i++) {
|
||||
GRPC_FD_UNREF(pollset_set->fds[i], "pollset");
|
||||
GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set");
|
||||
}
|
||||
gpr_free(pollset_set->pollsets);
|
||||
gpr_free(pollset_set->pollset_sets);
|
||||
gpr_free(pollset_set->fds);
|
||||
}
|
||||
|
||||
|
|
@ -73,7 +74,7 @@ void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
|
|||
pollset_set->pollsets[pollset_set->pollset_count++] = pollset;
|
||||
for (i = 0, j = 0; i < pollset_set->fd_count; i++) {
|
||||
if (grpc_fd_is_orphaned(pollset_set->fds[i])) {
|
||||
GRPC_FD_UNREF(pollset_set->fds[i], "pollset");
|
||||
GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set");
|
||||
} else {
|
||||
grpc_pollset_add_fd(exec_ctx, pollset, pollset_set->fds[i]);
|
||||
pollset_set->fds[j++] = pollset_set->fds[i];
|
||||
|
|
@ -99,6 +100,46 @@ void grpc_pollset_set_del_pollset(grpc_exec_ctx *exec_ctx,
|
|||
gpr_mu_unlock(&pollset_set->mu);
|
||||
}
|
||||
|
||||
void grpc_pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx,
|
||||
grpc_pollset_set *bag,
|
||||
grpc_pollset_set *item) {
|
||||
size_t i, j;
|
||||
gpr_mu_lock(&bag->mu);
|
||||
if (bag->pollset_set_count == bag->pollset_set_capacity) {
|
||||
bag->pollset_set_capacity = GPR_MAX(8, 2 * bag->pollset_set_capacity);
|
||||
bag->pollset_sets =
|
||||
gpr_realloc(bag->pollset_sets,
|
||||
bag->pollset_set_capacity * sizeof(*bag->pollset_sets));
|
||||
}
|
||||
bag->pollset_sets[bag->pollset_set_count++] = item;
|
||||
for (i = 0, j = 0; i < bag->fd_count; i++) {
|
||||
if (grpc_fd_is_orphaned(bag->fds[i])) {
|
||||
GRPC_FD_UNREF(bag->fds[i], "pollset_set");
|
||||
} else {
|
||||
grpc_pollset_set_add_fd(exec_ctx, item, bag->fds[i]);
|
||||
bag->fds[j++] = bag->fds[i];
|
||||
}
|
||||
}
|
||||
bag->fd_count = j;
|
||||
gpr_mu_unlock(&bag->mu);
|
||||
}
|
||||
|
||||
void grpc_pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx,
|
||||
grpc_pollset_set *bag,
|
||||
grpc_pollset_set *item) {
|
||||
size_t i;
|
||||
gpr_mu_lock(&bag->mu);
|
||||
for (i = 0; i < bag->pollset_set_count; i++) {
|
||||
if (bag->pollset_sets[i] == item) {
|
||||
bag->pollset_set_count--;
|
||||
GPR_SWAP(grpc_pollset_set *, bag->pollset_sets[i],
|
||||
bag->pollset_sets[bag->pollset_set_count]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
gpr_mu_unlock(&bag->mu);
|
||||
}
|
||||
|
||||
void grpc_pollset_set_add_fd(grpc_exec_ctx *exec_ctx,
|
||||
grpc_pollset_set *pollset_set, grpc_fd *fd) {
|
||||
size_t i;
|
||||
|
|
@ -113,6 +154,9 @@ void grpc_pollset_set_add_fd(grpc_exec_ctx *exec_ctx,
|
|||
for (i = 0; i < pollset_set->pollset_count; i++) {
|
||||
grpc_pollset_add_fd(exec_ctx, pollset_set->pollsets[i], fd);
|
||||
}
|
||||
for (i = 0; i < pollset_set->pollset_set_count; i++) {
|
||||
grpc_pollset_set_add_fd(exec_ctx, pollset_set->pollset_sets[i], fd);
|
||||
}
|
||||
gpr_mu_unlock(&pollset_set->mu);
|
||||
}
|
||||
|
||||
|
|
@ -129,6 +173,9 @@ void grpc_pollset_set_del_fd(grpc_exec_ctx *exec_ctx,
|
|||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < pollset_set->pollset_set_count; i++) {
|
||||
grpc_pollset_set_del_fd(exec_ctx, pollset_set->pollset_sets[i], fd);
|
||||
}
|
||||
gpr_mu_unlock(&pollset_set->mu);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ typedef struct grpc_pollset_set {
|
|||
size_t pollset_capacity;
|
||||
grpc_pollset **pollsets;
|
||||
|
||||
size_t pollset_set_count;
|
||||
size_t pollset_set_capacity;
|
||||
struct grpc_pollset_set **pollset_sets;
|
||||
|
||||
size_t fd_count;
|
||||
size_t fd_capacity;
|
||||
grpc_fd **fds;
|
||||
|
|
|
|||
|
|
@ -49,4 +49,12 @@ void grpc_pollset_set_del_pollset(grpc_exec_ctx* exec_ctx,
|
|||
grpc_pollset_set* pollset_set,
|
||||
grpc_pollset* pollset) {}
|
||||
|
||||
void grpc_pollset_set_add_pollset_set(grpc_exec_ctx* exec_ctx,
|
||||
grpc_pollset_set* bag,
|
||||
grpc_pollset_set* item) {}
|
||||
|
||||
void grpc_pollset_set_del_pollset_set(grpc_exec_ctx* exec_ctx,
|
||||
grpc_pollset_set* bag,
|
||||
grpc_pollset_set* item) {}
|
||||
|
||||
#endif /* GPR_WINSOCK_SOCKET */
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, int success) {
|
|||
finish:
|
||||
if (fd != NULL) {
|
||||
grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
|
||||
grpc_fd_orphan(exec_ctx, fd, NULL, "tcp_client_orphan");
|
||||
grpc_fd_orphan(exec_ctx, fd, NULL, NULL, "tcp_client_orphan");
|
||||
fd = NULL;
|
||||
}
|
||||
done = (--ac->refs == 0);
|
||||
|
|
@ -265,7 +265,7 @@ void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
|
|||
|
||||
if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
|
||||
gpr_log(GPR_ERROR, "connect error to '%s': %s", addr_str, strerror(errno));
|
||||
grpc_fd_orphan(exec_ctx, fdobj, NULL, "tcp_client_connect_error");
|
||||
grpc_fd_orphan(exec_ctx, fdobj, NULL, NULL, "tcp_client_connect_error");
|
||||
grpc_exec_ctx_enqueue(exec_ctx, closure, 0);
|
||||
goto done;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ typedef struct {
|
|||
|
||||
grpc_closure *read_cb;
|
||||
grpc_closure *write_cb;
|
||||
grpc_closure *release_fd_cb;
|
||||
int *release_fd;
|
||||
|
||||
grpc_closure read_closure;
|
||||
grpc_closure write_closure;
|
||||
|
|
@ -108,7 +110,8 @@ static void tcp_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
|
|||
}
|
||||
|
||||
static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
|
||||
grpc_fd_orphan(exec_ctx, tcp->em_fd, NULL, "tcp_unref_orphan");
|
||||
grpc_fd_orphan(exec_ctx, tcp->em_fd, tcp->release_fd_cb, tcp->release_fd,
|
||||
"tcp_unref_orphan");
|
||||
gpr_slice_buffer_destroy(&tcp->last_read_buffer);
|
||||
gpr_free(tcp->peer_string);
|
||||
gpr_free(tcp);
|
||||
|
|
@ -452,6 +455,8 @@ grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size,
|
|||
tcp->fd = em_fd->fd;
|
||||
tcp->read_cb = NULL;
|
||||
tcp->write_cb = NULL;
|
||||
tcp->release_fd_cb = NULL;
|
||||
tcp->release_fd = NULL;
|
||||
tcp->incoming_buffer = NULL;
|
||||
tcp->slice_size = slice_size;
|
||||
tcp->iov_size = 1;
|
||||
|
|
@ -468,4 +473,13 @@ grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size,
|
|||
return &tcp->base;
|
||||
}
|
||||
|
||||
void grpc_tcp_destroy_and_release_fd(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
|
||||
int *fd, grpc_closure *done) {
|
||||
grpc_tcp *tcp = (grpc_tcp *)ep;
|
||||
GPR_ASSERT(ep->vtable == &vtable);
|
||||
tcp->release_fd = fd;
|
||||
tcp->release_fd_cb = done;
|
||||
TCP_UNREF(exec_ctx, tcp, "destroy");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -56,4 +56,10 @@ extern int grpc_tcp_trace;
|
|||
grpc_endpoint *grpc_tcp_create(grpc_fd *fd, size_t read_slice_size,
|
||||
const char *peer_string);
|
||||
|
||||
/* Destroy the tcp endpoint without closing its fd. *fd will be set and done
|
||||
* will be called when the endpoint is destroyed.
|
||||
* Requires: ep must be a tcp endpoint and fd must not be NULL. */
|
||||
void grpc_tcp_destroy_and_release_fd(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
|
||||
int *fd, grpc_closure *done);
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_POSIX_H */
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
|
|||
}
|
||||
sp->destroyed_closure.cb = destroyed_port;
|
||||
sp->destroyed_closure.cb_arg = s;
|
||||
grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure,
|
||||
grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
|
||||
"tcp_listener_shutdown");
|
||||
}
|
||||
gpr_mu_unlock(&s->mu);
|
||||
|
|
@ -411,7 +411,6 @@ static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, int fd,
|
|||
|
||||
grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
|
||||
const void *addr, size_t addr_len) {
|
||||
int allocated_port = -1;
|
||||
grpc_tcp_listener *sp;
|
||||
grpc_tcp_listener *sp2 = NULL;
|
||||
int fd;
|
||||
|
|
@ -464,14 +463,13 @@ grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
|
|||
addr_len = sizeof(wild6);
|
||||
fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
|
||||
sp = add_socket_to_server(s, fd, addr, addr_len);
|
||||
allocated_port = sp->port;
|
||||
if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
|
||||
if (port == 0 && allocated_port > 0) {
|
||||
grpc_sockaddr_set_port((struct sockaddr *)&wild4, allocated_port);
|
||||
if (port == 0 && sp != NULL) {
|
||||
grpc_sockaddr_set_port((struct sockaddr *)&wild4, sp->port);
|
||||
sp2 = sp;
|
||||
}
|
||||
addr = (struct sockaddr *)&wild4;
|
||||
|
|
@ -488,8 +486,8 @@ grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
|
|||
addr_len = sizeof(addr4_copy);
|
||||
}
|
||||
sp = add_socket_to_server(s, fd, addr, addr_len);
|
||||
sp->sibling = sp2;
|
||||
if (sp2) sp2->is_sibling = 1;
|
||||
if (sp != NULL) sp->sibling = sp2;
|
||||
if (sp2 != NULL) sp2->is_sibling = 1;
|
||||
|
||||
done:
|
||||
gpr_free(allocated_addr);
|
||||
|
|
@ -534,8 +532,12 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
|
|||
}
|
||||
|
||||
int grpc_tcp_listener_get_port(grpc_tcp_listener *listener) {
|
||||
grpc_tcp_listener *sp = listener;
|
||||
return sp->port;
|
||||
if (listener != NULL) {
|
||||
grpc_tcp_listener *sp = listener;
|
||||
return sp->port;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void grpc_tcp_listener_ref(grpc_tcp_listener *listener) {
|
||||
|
|
|
|||
|
|
@ -486,8 +486,12 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
|
|||
}
|
||||
|
||||
int grpc_tcp_listener_get_port(grpc_tcp_listener *listener) {
|
||||
grpc_tcp_listener *sp = listener;
|
||||
return sp->port;
|
||||
if (listener != NULL) {
|
||||
grpc_tcp_listener *sp = listener;
|
||||
return sp->port;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void grpc_tcp_listener_ref(grpc_tcp_listener *listener) {
|
||||
|
|
|
|||
|
|
@ -197,7 +197,8 @@ static void win_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
|
|||
|
||||
tcp->read_slice = gpr_slice_malloc(8192);
|
||||
|
||||
buffer.len = GPR_SLICE_LENGTH(tcp->read_slice);
|
||||
buffer.len = (ULONG)GPR_SLICE_LENGTH(
|
||||
tcp->read_slice); // we know slice size fits in 32bit.
|
||||
buffer.buf = (char *)GPR_SLICE_START_PTR(tcp->read_slice);
|
||||
|
||||
TCP_REF(tcp, "read");
|
||||
|
|
@ -273,6 +274,7 @@ static void win_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
|
|||
WSABUF local_buffers[16];
|
||||
WSABUF *allocated = NULL;
|
||||
WSABUF *buffers = local_buffers;
|
||||
size_t len;
|
||||
|
||||
if (tcp->shutting_down) {
|
||||
grpc_exec_ctx_enqueue(exec_ctx, cb, 0);
|
||||
|
|
@ -281,19 +283,21 @@ static void win_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
|
|||
|
||||
tcp->write_cb = cb;
|
||||
tcp->write_slices = slices;
|
||||
|
||||
GPR_ASSERT(tcp->write_slices->count <= UINT_MAX);
|
||||
if (tcp->write_slices->count > GPR_ARRAY_SIZE(local_buffers)) {
|
||||
buffers = (WSABUF *)gpr_malloc(sizeof(WSABUF) * tcp->write_slices->count);
|
||||
allocated = buffers;
|
||||
}
|
||||
|
||||
for (i = 0; i < tcp->write_slices->count; i++) {
|
||||
buffers[i].len = GPR_SLICE_LENGTH(tcp->write_slices->slices[i]);
|
||||
len = GPR_SLICE_LENGTH(tcp->write_slices->slices[i]);
|
||||
GPR_ASSERT(len <= ULONG_MAX);
|
||||
buffers[i].len = (ULONG)len;
|
||||
buffers[i].buf = (char *)GPR_SLICE_START_PTR(tcp->write_slices->slices[i]);
|
||||
}
|
||||
|
||||
/* First, let's try a synchronous, non-blocking write. */
|
||||
status = WSASend(socket->socket, buffers, tcp->write_slices->count,
|
||||
status = WSASend(socket->socket, buffers, (DWORD)tcp->write_slices->count,
|
||||
&bytes_sent, 0, NULL, NULL);
|
||||
info->wsa_error = status == 0 ? 0 : WSAGetLastError();
|
||||
|
||||
|
|
@ -322,7 +326,7 @@ static void win_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
|
|||
/* If we got a WSAEWOULDBLOCK earlier, then we need to re-do the same
|
||||
operation, this time asynchronously. */
|
||||
memset(&socket->write_info.overlapped, 0, sizeof(OVERLAPPED));
|
||||
status = WSASend(socket->socket, buffers, tcp->write_slices->count,
|
||||
status = WSASend(socket->socket, buffers, (DWORD)tcp->write_slices->count,
|
||||
&bytes_sent, 0, &socket->write_info.overlapped, NULL);
|
||||
if (allocated) gpr_free(allocated);
|
||||
|
||||
|
|
|
|||
|
|
@ -126,8 +126,8 @@ static double ts_to_dbl(gpr_timespec ts) {
|
|||
|
||||
static gpr_timespec dbl_to_ts(double d) {
|
||||
gpr_timespec ts;
|
||||
ts.tv_sec = (time_t)d;
|
||||
ts.tv_nsec = (int)(1e9 * (d - (double)ts.tv_sec));
|
||||
ts.tv_sec = (gpr_int64)d;
|
||||
ts.tv_nsec = (gpr_int32)(1e9 * (d - (double)ts.tv_sec));
|
||||
ts.clock_type = GPR_TIMESPAN;
|
||||
return ts;
|
||||
}
|
||||
|
|
@ -343,11 +343,3 @@ int grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now,
|
|||
exec_ctx, now, next,
|
||||
gpr_time_cmp(now, gpr_inf_future(now.clock_type)) != 0);
|
||||
}
|
||||
|
||||
gpr_timespec grpc_timer_list_next_timeout(void) {
|
||||
gpr_timespec out;
|
||||
gpr_mu_lock(&g_mu);
|
||||
out = g_shard_queue[0]->min_deadline;
|
||||
gpr_mu_unlock(&g_mu);
|
||||
return out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,8 +54,6 @@ int grpc_timer_check(grpc_exec_ctx* exec_ctx, gpr_timespec now,
|
|||
void grpc_timer_list_init(gpr_timespec now);
|
||||
void grpc_timer_list_shutdown(grpc_exec_ctx* exec_ctx);
|
||||
|
||||
gpr_timespec grpc_timer_list_next_timeout(void);
|
||||
|
||||
/* the following must be implemented by each iomgr implementation */
|
||||
|
||||
void grpc_kick_poller(void);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#ifdef GRPC_NEED_UDP
|
||||
#ifdef GPR_POSIX_SOCKET
|
||||
|
||||
#include "src/core/iomgr/udp_server.h"
|
||||
|
|
@ -179,7 +180,7 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
|
|||
}
|
||||
sp->destroyed_closure.cb = destroyed_port;
|
||||
sp->destroyed_closure.cb_arg = s;
|
||||
grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure,
|
||||
grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
|
||||
"udp_listener_shutdown");
|
||||
}
|
||||
gpr_mu_unlock(&s->mu);
|
||||
|
|
@ -435,3 +436,4 @@ void grpc_udp_server_write(server_port *sp, const char *buffer, size_t buf_len,
|
|||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -40,19 +40,17 @@
|
|||
#include <stddef.h>
|
||||
|
||||
static const grpc_wakeup_fd_vtable *wakeup_fd_vtable = NULL;
|
||||
int grpc_allow_specialized_wakeup_fd = 1;
|
||||
|
||||
void grpc_wakeup_fd_global_init(void) {
|
||||
if (grpc_specialized_wakeup_fd_vtable.check_availability()) {
|
||||
if (grpc_allow_specialized_wakeup_fd &&
|
||||
grpc_specialized_wakeup_fd_vtable.check_availability()) {
|
||||
wakeup_fd_vtable = &grpc_specialized_wakeup_fd_vtable;
|
||||
} else {
|
||||
wakeup_fd_vtable = &grpc_pipe_wakeup_fd_vtable;
|
||||
}
|
||||
}
|
||||
|
||||
void grpc_wakeup_fd_global_init_force_fallback(void) {
|
||||
wakeup_fd_vtable = &grpc_pipe_wakeup_fd_vtable;
|
||||
}
|
||||
|
||||
void grpc_wakeup_fd_global_destroy(void) { wakeup_fd_vtable = NULL; }
|
||||
|
||||
void grpc_wakeup_fd_init(grpc_wakeup_fd *fd_info) {
|
||||
|
|
|
|||
|
|
@ -85,6 +85,8 @@ struct grpc_wakeup_fd {
|
|||
int write_fd;
|
||||
};
|
||||
|
||||
extern int grpc_allow_specialized_wakeup_fd;
|
||||
|
||||
#define GRPC_WAKEUP_FD_GET_READ_FD(fd_info) ((fd_info)->read_fd)
|
||||
|
||||
void grpc_wakeup_fd_init(grpc_wakeup_fd* fd_info);
|
||||
|
|
|
|||
|
|
@ -103,6 +103,9 @@ void grpc_workqueue_add_to_pollset(grpc_exec_ctx *exec_ctx,
|
|||
|
||||
void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {
|
||||
gpr_mu_lock(&workqueue->mu);
|
||||
if (grpc_closure_list_empty(workqueue->closure_list)) {
|
||||
grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd);
|
||||
}
|
||||
grpc_closure_list_move(&exec_ctx->closure_list, &workqueue->closure_list);
|
||||
gpr_mu_unlock(&workqueue->mu);
|
||||
}
|
||||
|
|
@ -115,7 +118,7 @@ static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, int success) {
|
|||
/* HACK: let wakeup_fd code know that we stole the fd */
|
||||
workqueue->wakeup_fd.read_fd = 0;
|
||||
grpc_wakeup_fd_destroy(&workqueue->wakeup_fd);
|
||||
grpc_fd_orphan(exec_ctx, workqueue->wakeup_read_fd, NULL, "destroy");
|
||||
grpc_fd_orphan(exec_ctx, workqueue->wakeup_read_fd, NULL, NULL, "destroy");
|
||||
gpr_free(workqueue);
|
||||
} else {
|
||||
gpr_mu_lock(&workqueue->mu);
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include <grpc/support/log.h>
|
||||
|
||||
#include "src/core/json/json_reader.h"
|
||||
|
||||
static void json_reader_string_clear(grpc_json_reader *reader) {
|
||||
|
|
@ -224,13 +226,13 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
|
|||
reader->in_array = 1;
|
||||
break;
|
||||
case GRPC_JSON_TOP_LEVEL:
|
||||
if (reader->depth != 0) return GRPC_JSON_INTERNAL_ERROR;
|
||||
GPR_ASSERT(reader->depth == 0);
|
||||
reader->in_object = 0;
|
||||
reader->in_array = 0;
|
||||
reader->state = GRPC_JSON_STATE_END;
|
||||
break;
|
||||
default:
|
||||
return GRPC_JSON_INTERNAL_ERROR;
|
||||
GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -279,8 +281,7 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
|
|||
break;
|
||||
|
||||
case GRPC_JSON_STATE_OBJECT_KEY_STRING:
|
||||
if (reader->unicode_high_surrogate != 0)
|
||||
return GRPC_JSON_PARSE_ERROR;
|
||||
GPR_ASSERT(reader->unicode_high_surrogate == 0);
|
||||
if (c == '"') {
|
||||
reader->state = GRPC_JSON_STATE_OBJECT_KEY_END;
|
||||
json_reader_set_key(reader);
|
||||
|
|
@ -461,7 +462,7 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
|
|||
}
|
||||
break;
|
||||
default:
|
||||
return GRPC_JSON_INTERNAL_ERROR;
|
||||
GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -641,7 +642,7 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
|
|||
case ',':
|
||||
case '}':
|
||||
case ']':
|
||||
return GRPC_JSON_INTERNAL_ERROR;
|
||||
GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -655,5 +656,5 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
|
|||
}
|
||||
}
|
||||
|
||||
return GRPC_JSON_INTERNAL_ERROR;
|
||||
GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -353,7 +353,7 @@ static void json_dump_recursive(grpc_json_writer *writer, grpc_json *json,
|
|||
grpc_json_writer_value_raw_with_len(writer, "null", 4);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
GPR_UNREACHABLE_CODE(abort());
|
||||
}
|
||||
json = json->next;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,10 +141,11 @@ static void write_log(gpr_timer_log *log) {
|
|||
entry->tm = gpr_time_0(entry->tm.clock_type);
|
||||
}
|
||||
fprintf(output_file,
|
||||
"{\"t\": %ld.%09d, \"thd\": \"%d\", \"type\": \"%c\", \"tag\": "
|
||||
"{\"t\": %lld.%09d, \"thd\": \"%d\", \"type\": \"%c\", \"tag\": "
|
||||
"\"%s\", \"file\": \"%s\", \"line\": %d, \"imp\": %d}\n",
|
||||
entry->tm.tv_sec, entry->tm.tv_nsec, entry->thd, entry->type,
|
||||
entry->tagstr, entry->file, entry->line, entry->important);
|
||||
(long long)entry->tm.tv_sec, (int)entry->tm.tv_nsec, entry->thd,
|
||||
entry->type, entry->tagstr, entry->file, entry->line,
|
||||
entry->important);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,12 +39,13 @@
|
|||
#include <grpc/support/log.h>
|
||||
#include <grpc/support/string_util.h>
|
||||
|
||||
#include "src/core/support/string.h"
|
||||
#include "src/core/channel/channel_stack.h"
|
||||
#include "src/core/security/security_context.h"
|
||||
#include "src/core/security/security_connector.h"
|
||||
#include "src/core/security/credentials.h"
|
||||
#include "src/core/security/security_connector.h"
|
||||
#include "src/core/security/security_context.h"
|
||||
#include "src/core/support/string.h"
|
||||
#include "src/core/surface/call.h"
|
||||
#include "src/core/transport/static_metadata.h"
|
||||
|
||||
#define MAX_CREDENTIALS_METADATA_COUNT 4
|
||||
|
||||
|
|
@ -61,24 +62,29 @@ typedef struct {
|
|||
grpc_transport_stream_op op;
|
||||
gpr_uint8 security_context_set;
|
||||
grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT];
|
||||
char *service_url;
|
||||
grpc_auth_metadata_context auth_md_context;
|
||||
} call_data;
|
||||
|
||||
/* We can have a per-channel credentials. */
|
||||
typedef struct {
|
||||
grpc_channel_security_connector *security_connector;
|
||||
grpc_mdctx *md_ctx;
|
||||
grpc_mdstr *authority_string;
|
||||
grpc_mdstr *path_string;
|
||||
grpc_mdstr *error_msg_key;
|
||||
grpc_mdstr *status_key;
|
||||
grpc_auth_context *auth_context;
|
||||
} channel_data;
|
||||
|
||||
static void reset_service_url(call_data *calld) {
|
||||
if (calld->service_url != NULL) {
|
||||
gpr_free(calld->service_url);
|
||||
calld->service_url = NULL;
|
||||
static void reset_auth_metadata_context(
|
||||
grpc_auth_metadata_context *auth_md_context) {
|
||||
if (auth_md_context->service_url != NULL) {
|
||||
gpr_free((char *)auth_md_context->service_url);
|
||||
auth_md_context->service_url = NULL;
|
||||
}
|
||||
if (auth_md_context->method_name != NULL) {
|
||||
gpr_free((char *)auth_md_context->method_name);
|
||||
auth_md_context->method_name = NULL;
|
||||
}
|
||||
GRPC_AUTH_CONTEXT_UNREF(
|
||||
(grpc_auth_context *)auth_md_context->channel_auth_context,
|
||||
"grpc_auth_metadata_context");
|
||||
auth_md_context->channel_auth_context = NULL;
|
||||
}
|
||||
|
||||
static void bubble_up_error(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
|
||||
|
|
@ -95,11 +101,10 @@ static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
|
|||
grpc_credentials_status status) {
|
||||
grpc_call_element *elem = (grpc_call_element *)user_data;
|
||||
call_data *calld = elem->call_data;
|
||||
channel_data *chand = elem->channel_data;
|
||||
grpc_transport_stream_op *op = &calld->op;
|
||||
grpc_metadata_batch *mdb;
|
||||
size_t i;
|
||||
reset_service_url(calld);
|
||||
reset_auth_metadata_context(&calld->auth_md_context);
|
||||
if (status != GRPC_CREDENTIALS_OK) {
|
||||
bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED,
|
||||
"Credentials failed to get metadata.");
|
||||
|
|
@ -111,15 +116,20 @@ static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
|
|||
for (i = 0; i < num_md; i++) {
|
||||
grpc_metadata_batch_add_tail(
|
||||
mdb, &calld->md_links[i],
|
||||
grpc_mdelem_from_slices(chand->md_ctx, gpr_slice_ref(md_elems[i].key),
|
||||
grpc_mdelem_from_slices(gpr_slice_ref(md_elems[i].key),
|
||||
gpr_slice_ref(md_elems[i].value)));
|
||||
}
|
||||
grpc_call_next_op(exec_ctx, elem, op);
|
||||
}
|
||||
|
||||
void build_service_url(const char *url_scheme, call_data *calld) {
|
||||
void build_auth_metadata_context(grpc_security_connector *sc,
|
||||
grpc_auth_context *auth_context,
|
||||
call_data *calld) {
|
||||
char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method));
|
||||
char *last_slash = strrchr(service, '/');
|
||||
char *method_name = NULL;
|
||||
char *service_url = NULL;
|
||||
reset_auth_metadata_context(&calld->auth_md_context);
|
||||
if (last_slash == NULL) {
|
||||
gpr_log(GPR_ERROR, "No '/' found in fully qualified method name");
|
||||
service[0] = '\0';
|
||||
|
|
@ -128,11 +138,16 @@ void build_service_url(const char *url_scheme, call_data *calld) {
|
|||
service[1] = '\0';
|
||||
} else {
|
||||
*last_slash = '\0';
|
||||
method_name = gpr_strdup(last_slash + 1);
|
||||
}
|
||||
if (url_scheme == NULL) url_scheme = "";
|
||||
reset_service_url(calld);
|
||||
gpr_asprintf(&calld->service_url, "%s://%s%s", url_scheme,
|
||||
if (method_name == NULL) method_name = gpr_strdup("");
|
||||
gpr_asprintf(&service_url, "%s://%s%s",
|
||||
sc->url_scheme == NULL ? "" : sc->url_scheme,
|
||||
grpc_mdstr_as_c_string(calld->host), service);
|
||||
calld->auth_md_context.service_url = service_url;
|
||||
calld->auth_md_context.method_name = method_name;
|
||||
calld->auth_md_context.channel_auth_context =
|
||||
GRPC_AUTH_CONTEXT_REF(auth_context, "grpc_auth_metadata_context");
|
||||
gpr_free(service);
|
||||
}
|
||||
|
||||
|
|
@ -166,12 +181,13 @@ static void send_security_metadata(grpc_exec_ctx *exec_ctx,
|
|||
call_creds_has_md ? ctx->creds : channel_call_creds);
|
||||
}
|
||||
|
||||
build_service_url(chand->security_connector->base.url_scheme, calld);
|
||||
build_auth_metadata_context(&chand->security_connector->base,
|
||||
chand->auth_context, calld);
|
||||
calld->op = *op; /* Copy op (originates from the caller's stack). */
|
||||
GPR_ASSERT(calld->pollset);
|
||||
grpc_call_credentials_get_request_metadata(exec_ctx, calld->creds,
|
||||
calld->pollset, calld->service_url,
|
||||
on_credentials_metadata, elem);
|
||||
grpc_call_credentials_get_request_metadata(
|
||||
exec_ctx, calld->creds, calld->pollset, calld->auth_md_context,
|
||||
on_credentials_metadata, elem);
|
||||
}
|
||||
|
||||
static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data,
|
||||
|
|
@ -217,7 +233,7 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
|
|||
sec_ctx = op->context[GRPC_CONTEXT_SECURITY].value;
|
||||
GRPC_AUTH_CONTEXT_UNREF(sec_ctx->auth_context, "client auth filter");
|
||||
sec_ctx->auth_context = GRPC_AUTH_CONTEXT_REF(
|
||||
chand->security_connector->base.auth_context, "client_auth_filter");
|
||||
chand->auth_context, "client_auth_filter");
|
||||
}
|
||||
|
||||
if (op->send_initial_metadata != NULL) {
|
||||
|
|
@ -225,36 +241,22 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
|
|||
grpc_mdelem *md = l->md;
|
||||
/* Pointer comparison is OK for md_elems created from the same context.
|
||||
*/
|
||||
if (md->key == chand->authority_string) {
|
||||
if (md->key == GRPC_MDSTR_AUTHORITY) {
|
||||
if (calld->host != NULL) GRPC_MDSTR_UNREF(calld->host);
|
||||
calld->host = GRPC_MDSTR_REF(md->value);
|
||||
} else if (md->key == chand->path_string) {
|
||||
} else if (md->key == GRPC_MDSTR_PATH) {
|
||||
if (calld->method != NULL) GRPC_MDSTR_UNREF(calld->method);
|
||||
calld->method = GRPC_MDSTR_REF(md->value);
|
||||
}
|
||||
}
|
||||
if (calld->host != NULL) {
|
||||
grpc_security_status status;
|
||||
const char *call_host = grpc_mdstr_as_c_string(calld->host);
|
||||
calld->op = *op; /* Copy op (originates from the caller's stack). */
|
||||
status = grpc_channel_security_connector_check_call_host(
|
||||
exec_ctx, chand->security_connector, call_host, on_host_checked,
|
||||
elem);
|
||||
if (status != GRPC_SECURITY_OK) {
|
||||
if (status == GRPC_SECURITY_ERROR) {
|
||||
char *error_msg;
|
||||
gpr_asprintf(&error_msg,
|
||||
"Invalid host %s set in :authority metadata.",
|
||||
call_host);
|
||||
bubble_up_error(exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT,
|
||||
error_msg);
|
||||
gpr_free(error_msg);
|
||||
}
|
||||
return; /* early exit */
|
||||
}
|
||||
grpc_channel_security_connector_check_call_host(
|
||||
exec_ctx, chand->security_connector, call_host, chand->auth_context,
|
||||
on_host_checked, elem);
|
||||
return; /* early exit */
|
||||
}
|
||||
send_security_metadata(exec_ctx, elem, op);
|
||||
return; /* early exit */
|
||||
}
|
||||
|
||||
/* pass control down the stack */
|
||||
|
|
@ -285,7 +287,7 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
|
|||
if (calld->method != NULL) {
|
||||
GRPC_MDSTR_UNREF(calld->method);
|
||||
}
|
||||
reset_service_url(calld);
|
||||
reset_auth_metadata_context(&calld->auth_md_context);
|
||||
}
|
||||
|
||||
/* Constructor for channel_data */
|
||||
|
|
@ -294,6 +296,9 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
|
|||
grpc_channel_element_args *args) {
|
||||
grpc_security_connector *sc =
|
||||
grpc_find_security_connector_in_args(args->channel_args);
|
||||
grpc_auth_context *auth_context =
|
||||
grpc_find_auth_context_in_args(args->channel_args);
|
||||
|
||||
/* grab pointers to our data from the channel element */
|
||||
channel_data *chand = elem->channel_data;
|
||||
|
||||
|
|
@ -302,17 +307,15 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
|
|||
path */
|
||||
GPR_ASSERT(!args->is_last);
|
||||
GPR_ASSERT(sc != NULL);
|
||||
GPR_ASSERT(auth_context != NULL);
|
||||
|
||||
/* initialize members */
|
||||
GPR_ASSERT(sc->is_client_side);
|
||||
chand->security_connector =
|
||||
(grpc_channel_security_connector *)GRPC_SECURITY_CONNECTOR_REF(
|
||||
sc, "client_auth_filter");
|
||||
chand->md_ctx = args->metadata_context;
|
||||
chand->authority_string = grpc_mdstr_from_string(chand->md_ctx, ":authority");
|
||||
chand->path_string = grpc_mdstr_from_string(chand->md_ctx, ":path");
|
||||
chand->error_msg_key = grpc_mdstr_from_string(chand->md_ctx, "grpc-message");
|
||||
chand->status_key = grpc_mdstr_from_string(chand->md_ctx, "grpc-status");
|
||||
chand->auth_context =
|
||||
GRPC_AUTH_CONTEXT_REF(auth_context, "client_auth_filter");
|
||||
}
|
||||
|
||||
/* Destructor for channel data */
|
||||
|
|
@ -320,21 +323,11 @@ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
|
|||
grpc_channel_element *elem) {
|
||||
/* grab pointers to our data from the channel element */
|
||||
channel_data *chand = elem->channel_data;
|
||||
grpc_channel_security_connector *ctx = chand->security_connector;
|
||||
if (ctx != NULL)
|
||||
GRPC_SECURITY_CONNECTOR_UNREF(&ctx->base, "client_auth_filter");
|
||||
if (chand->authority_string != NULL) {
|
||||
GRPC_MDSTR_UNREF(chand->authority_string);
|
||||
}
|
||||
if (chand->error_msg_key != NULL) {
|
||||
GRPC_MDSTR_UNREF(chand->error_msg_key);
|
||||
}
|
||||
if (chand->status_key != NULL) {
|
||||
GRPC_MDSTR_UNREF(chand->status_key);
|
||||
}
|
||||
if (chand->path_string != NULL) {
|
||||
GRPC_MDSTR_UNREF(chand->path_string);
|
||||
grpc_channel_security_connector *sc = chand->security_connector;
|
||||
if (sc != NULL) {
|
||||
GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "client_auth_filter");
|
||||
}
|
||||
GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "client_auth_filter");
|
||||
}
|
||||
|
||||
const grpc_channel_filter grpc_client_auth_filter = {
|
||||
|
|
|
|||
|
|
@ -33,22 +33,21 @@
|
|||
|
||||
#include "src/core/security/credentials.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "src/core/channel/channel_args.h"
|
||||
#include "src/core/channel/http_client_filter.h"
|
||||
#include "src/core/json/json.h"
|
||||
#include "src/core/httpcli/httpcli.h"
|
||||
#include "src/core/iomgr/iomgr.h"
|
||||
#include "src/core/surface/api_trace.h"
|
||||
#include "src/core/iomgr/executor.h"
|
||||
#include "src/core/json/json.h"
|
||||
#include "src/core/support/string.h"
|
||||
#include "src/core/surface/api_trace.h"
|
||||
|
||||
#include <grpc/support/alloc.h>
|
||||
#include <grpc/support/log.h>
|
||||
#include <grpc/support/string_util.h>
|
||||
#include <grpc/support/sync.h>
|
||||
#include <grpc/support/thd.h>
|
||||
#include <grpc/support/time.h>
|
||||
|
||||
/* -- Common. -- */
|
||||
|
|
@ -116,19 +115,17 @@ void grpc_call_credentials_release(grpc_call_credentials *creds) {
|
|||
grpc_call_credentials_unref(creds);
|
||||
}
|
||||
|
||||
void grpc_call_credentials_get_request_metadata(grpc_exec_ctx *exec_ctx,
|
||||
grpc_call_credentials *creds,
|
||||
grpc_pollset *pollset,
|
||||
const char *service_url,
|
||||
grpc_credentials_metadata_cb cb,
|
||||
void *user_data) {
|
||||
void grpc_call_credentials_get_request_metadata(
|
||||
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
|
||||
grpc_pollset *pollset, grpc_auth_metadata_context context,
|
||||
grpc_credentials_metadata_cb cb, void *user_data) {
|
||||
if (creds == NULL || creds->vtable->get_request_metadata == NULL) {
|
||||
if (cb != NULL) {
|
||||
cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
|
||||
}
|
||||
return;
|
||||
}
|
||||
creds->vtable->get_request_metadata(exec_ctx, creds, pollset, service_url, cb,
|
||||
creds->vtable->get_request_metadata(exec_ctx, creds, pollset, context, cb,
|
||||
user_data);
|
||||
}
|
||||
|
||||
|
|
@ -182,8 +179,8 @@ void grpc_server_credentials_set_auth_metadata_processor(
|
|||
GRPC_API_TRACE(
|
||||
"grpc_server_credentials_set_auth_metadata_processor("
|
||||
"creds=%p, "
|
||||
"processor=grpc_auth_metadata_processor { process: %lx, state: %p })",
|
||||
3, (creds, (unsigned long)processor.process, processor.state));
|
||||
"processor=grpc_auth_metadata_processor { process: %p, state: %p })",
|
||||
3, (creds, (void*)(gpr_intptr)processor.process, processor.state));
|
||||
if (creds == NULL) return;
|
||||
if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
|
||||
creds->processor.destroy(creds->processor.state);
|
||||
|
|
@ -429,7 +426,7 @@ static void jwt_destruct(grpc_call_credentials *creds) {
|
|||
static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
|
||||
grpc_call_credentials *creds,
|
||||
grpc_pollset *pollset,
|
||||
const char *service_url,
|
||||
grpc_auth_metadata_context context,
|
||||
grpc_credentials_metadata_cb cb,
|
||||
void *user_data) {
|
||||
grpc_service_account_jwt_access_credentials *c =
|
||||
|
|
@ -442,7 +439,7 @@ static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
|
|||
{
|
||||
gpr_mu_lock(&c->cache_mu);
|
||||
if (c->cached.service_url != NULL &&
|
||||
strcmp(c->cached.service_url, service_url) == 0 &&
|
||||
strcmp(c->cached.service_url, context.service_url) == 0 &&
|
||||
c->cached.jwt_md != NULL &&
|
||||
(gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration,
|
||||
gpr_now(GPR_CLOCK_REALTIME)),
|
||||
|
|
@ -457,14 +454,15 @@ static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
|
|||
/* Generate a new jwt. */
|
||||
gpr_mu_lock(&c->cache_mu);
|
||||
jwt_reset_cache(c);
|
||||
jwt = grpc_jwt_encode_and_sign(&c->key, service_url, c->jwt_lifetime, NULL);
|
||||
jwt = grpc_jwt_encode_and_sign(&c->key, context.service_url,
|
||||
c->jwt_lifetime, NULL);
|
||||
if (jwt != NULL) {
|
||||
char *md_value;
|
||||
gpr_asprintf(&md_value, "Bearer %s", jwt);
|
||||
gpr_free(jwt);
|
||||
c->cached.jwt_expiration =
|
||||
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime);
|
||||
c->cached.service_url = gpr_strdup(service_url);
|
||||
c->cached.service_url = gpr_strdup(context.service_url);
|
||||
c->cached.jwt_md = grpc_credentials_md_store_create(1);
|
||||
grpc_credentials_md_store_add_cstrings(
|
||||
c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value);
|
||||
|
|
@ -512,10 +510,11 @@ grpc_call_credentials *grpc_service_account_jwt_access_credentials_create(
|
|||
"grpc_service_account_jwt_access_credentials_create("
|
||||
"json_key=%s, "
|
||||
"token_lifetime="
|
||||
"gpr_timespec { tv_sec: %ld, tv_nsec: %d, clock_type: %d }, "
|
||||
"gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, "
|
||||
"reserved=%p)",
|
||||
5, (json_key, (long)token_lifetime.tv_sec, token_lifetime.tv_nsec,
|
||||
(int)token_lifetime.clock_type, reserved));
|
||||
5,
|
||||
(json_key, (long long)token_lifetime.tv_sec, (int)token_lifetime.tv_nsec,
|
||||
(int)token_lifetime.clock_type, reserved));
|
||||
GPR_ASSERT(reserved == NULL);
|
||||
return grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
|
||||
grpc_auth_json_key_create_from_string(json_key), token_lifetime);
|
||||
|
|
@ -649,7 +648,7 @@ static void on_oauth2_token_fetcher_http_response(
|
|||
|
||||
static void oauth2_token_fetcher_get_request_metadata(
|
||||
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
|
||||
grpc_pollset *pollset, const char *service_url,
|
||||
grpc_pollset *pollset, grpc_auth_metadata_context context,
|
||||
grpc_credentials_metadata_cb cb, void *user_data) {
|
||||
grpc_oauth2_token_fetcher_credentials *c =
|
||||
(grpc_oauth2_token_fetcher_credentials *)creds;
|
||||
|
|
@ -793,30 +792,27 @@ static void md_only_test_destruct(grpc_call_credentials *creds) {
|
|||
grpc_credentials_md_store_unref(c->md_store);
|
||||
}
|
||||
|
||||
static void on_simulated_token_fetch_done(void *user_data) {
|
||||
static void on_simulated_token_fetch_done(grpc_exec_ctx *exec_ctx,
|
||||
void *user_data, int success) {
|
||||
grpc_credentials_metadata_request *r =
|
||||
(grpc_credentials_metadata_request *)user_data;
|
||||
grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds;
|
||||
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
|
||||
r->cb(&exec_ctx, r->user_data, c->md_store->entries, c->md_store->num_entries,
|
||||
r->cb(exec_ctx, r->user_data, c->md_store->entries, c->md_store->num_entries,
|
||||
GRPC_CREDENTIALS_OK);
|
||||
grpc_credentials_metadata_request_destroy(r);
|
||||
grpc_exec_ctx_finish(&exec_ctx);
|
||||
}
|
||||
|
||||
static void md_only_test_get_request_metadata(grpc_exec_ctx *exec_ctx,
|
||||
grpc_call_credentials *creds,
|
||||
grpc_pollset *pollset,
|
||||
const char *service_url,
|
||||
grpc_credentials_metadata_cb cb,
|
||||
void *user_data) {
|
||||
static void md_only_test_get_request_metadata(
|
||||
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
|
||||
grpc_pollset *pollset, grpc_auth_metadata_context context,
|
||||
grpc_credentials_metadata_cb cb, void *user_data) {
|
||||
grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
|
||||
|
||||
if (c->is_async) {
|
||||
gpr_thd_id thd_id;
|
||||
grpc_credentials_metadata_request *cb_arg =
|
||||
grpc_credentials_metadata_request_create(creds, cb, user_data);
|
||||
gpr_thd_new(&thd_id, on_simulated_token_fetch_done, cb_arg, NULL);
|
||||
grpc_executor_enqueue(
|
||||
grpc_closure_create(on_simulated_token_fetch_done, cb_arg), 1);
|
||||
} else {
|
||||
cb(exec_ctx, user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK);
|
||||
}
|
||||
|
|
@ -846,12 +842,10 @@ static void access_token_destruct(grpc_call_credentials *creds) {
|
|||
grpc_credentials_md_store_unref(c->access_token_md);
|
||||
}
|
||||
|
||||
static void access_token_get_request_metadata(grpc_exec_ctx *exec_ctx,
|
||||
grpc_call_credentials *creds,
|
||||
grpc_pollset *pollset,
|
||||
const char *service_url,
|
||||
grpc_credentials_metadata_cb cb,
|
||||
void *user_data) {
|
||||
static void access_token_get_request_metadata(
|
||||
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
|
||||
grpc_pollset *pollset, grpc_auth_metadata_context context,
|
||||
grpc_credentials_metadata_cb cb, void *user_data) {
|
||||
grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
|
||||
cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
|
||||
}
|
||||
|
|
@ -887,7 +881,7 @@ static grpc_security_status fake_transport_security_create_security_connector(
|
|||
grpc_channel_credentials *c, grpc_call_credentials *call_creds,
|
||||
const char *target, const grpc_channel_args *args,
|
||||
grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
|
||||
*sc = grpc_fake_channel_security_connector_create(call_creds, 1);
|
||||
*sc = grpc_fake_channel_security_connector_create(call_creds);
|
||||
return GRPC_SECURITY_OK;
|
||||
}
|
||||
|
||||
|
|
@ -932,7 +926,7 @@ typedef struct {
|
|||
grpc_composite_call_credentials *composite_creds;
|
||||
size_t creds_index;
|
||||
grpc_credentials_md_store *md_elems;
|
||||
char *service_url;
|
||||
grpc_auth_metadata_context auth_md_context;
|
||||
void *user_data;
|
||||
grpc_pollset *pollset;
|
||||
grpc_credentials_metadata_cb cb;
|
||||
|
|
@ -950,7 +944,6 @@ static void composite_call_destruct(grpc_call_credentials *creds) {
|
|||
static void composite_call_md_context_destroy(
|
||||
grpc_composite_call_credentials_metadata_context *ctx) {
|
||||
grpc_credentials_md_store_unref(ctx->md_elems);
|
||||
if (ctx->service_url != NULL) gpr_free(ctx->service_url);
|
||||
gpr_free(ctx);
|
||||
}
|
||||
|
||||
|
|
@ -978,9 +971,9 @@ static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
|
|||
if (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
|
||||
grpc_call_credentials *inner_creds =
|
||||
ctx->composite_creds->inner.creds_array[ctx->creds_index++];
|
||||
grpc_call_credentials_get_request_metadata(exec_ctx, inner_creds,
|
||||
ctx->pollset, ctx->service_url,
|
||||
composite_call_metadata_cb, ctx);
|
||||
grpc_call_credentials_get_request_metadata(
|
||||
exec_ctx, inner_creds, ctx->pollset, ctx->auth_md_context,
|
||||
composite_call_metadata_cb, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -990,26 +983,24 @@ static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
|
|||
composite_call_md_context_destroy(ctx);
|
||||
}
|
||||
|
||||
static void composite_call_get_request_metadata(grpc_exec_ctx *exec_ctx,
|
||||
grpc_call_credentials *creds,
|
||||
grpc_pollset *pollset,
|
||||
const char *service_url,
|
||||
grpc_credentials_metadata_cb cb,
|
||||
void *user_data) {
|
||||
static void composite_call_get_request_metadata(
|
||||
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
|
||||
grpc_pollset *pollset, grpc_auth_metadata_context auth_md_context,
|
||||
grpc_credentials_metadata_cb cb, void *user_data) {
|
||||
grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
|
||||
grpc_composite_call_credentials_metadata_context *ctx;
|
||||
|
||||
ctx = gpr_malloc(sizeof(grpc_composite_call_credentials_metadata_context));
|
||||
memset(ctx, 0, sizeof(grpc_composite_call_credentials_metadata_context));
|
||||
ctx->service_url = gpr_strdup(service_url);
|
||||
ctx->auth_md_context = auth_md_context;
|
||||
ctx->user_data = user_data;
|
||||
ctx->cb = cb;
|
||||
ctx->composite_creds = c;
|
||||
ctx->pollset = pollset;
|
||||
ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds);
|
||||
grpc_call_credentials_get_request_metadata(
|
||||
exec_ctx, c->inner.creds_array[ctx->creds_index++], pollset, service_url,
|
||||
composite_call_metadata_cb, ctx);
|
||||
exec_ctx, c->inner.creds_array[ctx->creds_index++], pollset,
|
||||
auth_md_context, composite_call_metadata_cb, ctx);
|
||||
}
|
||||
|
||||
static grpc_call_credentials_vtable composite_call_credentials_vtable = {
|
||||
|
|
@ -1103,7 +1094,7 @@ static void iam_destruct(grpc_call_credentials *creds) {
|
|||
static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
|
||||
grpc_call_credentials *creds,
|
||||
grpc_pollset *pollset,
|
||||
const char *service_url,
|
||||
grpc_auth_metadata_context context,
|
||||
grpc_credentials_metadata_cb cb,
|
||||
void *user_data) {
|
||||
grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
|
||||
|
|
@ -1192,7 +1183,7 @@ static void plugin_md_request_metadata_ready(void *request,
|
|||
static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
|
||||
grpc_call_credentials *creds,
|
||||
grpc_pollset *pollset,
|
||||
const char *service_url,
|
||||
grpc_auth_metadata_context context,
|
||||
grpc_credentials_metadata_cb cb,
|
||||
void *user_data) {
|
||||
grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
|
||||
|
|
@ -1201,7 +1192,7 @@ static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
|
|||
memset(request, 0, sizeof(*request));
|
||||
request->user_data = user_data;
|
||||
request->cb = cb;
|
||||
c->plugin.get_metadata(c->plugin.state, service_url,
|
||||
c->plugin.get_metadata(c->plugin.state, context,
|
||||
plugin_md_request_metadata_ready, request);
|
||||
} else {
|
||||
cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
|
||||
|
|
@ -1218,7 +1209,7 @@ grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
|
|||
(reserved));
|
||||
GPR_ASSERT(reserved == NULL);
|
||||
memset(c, 0, sizeof(*c));
|
||||
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_METADATA_PLUGIN;
|
||||
c->base.type = plugin.type;
|
||||
c->base.vtable = &plugin_vtable;
|
||||
gpr_ref_init(&c->base.refcount, 1);
|
||||
c->plugin = plugin;
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ typedef enum {
|
|||
"FakeTransportSecurity"
|
||||
|
||||
#define GRPC_CALL_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
|
||||
#define GRPC_CALL_CREDENTIALS_TYPE_METADATA_PLUGIN "Plugin"
|
||||
#define GRPC_CALL_CREDENTIALS_TYPE_JWT "Jwt"
|
||||
#define GRPC_CALL_CREDENTIALS_TYPE_IAM "Iam"
|
||||
#define GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE "Composite"
|
||||
|
|
@ -94,6 +93,14 @@ typedef enum {
|
|||
/* It is the caller's responsibility to gpr_free the result if not NULL. */
|
||||
char *grpc_get_well_known_google_credentials_file_path(void);
|
||||
|
||||
/* Implementation function for the different platforms. */
|
||||
char *grpc_get_well_known_google_credentials_file_path_impl(void);
|
||||
|
||||
/* Override for testing only. Not thread-safe */
|
||||
typedef char *(*grpc_well_known_credentials_path_getter)(void);
|
||||
void grpc_override_well_known_credentials_path_getter(
|
||||
grpc_well_known_credentials_path_getter getter);
|
||||
|
||||
/* --- grpc_channel_credentials. --- */
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -162,7 +169,7 @@ typedef struct {
|
|||
void (*destruct)(grpc_call_credentials *c);
|
||||
void (*get_request_metadata)(grpc_exec_ctx *exec_ctx,
|
||||
grpc_call_credentials *c, grpc_pollset *pollset,
|
||||
const char *service_url,
|
||||
grpc_auth_metadata_context context,
|
||||
grpc_credentials_metadata_cb cb,
|
||||
void *user_data);
|
||||
} grpc_call_credentials_vtable;
|
||||
|
|
@ -175,12 +182,10 @@ struct grpc_call_credentials {
|
|||
|
||||
grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds);
|
||||
void grpc_call_credentials_unref(grpc_call_credentials *creds);
|
||||
void grpc_call_credentials_get_request_metadata(grpc_exec_ctx *exec_ctx,
|
||||
grpc_call_credentials *creds,
|
||||
grpc_pollset *pollset,
|
||||
const char *service_url,
|
||||
grpc_credentials_metadata_cb cb,
|
||||
void *user_data);
|
||||
void grpc_call_credentials_get_request_metadata(
|
||||
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
|
||||
grpc_pollset *pollset, grpc_auth_metadata_context context,
|
||||
grpc_credentials_metadata_cb cb, void *user_data);
|
||||
|
||||
typedef struct {
|
||||
grpc_call_credentials **creds_array;
|
||||
|
|
@ -204,6 +209,7 @@ grpc_credentials_status
|
|||
grpc_oauth2_token_fetcher_credentials_parse_server_response(
|
||||
const struct grpc_httpcli_response *response,
|
||||
grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime);
|
||||
|
||||
void grpc_flush_cached_google_default_credentials(void);
|
||||
|
||||
/* Metadata-only credentials with the specified key and value where
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
#include "src/core/support/env.h"
|
||||
#include "src/core/support/string.h"
|
||||
|
||||
char *grpc_get_well_known_google_credentials_file_path(void) {
|
||||
char *grpc_get_well_known_google_credentials_file_path_impl(void) {
|
||||
char *result = NULL;
|
||||
char *home = gpr_getenv("HOME");
|
||||
if (home == NULL) {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
#include "src/core/support/env.h"
|
||||
#include "src/core/support/string.h"
|
||||
|
||||
char *grpc_get_well_known_google_credentials_file_path(void) {
|
||||
char *grpc_get_well_known_google_credentials_file_path_impl(void) {
|
||||
char *result = NULL;
|
||||
char *appdata_path = gpr_getenv("APPDATA");
|
||||
if (appdata_path == NULL) {
|
||||
|
|
|
|||
|
|
@ -241,5 +241,20 @@ void grpc_flush_cached_google_default_credentials(void) {
|
|||
grpc_channel_credentials_unref(default_credentials);
|
||||
default_credentials = NULL;
|
||||
}
|
||||
compute_engine_detection_done = 0;
|
||||
gpr_mu_unlock(&g_mu);
|
||||
}
|
||||
|
||||
/* -- Well known credentials path. -- */
|
||||
|
||||
static grpc_well_known_credentials_path_getter creds_path_getter = NULL;
|
||||
|
||||
char *grpc_get_well_known_google_credentials_file_path(void) {
|
||||
if (creds_path_getter != NULL) return creds_path_getter();
|
||||
return grpc_get_well_known_google_credentials_file_path_impl();
|
||||
}
|
||||
|
||||
void grpc_override_well_known_credentials_path_getter(
|
||||
grpc_well_known_credentials_path_getter getter) {
|
||||
creds_path_getter = getter;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include "src/core/security/security_context.h"
|
||||
#include "src/core/security/secure_endpoint.h"
|
||||
#include <grpc/support/alloc.h>
|
||||
#include <grpc/support/log.h>
|
||||
|
|
@ -56,6 +57,7 @@ typedef struct {
|
|||
void *user_data;
|
||||
grpc_closure on_handshake_data_sent_to_peer;
|
||||
grpc_closure on_handshake_data_received_from_peer;
|
||||
grpc_auth_context *auth_context;
|
||||
} grpc_security_handshake;
|
||||
|
||||
static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
|
||||
|
|
@ -64,12 +66,40 @@ static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
|
|||
static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *setup,
|
||||
int success);
|
||||
|
||||
static void security_connector_remove_handshake(grpc_security_handshake *h) {
|
||||
grpc_security_connector_handshake_list *node;
|
||||
grpc_security_connector_handshake_list *tmp;
|
||||
grpc_security_connector *sc = h->connector;
|
||||
gpr_mu_lock(&sc->mu);
|
||||
node = sc->handshaking_handshakes;
|
||||
if (node && node->handshake == h) {
|
||||
sc->handshaking_handshakes = node->next;
|
||||
gpr_free(node);
|
||||
gpr_mu_unlock(&sc->mu);
|
||||
return;
|
||||
}
|
||||
while (node) {
|
||||
if (node->next->handshake == h) {
|
||||
tmp = node->next;
|
||||
node->next = node->next->next;
|
||||
gpr_free(tmp);
|
||||
gpr_mu_unlock(&sc->mu);
|
||||
return;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
gpr_mu_unlock(&sc->mu);
|
||||
}
|
||||
|
||||
static void security_handshake_done(grpc_exec_ctx *exec_ctx,
|
||||
grpc_security_handshake *h,
|
||||
int is_success) {
|
||||
if (!h->connector->is_client_side) {
|
||||
security_connector_remove_handshake(h);
|
||||
}
|
||||
if (is_success) {
|
||||
h->cb(exec_ctx, h->user_data, GRPC_SECURITY_OK, h->wrapped_endpoint,
|
||||
h->secure_endpoint);
|
||||
h->cb(exec_ctx, h->user_data, GRPC_SECURITY_OK, h->secure_endpoint,
|
||||
h->auth_context);
|
||||
} else {
|
||||
if (h->secure_endpoint != NULL) {
|
||||
grpc_endpoint_shutdown(exec_ctx, h->secure_endpoint);
|
||||
|
|
@ -77,20 +107,21 @@ static void security_handshake_done(grpc_exec_ctx *exec_ctx,
|
|||
} else {
|
||||
grpc_endpoint_destroy(exec_ctx, h->wrapped_endpoint);
|
||||
}
|
||||
h->cb(exec_ctx, h->user_data, GRPC_SECURITY_ERROR, h->wrapped_endpoint,
|
||||
NULL);
|
||||
h->cb(exec_ctx, h->user_data, GRPC_SECURITY_ERROR, NULL, NULL);
|
||||
}
|
||||
if (h->handshaker != NULL) tsi_handshaker_destroy(h->handshaker);
|
||||
if (h->handshake_buffer != NULL) gpr_free(h->handshake_buffer);
|
||||
gpr_slice_buffer_destroy(&h->left_overs);
|
||||
gpr_slice_buffer_destroy(&h->outgoing);
|
||||
gpr_slice_buffer_destroy(&h->incoming);
|
||||
GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake");
|
||||
GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake");
|
||||
gpr_free(h);
|
||||
}
|
||||
|
||||
static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data,
|
||||
grpc_security_status status) {
|
||||
grpc_security_status status,
|
||||
grpc_auth_context *auth_context) {
|
||||
grpc_security_handshake *h = user_data;
|
||||
tsi_frame_protector *protector;
|
||||
tsi_result result;
|
||||
|
|
@ -99,6 +130,7 @@ static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data,
|
|||
security_handshake_done(exec_ctx, h, 0);
|
||||
return;
|
||||
}
|
||||
h->auth_context = GRPC_AUTH_CONTEXT_REF(auth_context, "handshake");
|
||||
result =
|
||||
tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector);
|
||||
if (result != TSI_OK) {
|
||||
|
|
@ -117,7 +149,6 @@ static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data,
|
|||
}
|
||||
|
||||
static void check_peer(grpc_exec_ctx *exec_ctx, grpc_security_handshake *h) {
|
||||
grpc_security_status peer_status;
|
||||
tsi_peer peer;
|
||||
tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer);
|
||||
|
||||
|
|
@ -127,15 +158,8 @@ static void check_peer(grpc_exec_ctx *exec_ctx, grpc_security_handshake *h) {
|
|||
security_handshake_done(exec_ctx, h, 0);
|
||||
return;
|
||||
}
|
||||
peer_status = grpc_security_connector_check_peer(h->connector, peer,
|
||||
on_peer_checked, h);
|
||||
if (peer_status == GRPC_SECURITY_ERROR) {
|
||||
gpr_log(GPR_ERROR, "Peer check failed.");
|
||||
security_handshake_done(exec_ctx, h, 0);
|
||||
return;
|
||||
} else if (peer_status == GRPC_SECURITY_OK) {
|
||||
on_peer_checked(exec_ctx, h, peer_status);
|
||||
}
|
||||
grpc_security_connector_check_peer(exec_ctx, h->connector, peer,
|
||||
on_peer_checked, h);
|
||||
}
|
||||
|
||||
static void send_handshake_bytes_to_peer(grpc_exec_ctx *exec_ctx,
|
||||
|
|
@ -268,6 +292,7 @@ void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
|
|||
grpc_endpoint *nonsecure_endpoint,
|
||||
grpc_security_handshake_done_cb cb,
|
||||
void *user_data) {
|
||||
grpc_security_connector_handshake_list *handshake_node;
|
||||
grpc_security_handshake *h = gpr_malloc(sizeof(grpc_security_handshake));
|
||||
memset(h, 0, sizeof(grpc_security_handshake));
|
||||
h->handshaker = handshaker;
|
||||
|
|
@ -284,5 +309,19 @@ void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
|
|||
gpr_slice_buffer_init(&h->left_overs);
|
||||
gpr_slice_buffer_init(&h->outgoing);
|
||||
gpr_slice_buffer_init(&h->incoming);
|
||||
if (!connector->is_client_side) {
|
||||
handshake_node = gpr_malloc(sizeof(grpc_security_connector_handshake_list));
|
||||
handshake_node->handshake = h;
|
||||
gpr_mu_lock(&connector->mu);
|
||||
handshake_node->next = connector->handshaking_handshakes;
|
||||
connector->handshaking_handshakes = handshake_node;
|
||||
gpr_mu_unlock(&connector->mu);
|
||||
}
|
||||
send_handshake_bytes_to_peer(exec_ctx, h);
|
||||
}
|
||||
|
||||
void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx,
|
||||
void *handshake) {
|
||||
grpc_security_handshake *h = handshake;
|
||||
grpc_endpoint_shutdown(exec_ctx, h->wrapped_endpoint);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,4 +45,6 @@ void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
|
|||
grpc_security_handshake_done_cb cb,
|
||||
void *user_data);
|
||||
|
||||
void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx, void *handshake);
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_SECURITY_HANDSHAKE_H */
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue