Merge branch 'cleaner-posix2' into cleaner-posix3

pull/5647/head
Craig Tiller 9 years ago
commit ec8eef42b8
  1. 177
      BUILD
  2. 8
      CONTRIBUTING.md
  3. 13
      INSTALL.md
  4. 590
      Makefile
  5. 101
      build.yaml
  6. 11
      composer.json
  7. 447
      examples/README.md
  8. 2
      examples/cpp/README.md
  9. 10
      examples/php/README.md
  10. 11
      examples/php/composer.json
  11. 6
      examples/php/greeter_client.php
  12. 6
      examples/php/route_guide/route_guide_client.php
  13. 2
      examples/python/route_guide/route_guide_server.py
  14. 10
      gRPC.podspec
  15. 10
      grpc.gemspec
  16. 2
      include/grpc++/alarm.h
  17. 2
      include/grpc++/channel.h
  18. 29
      include/grpc++/impl/codegen/async_stream.h
  19. 9
      include/grpc++/impl/codegen/async_unary_call.h
  20. 80
      include/grpc++/impl/codegen/call.h
  21. 3
      include/grpc++/impl/codegen/client_context.h
  22. 3
      include/grpc++/impl/codegen/client_unary_call.h
  23. 44
      include/grpc++/impl/codegen/completion_queue.h
  24. 97
      include/grpc++/impl/codegen/core_codegen_interface.h
  25. 16
      include/grpc++/impl/codegen/grpc_library.h
  26. 463
      include/grpc++/impl/codegen/impl/async_stream.h
  27. 152
      include/grpc++/impl/codegen/impl/status_code_enum.h
  28. 45
      include/grpc++/impl/codegen/impl/sync.h
  29. 5
      include/grpc++/impl/codegen/method_handler_impl.h
  30. 23
      include/grpc++/impl/codegen/proto_utils.h
  31. 3
      include/grpc++/impl/codegen/server_context.h
  32. 7
      include/grpc++/impl/codegen/server_interface.h
  33. 12
      include/grpc++/impl/codegen/service_type.h
  34. 72
      include/grpc++/impl/codegen/string_ref.h
  35. 21
      include/grpc++/impl/codegen/sync_stream.h
  36. 10
      include/grpc++/impl/grpc_library.h
  37. 4
      include/grpc++/security/credentials.h
  38. 2
      include/grpc++/server.h
  39. 35
      include/grpc/impl/codegen/port_platform.h
  40. 10
      package.json
  41. 12
      package.xml
  42. 8
      setup.py
  43. 27
      src/core/channel/client_channel.c
  44. 14
      src/core/channel/subchannel_call_holder.c
  45. 4
      src/core/client_config/client_config.c
  46. 2
      src/core/client_config/lb_policies/pick_first.c
  47. 53
      src/core/client_config/resolvers/dns_resolver.c
  48. 14
      src/core/client_config/subchannel.c
  49. 75
      src/core/iomgr/exec_ctx.c
  50. 23
      src/core/iomgr/exec_ctx.h
  51. 14
      src/core/iomgr/iocp_windows.c
  52. 11
      src/core/iomgr/iocp_windows.h
  53. 3
      src/core/iomgr/iomgr.c
  54. 12
      src/core/iomgr/pollset.h
  55. 6
      src/core/iomgr/resolve_address.h
  56. 19
      src/core/iomgr/resolve_address_posix.c
  57. 19
      src/core/iomgr/resolve_address_windows.c
  58. 3
      src/core/iomgr/tcp_server_windows.c
  59. 16
      src/core/iomgr/timer.c
  60. 1
      src/core/iomgr/timer.h
  61. 16
      src/core/iomgr/timer_heap.c
  62. 4
      src/core/iomgr/workqueue_posix.c
  63. 4
      src/core/support/alloc.c
  64. 2
      src/core/surface/completion_queue.c
  65. 4
      src/core/transport/chttp2_transport.c
  66. 76
      src/core/tsi/ssl_transport_security.c
  67. 5
      src/core/tsi/ssl_transport_security.h
  68. 74
      src/cpp/README.md
  69. 16
      src/cpp/client/secure_credentials.cc
  70. 45
      src/cpp/codegen/codegen_init.cc
  71. 92
      src/cpp/common/call.cc
  72. 33
      src/cpp/common/completion_queue.cc
  73. 86
      src/cpp/common/core_codegen.cc
  74. 71
      src/cpp/common/core_codegen.h
  75. 24
      src/cpp/server/server_context.cc
  76. 66
      src/cpp/util/string_ref.cc
  77. 2
      src/csharp/Grpc.Core/Metadata.cs
  78. 2
      src/node/README.md
  79. 5
      src/node/src/client.js
  80. 37
      src/objective-c/GRPCClient/GRPCCall.m
  81. 3
      src/objective-c/GRPCClient/private/GRPCChannel.h
  82. 14
      src/objective-c/GRPCClient/private/GRPCChannel.m
  83. 7
      src/objective-c/GRPCClient/private/GRPCCompletionQueue.h
  84. 31
      src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
  85. 77
      src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.h
  86. 192
      src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m
  87. 24
      src/objective-c/GRPCClient/private/GRPCHost.h
  88. 71
      src/objective-c/GRPCClient/private/GRPCHost.m
  89. 65
      src/objective-c/GRPCClient/private/GRPCReachabilityFlagNames.xmacro.h
  90. 2
      src/objective-c/GRPCClient/private/GRPCWrappedCall.h
  91. 43
      src/objective-c/RxLibrary/GRXWriteable.m
  92. 2
      src/objective-c/tests/GRPCClientTests.m
  93. 51
      src/objective-c/tests/RxLibraryUnitTests.m
  94. 117
      src/php/README.md
  95. 6
      src/php/composer.json
  96. 67
      src/php/ext/grpc/README.md
  97. 6
      src/php/tests/generated_code/math_client.php
  98. 1
      src/proto/grpc/testing/echo_messages.proto
  99. 12
      src/python/grpcio/README.rst
  100. 3
      src/python/grpcio/commands.py
  101. Some files were not shown because too many files have changed in this diff Show More

177
BUILD

@ -452,17 +452,17 @@ cc_library(
], ],
hdrs = [ hdrs = [
"include/grpc/grpc_security.h", "include/grpc/grpc_security.h",
"include/grpc/byte_buffer.h",
"include/grpc/byte_buffer_reader.h",
"include/grpc/compression.h",
"include/grpc/grpc.h",
"include/grpc/status.h",
"include/grpc/impl/codegen/byte_buffer.h", "include/grpc/impl/codegen/byte_buffer.h",
"include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/compression_types.h",
"include/grpc/impl/codegen/connectivity_state.h", "include/grpc/impl/codegen/connectivity_state.h",
"include/grpc/impl/codegen/grpc_types.h", "include/grpc/impl/codegen/grpc_types.h",
"include/grpc/impl/codegen/propagation_bits.h", "include/grpc/impl/codegen/propagation_bits.h",
"include/grpc/impl/codegen/status.h", "include/grpc/impl/codegen/status.h",
"include/grpc/byte_buffer.h",
"include/grpc/byte_buffer_reader.h",
"include/grpc/compression.h",
"include/grpc/grpc.h",
"include/grpc/status.h",
"include/grpc/census.h", "include/grpc/census.h",
], ],
includes = [ includes = [
@ -480,6 +480,42 @@ cc_library(
) )
cc_library(
name = "grpc_codegen_lib",
srcs = [
],
hdrs = [
"include/grpc/impl/codegen/alloc.h",
"include/grpc/impl/codegen/atm.h",
"include/grpc/impl/codegen/atm_gcc_atomic.h",
"include/grpc/impl/codegen/atm_gcc_sync.h",
"include/grpc/impl/codegen/atm_win32.h",
"include/grpc/impl/codegen/log.h",
"include/grpc/impl/codegen/port_platform.h",
"include/grpc/impl/codegen/slice.h",
"include/grpc/impl/codegen/slice_buffer.h",
"include/grpc/impl/codegen/sync.h",
"include/grpc/impl/codegen/sync_generic.h",
"include/grpc/impl/codegen/sync_posix.h",
"include/grpc/impl/codegen/sync_win32.h",
"include/grpc/impl/codegen/time.h",
"include/grpc/impl/codegen/byte_buffer.h",
"include/grpc/impl/codegen/compression_types.h",
"include/grpc/impl/codegen/connectivity_state.h",
"include/grpc/impl/codegen/grpc_types.h",
"include/grpc/impl/codegen/propagation_bits.h",
"include/grpc/impl/codegen/status.h",
],
includes = [
"include",
".",
],
deps = [
"//external:protobuf_compiler",
],
)
cc_library( cc_library(
name = "grpc_unsecure", name = "grpc_unsecure",
srcs = [ srcs = [
@ -795,9 +831,11 @@ cc_library(
name = "grpc++", name = "grpc++",
srcs = [ srcs = [
"src/cpp/client/secure_credentials.h", "src/cpp/client/secure_credentials.h",
"src/cpp/common/core_codegen.h",
"src/cpp/common/secure_auth_context.h", "src/cpp/common/secure_auth_context.h",
"src/cpp/server/secure_server_credentials.h", "src/cpp/server/secure_server_credentials.h",
"src/cpp/client/create_channel_internal.h", "src/cpp/client/create_channel_internal.h",
"src/cpp/common/core_codegen.h",
"src/cpp/common/create_auth_context.h", "src/cpp/common/create_auth_context.h",
"src/cpp/server/dynamic_thread_pool.h", "src/cpp/server/dynamic_thread_pool.h",
"src/cpp/server/thread_pool_interface.h", "src/cpp/server/thread_pool_interface.h",
@ -814,11 +852,10 @@ cc_library(
"src/cpp/client/credentials.cc", "src/cpp/client/credentials.cc",
"src/cpp/client/generic_stub.cc", "src/cpp/client/generic_stub.cc",
"src/cpp/client/insecure_credentials.cc", "src/cpp/client/insecure_credentials.cc",
"src/cpp/common/call.cc",
"src/cpp/common/channel_arguments.cc", "src/cpp/common/channel_arguments.cc",
"src/cpp/common/completion_queue.cc", "src/cpp/common/completion_queue.cc",
"src/cpp/common/core_codegen.cc",
"src/cpp/common/rpc_method.cc", "src/cpp/common/rpc_method.cc",
"src/cpp/proto/proto_utils.cc",
"src/cpp/server/async_generic_service.cc", "src/cpp/server/async_generic_service.cc",
"src/cpp/server/create_default_thread_pool.cc", "src/cpp/server/create_default_thread_pool.cc",
"src/cpp/server/dynamic_thread_pool.cc", "src/cpp/server/dynamic_thread_pool.cc",
@ -832,7 +869,7 @@ cc_library(
"src/cpp/util/status.cc", "src/cpp/util/status.cc",
"src/cpp/util/string_ref.cc", "src/cpp/util/string_ref.cc",
"src/cpp/util/time.cc", "src/cpp/util/time.cc",
"src/cpp/codegen/grpc_library.cc", "src/cpp/codegen/codegen_init.cc",
], ],
hdrs = [ hdrs = [
"include/grpc++/alarm.h", "include/grpc++/alarm.h",
@ -890,6 +927,7 @@ cc_library(
"include/grpc++/impl/codegen/completion_queue_tag.h", "include/grpc++/impl/codegen/completion_queue_tag.h",
"include/grpc++/impl/codegen/config.h", "include/grpc++/impl/codegen/config.h",
"include/grpc++/impl/codegen/config_protobuf.h", "include/grpc++/impl/codegen/config_protobuf.h",
"include/grpc++/impl/codegen/core_codegen_interface.h",
"include/grpc++/impl/codegen/grpc_library.h", "include/grpc++/impl/codegen/grpc_library.h",
"include/grpc++/impl/codegen/method_handler_impl.h", "include/grpc++/impl/codegen/method_handler_impl.h",
"include/grpc++/impl/codegen/proto_utils.h", "include/grpc++/impl/codegen/proto_utils.h",
@ -922,10 +960,79 @@ cc_library(
) )
cc_library(
name = "grpc++_codegen_lib",
srcs = [
"src/cpp/codegen/codegen_init.cc",
],
hdrs = [
"include/grpc/impl/codegen/alloc.h",
"include/grpc/impl/codegen/atm.h",
"include/grpc/impl/codegen/atm_gcc_atomic.h",
"include/grpc/impl/codegen/atm_gcc_sync.h",
"include/grpc/impl/codegen/atm_win32.h",
"include/grpc/impl/codegen/log.h",
"include/grpc/impl/codegen/port_platform.h",
"include/grpc/impl/codegen/slice.h",
"include/grpc/impl/codegen/slice_buffer.h",
"include/grpc/impl/codegen/sync.h",
"include/grpc/impl/codegen/sync_generic.h",
"include/grpc/impl/codegen/sync_posix.h",
"include/grpc/impl/codegen/sync_win32.h",
"include/grpc/impl/codegen/time.h",
"include/grpc/impl/codegen/byte_buffer.h",
"include/grpc/impl/codegen/compression_types.h",
"include/grpc/impl/codegen/connectivity_state.h",
"include/grpc/impl/codegen/grpc_types.h",
"include/grpc/impl/codegen/propagation_bits.h",
"include/grpc/impl/codegen/status.h",
"include/grpc++/impl/codegen/async_stream.h",
"include/grpc++/impl/codegen/async_unary_call.h",
"include/grpc++/impl/codegen/call.h",
"include/grpc++/impl/codegen/call_hook.h",
"include/grpc++/impl/codegen/channel_interface.h",
"include/grpc++/impl/codegen/client_context.h",
"include/grpc++/impl/codegen/client_unary_call.h",
"include/grpc++/impl/codegen/completion_queue.h",
"include/grpc++/impl/codegen/completion_queue_tag.h",
"include/grpc++/impl/codegen/config.h",
"include/grpc++/impl/codegen/config_protobuf.h",
"include/grpc++/impl/codegen/core_codegen_interface.h",
"include/grpc++/impl/codegen/grpc_library.h",
"include/grpc++/impl/codegen/method_handler_impl.h",
"include/grpc++/impl/codegen/proto_utils.h",
"include/grpc++/impl/codegen/rpc_method.h",
"include/grpc++/impl/codegen/rpc_service_method.h",
"include/grpc++/impl/codegen/security/auth_context.h",
"include/grpc++/impl/codegen/serialization_traits.h",
"include/grpc++/impl/codegen/server_context.h",
"include/grpc++/impl/codegen/server_interface.h",
"include/grpc++/impl/codegen/service_type.h",
"include/grpc++/impl/codegen/status.h",
"include/grpc++/impl/codegen/status_code_enum.h",
"include/grpc++/impl/codegen/string_ref.h",
"include/grpc++/impl/codegen/stub_options.h",
"include/grpc++/impl/codegen/sync.h",
"include/grpc++/impl/codegen/sync_cxx11.h",
"include/grpc++/impl/codegen/sync_no_cxx11.h",
"include/grpc++/impl/codegen/sync_stream.h",
"include/grpc++/impl/codegen/time.h",
],
includes = [
"include",
".",
],
deps = [
"//external:protobuf_compiler",
],
)
cc_library( cc_library(
name = "grpc++_unsecure", name = "grpc++_unsecure",
srcs = [ srcs = [
"src/cpp/client/create_channel_internal.h", "src/cpp/client/create_channel_internal.h",
"src/cpp/common/core_codegen.h",
"src/cpp/common/create_auth_context.h", "src/cpp/common/create_auth_context.h",
"src/cpp/server/dynamic_thread_pool.h", "src/cpp/server/dynamic_thread_pool.h",
"src/cpp/server/thread_pool_interface.h", "src/cpp/server/thread_pool_interface.h",
@ -937,11 +1044,10 @@ cc_library(
"src/cpp/client/credentials.cc", "src/cpp/client/credentials.cc",
"src/cpp/client/generic_stub.cc", "src/cpp/client/generic_stub.cc",
"src/cpp/client/insecure_credentials.cc", "src/cpp/client/insecure_credentials.cc",
"src/cpp/common/call.cc",
"src/cpp/common/channel_arguments.cc", "src/cpp/common/channel_arguments.cc",
"src/cpp/common/completion_queue.cc", "src/cpp/common/completion_queue.cc",
"src/cpp/common/core_codegen.cc",
"src/cpp/common/rpc_method.cc", "src/cpp/common/rpc_method.cc",
"src/cpp/proto/proto_utils.cc",
"src/cpp/server/async_generic_service.cc", "src/cpp/server/async_generic_service.cc",
"src/cpp/server/create_default_thread_pool.cc", "src/cpp/server/create_default_thread_pool.cc",
"src/cpp/server/dynamic_thread_pool.cc", "src/cpp/server/dynamic_thread_pool.cc",
@ -955,7 +1061,7 @@ cc_library(
"src/cpp/util/status.cc", "src/cpp/util/status.cc",
"src/cpp/util/string_ref.cc", "src/cpp/util/string_ref.cc",
"src/cpp/util/time.cc", "src/cpp/util/time.cc",
"src/cpp/codegen/grpc_library.cc", "src/cpp/codegen/codegen_init.cc",
], ],
hdrs = [ hdrs = [
"include/grpc++/alarm.h", "include/grpc++/alarm.h",
@ -1013,6 +1119,7 @@ cc_library(
"include/grpc++/impl/codegen/completion_queue_tag.h", "include/grpc++/impl/codegen/completion_queue_tag.h",
"include/grpc++/impl/codegen/config.h", "include/grpc++/impl/codegen/config.h",
"include/grpc++/impl/codegen/config_protobuf.h", "include/grpc++/impl/codegen/config_protobuf.h",
"include/grpc++/impl/codegen/core_codegen_interface.h",
"include/grpc++/impl/codegen/grpc_library.h", "include/grpc++/impl/codegen/grpc_library.h",
"include/grpc++/impl/codegen/method_handler_impl.h", "include/grpc++/impl/codegen/method_handler_impl.h",
"include/grpc++/impl/codegen/proto_utils.h", "include/grpc++/impl/codegen/proto_utils.h",
@ -1068,45 +1175,8 @@ cc_library(
"src/compiler/objective_c_generator.cc", "src/compiler/objective_c_generator.cc",
"src/compiler/python_generator.cc", "src/compiler/python_generator.cc",
"src/compiler/ruby_generator.cc", "src/compiler/ruby_generator.cc",
"src/cpp/codegen/grpc_library.cc",
], ],
hdrs = [ hdrs = [
"include/grpc++/impl/codegen/async_stream.h",
"include/grpc++/impl/codegen/async_unary_call.h",
"include/grpc++/impl/codegen/call.h",
"include/grpc++/impl/codegen/call_hook.h",
"include/grpc++/impl/codegen/channel_interface.h",
"include/grpc++/impl/codegen/client_context.h",
"include/grpc++/impl/codegen/client_unary_call.h",
"include/grpc++/impl/codegen/completion_queue.h",
"include/grpc++/impl/codegen/completion_queue_tag.h",
"include/grpc++/impl/codegen/config.h",
"include/grpc++/impl/codegen/config_protobuf.h",
"include/grpc++/impl/codegen/grpc_library.h",
"include/grpc++/impl/codegen/method_handler_impl.h",
"include/grpc++/impl/codegen/proto_utils.h",
"include/grpc++/impl/codegen/rpc_method.h",
"include/grpc++/impl/codegen/rpc_service_method.h",
"include/grpc++/impl/codegen/security/auth_context.h",
"include/grpc++/impl/codegen/serialization_traits.h",
"include/grpc++/impl/codegen/server_context.h",
"include/grpc++/impl/codegen/server_interface.h",
"include/grpc++/impl/codegen/service_type.h",
"include/grpc++/impl/codegen/status.h",
"include/grpc++/impl/codegen/status_code_enum.h",
"include/grpc++/impl/codegen/string_ref.h",
"include/grpc++/impl/codegen/stub_options.h",
"include/grpc++/impl/codegen/sync.h",
"include/grpc++/impl/codegen/sync_cxx11.h",
"include/grpc++/impl/codegen/sync_no_cxx11.h",
"include/grpc++/impl/codegen/sync_stream.h",
"include/grpc++/impl/codegen/time.h",
"include/grpc/impl/codegen/byte_buffer.h",
"include/grpc/impl/codegen/compression_types.h",
"include/grpc/impl/codegen/connectivity_state.h",
"include/grpc/impl/codegen/grpc_types.h",
"include/grpc/impl/codegen/propagation_bits.h",
"include/grpc/impl/codegen/status.h",
"include/grpc/impl/codegen/alloc.h", "include/grpc/impl/codegen/alloc.h",
"include/grpc/impl/codegen/atm.h", "include/grpc/impl/codegen/atm.h",
"include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_atomic.h",
@ -1128,6 +1198,7 @@ cc_library(
], ],
deps = [ deps = [
"//external:protobuf_compiler", "//external:protobuf_compiler",
":grpc++_codegen_lib",
], ],
) )
@ -1426,17 +1497,17 @@ objc_library(
], ],
hdrs = [ hdrs = [
"include/grpc/grpc_security.h", "include/grpc/grpc_security.h",
"include/grpc/byte_buffer.h",
"include/grpc/byte_buffer_reader.h",
"include/grpc/compression.h",
"include/grpc/grpc.h",
"include/grpc/status.h",
"include/grpc/impl/codegen/byte_buffer.h", "include/grpc/impl/codegen/byte_buffer.h",
"include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/compression_types.h",
"include/grpc/impl/codegen/connectivity_state.h", "include/grpc/impl/codegen/connectivity_state.h",
"include/grpc/impl/codegen/grpc_types.h", "include/grpc/impl/codegen/grpc_types.h",
"include/grpc/impl/codegen/propagation_bits.h", "include/grpc/impl/codegen/propagation_bits.h",
"include/grpc/impl/codegen/status.h", "include/grpc/impl/codegen/status.h",
"include/grpc/byte_buffer.h",
"include/grpc/byte_buffer_reader.h",
"include/grpc/compression.h",
"include/grpc/grpc.h",
"include/grpc/status.h",
"include/grpc/census.h", "include/grpc/census.h",
"src/core/census/grpc_filter.h", "src/core/census/grpc_filter.h",
"src/core/channel/channel_args.h", "src/core/channel/channel_args.h",

@ -45,9 +45,13 @@ In order to run most of the available tests, one would need to run:
`./tools/run_tests/run_tests.py` `./tools/run_tests/run_tests.py`
If you want to run all the possible tests for any of the languages {c, c++, node, php, python}, do this: If you want to run tests for any of the languages {c, c++, csharp, node, objc, php, python, ruby}, do this:
`./tools/run_tests/run_tests.py -l <lang> -c all` `./tools/run_tests/run_tests.py -l <lang>`
To know about the list of available commands, do this:
`./tools/run_tests/run_tests.py -h`
## Adding or removing source code ## Adding or removing source code

@ -3,7 +3,7 @@
For language-specific installation instructions for gRPC runtime, please For language-specific installation instructions for gRPC runtime, please
refer to these documents refer to these documents
* [C++](examples/cpp) * [C++](examples/cpp): Currently to install gRPC for C++, you need to build from source as described below.
* [C#](src/csharp): NuGet package `Grpc` * [C#](src/csharp): NuGet package `Grpc`
* [Go](https://github.com/grpc/grpc-go): `go get google.golang.org/grpc` * [Go](https://github.com/grpc/grpc-go): `go get google.golang.org/grpc`
* [Java](https://github.com/grpc/grpc-java) * [Java](https://github.com/grpc/grpc-java)
@ -32,6 +32,17 @@ terminal:
$ [sudo] xcode-select --install $ [sudo] xcode-select --install
``` ```
##Protoc
By default gRPC uses [protocol buffers](https://github.com/google/protobuf),
you will need the `protoc` compiler to generate stub server and client code.
If you compile gRPC from source, as described below, the Makefile will
automatically try and compile the `protoc` in third_party if you cloned the
repository recursively and it detects that you don't already have it
installed.
#Build from Source #Build from Source
For developers who are interested to contribute, here is how to compile the For developers who are interested to contribute, here is how to compile the

@ -95,6 +95,46 @@ LDXX_opt = $(DEFAULT_CXX)
CPPFLAGS_opt = -O2 CPPFLAGS_opt = -O2
DEFINES_opt = NDEBUG DEFINES_opt = NDEBUG
VALID_CONFIG_dbg = 1
CC_dbg = $(DEFAULT_CC)
CXX_dbg = $(DEFAULT_CXX)
LD_dbg = $(DEFAULT_CC)
LDXX_dbg = $(DEFAULT_CXX)
CPPFLAGS_dbg = -O0
DEFINES_dbg = _DEBUG DEBUG
VALID_CONFIG_easan = 1
REQUIRE_CUSTOM_LIBRARIES_easan = 1
CC_easan = clang
CXX_easan = clang++
LD_easan = clang
LDXX_easan = clang++
CPPFLAGS_easan = -O0 -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
LDFLAGS_easan = -fsanitize=address
DEFINES_easan = _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
DEFINES_easan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
VALID_CONFIG_asan = 1
REQUIRE_CUSTOM_LIBRARIES_asan = 1
CC_asan = clang
CXX_asan = clang++
LD_asan = clang
LDXX_asan = clang++
CPPFLAGS_asan = -O0 -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
LDFLAGS_asan = -fsanitize=address
DEFINES_asan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
VALID_CONFIG_msan = 1
REQUIRE_CUSTOM_LIBRARIES_msan = 1
CC_msan = clang
CXX_msan = clang++
LD_msan = clang
LDXX_msan = clang++
CPPFLAGS_msan = -O0 -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -Wno-unused-command-line-argument -fPIE -pie -DGPR_NO_DIRECT_SYSCALLS
LDFLAGS_msan = -fsanitize=memory -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -fPIE -pie $(if $(JENKINS_BUILD),-Wl$(comma)-Ttext-segment=0x7e0000000000,)
DEFINES_msan = NDEBUG
DEFINES_msan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=4
VALID_CONFIG_basicprof = 1 VALID_CONFIG_basicprof = 1
CC_basicprof = $(DEFAULT_CC) CC_basicprof = $(DEFAULT_CC)
CXX_basicprof = $(DEFAULT_CXX) CXX_basicprof = $(DEFAULT_CXX)
@ -123,6 +163,14 @@ CPPFLAGS_asan-noleaks = -O0 -fsanitize=address -fno-omit-frame-pointer -Wno-unus
LDFLAGS_asan-noleaks = -fsanitize=address LDFLAGS_asan-noleaks = -fsanitize=address
DEFINES_asan-noleaks += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3 DEFINES_asan-noleaks += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
VALID_CONFIG_edbg = 1
CC_edbg = $(DEFAULT_CC)
CXX_edbg = $(DEFAULT_CXX)
LD_edbg = $(DEFAULT_CC)
LDXX_edbg = $(DEFAULT_CXX)
CPPFLAGS_edbg = -O0
DEFINES_edbg = _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
VALID_CONFIG_ubsan = 1 VALID_CONFIG_ubsan = 1
REQUIRE_CUSTOM_LIBRARIES_ubsan = 1 REQUIRE_CUSTOM_LIBRARIES_ubsan = 1
CC_ubsan = clang CC_ubsan = clang
@ -134,13 +182,15 @@ LDFLAGS_ubsan = -fsanitize=undefined
DEFINES_ubsan = NDEBUG DEFINES_ubsan = NDEBUG
DEFINES_ubsan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=1.5 DEFINES_ubsan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=1.5
VALID_CONFIG_dbg = 1 VALID_CONFIG_tsan = 1
CC_dbg = $(DEFAULT_CC) REQUIRE_CUSTOM_LIBRARIES_tsan = 1
CXX_dbg = $(DEFAULT_CXX) CC_tsan = clang
LD_dbg = $(DEFAULT_CC) CXX_tsan = clang++
LDXX_dbg = $(DEFAULT_CXX) LD_tsan = clang
CPPFLAGS_dbg = -O0 LDXX_tsan = clang++
DEFINES_dbg = _DEBUG DEBUG CPPFLAGS_tsan = -O0 -fsanitize=thread -fno-omit-frame-pointer -Wno-unused-command-line-argument -fPIE -pie -DGPR_NO_DIRECT_SYSCALLS
LDFLAGS_tsan = -fsanitize=thread -fPIE -pie $(if $(JENKINS_BUILD),-Wl$(comma)-Ttext-segment=0x7e0000000000,)
DEFINES_tsan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=5
VALID_CONFIG_stapprof = 1 VALID_CONFIG_stapprof = 1
CC_stapprof = $(DEFAULT_CC) CC_stapprof = $(DEFAULT_CC)
@ -150,14 +200,14 @@ LDXX_stapprof = $(DEFAULT_CXX)
CPPFLAGS_stapprof = -O2 -DGRPC_STAP_PROFILER CPPFLAGS_stapprof = -O2 -DGRPC_STAP_PROFILER
DEFINES_stapprof = NDEBUG DEFINES_stapprof = NDEBUG
VALID_CONFIG_gcov = 1 VALID_CONFIG_mutrace = 1
CC_gcov = gcc CC_mutrace = $(DEFAULT_CC)
CXX_gcov = g++ CXX_mutrace = $(DEFAULT_CXX)
LD_gcov = gcc LD_mutrace = $(DEFAULT_CC)
LDXX_gcov = g++ LDXX_mutrace = $(DEFAULT_CXX)
CPPFLAGS_gcov = -O0 -fprofile-arcs -ftest-coverage -Wno-return-type CPPFLAGS_mutrace = -O0
LDFLAGS_gcov = -fprofile-arcs -ftest-coverage -rdynamic LDFLAGS_mutrace = -rdynamic
DEFINES_gcov = _DEBUG DEBUG GPR_GCOV DEFINES_mutrace = _DEBUG DEBUG
VALID_CONFIG_memcheck = 1 VALID_CONFIG_memcheck = 1
CC_memcheck = $(DEFAULT_CC) CC_memcheck = $(DEFAULT_CC)
@ -169,45 +219,25 @@ LDFLAGS_memcheck = -rdynamic
DEFINES_memcheck = _DEBUG DEBUG DEFINES_memcheck = _DEBUG DEBUG
DEFINES_memcheck += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=10 DEFINES_memcheck += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=10
VALID_CONFIG_asan = 1 VALID_CONFIG_etsan = 1
REQUIRE_CUSTOM_LIBRARIES_asan = 1 REQUIRE_CUSTOM_LIBRARIES_etsan = 1
CC_asan = clang CC_etsan = clang
CXX_asan = clang++ CXX_etsan = clang++
LD_asan = clang LD_etsan = clang
LDXX_asan = clang++ LDXX_etsan = clang++
CPPFLAGS_asan = -O0 -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS CPPFLAGS_etsan = -O0 -fsanitize=thread -fno-omit-frame-pointer -Wno-unused-command-line-argument -fPIE -pie -DGPR_NO_DIRECT_SYSCALLS
LDFLAGS_asan = -fsanitize=address LDFLAGS_etsan = -fsanitize=thread -fPIE -pie $(if $(JENKINS_BUILD),-Wl$(comma)-Ttext-segment=0x7e0000000000,)
DEFINES_asan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3 DEFINES_etsan = _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
DEFINES_etsan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=5
VALID_CONFIG_tsan = 1 VALID_CONFIG_gcov = 1
REQUIRE_CUSTOM_LIBRARIES_tsan = 1 CC_gcov = gcc
CC_tsan = clang CXX_gcov = g++
CXX_tsan = clang++ LD_gcov = gcc
LD_tsan = clang LDXX_gcov = g++
LDXX_tsan = clang++ CPPFLAGS_gcov = -O0 -fprofile-arcs -ftest-coverage -Wno-return-type
CPPFLAGS_tsan = -O0 -fsanitize=thread -fno-omit-frame-pointer -Wno-unused-command-line-argument -fPIE -pie -DGPR_NO_DIRECT_SYSCALLS LDFLAGS_gcov = -fprofile-arcs -ftest-coverage -rdynamic
LDFLAGS_tsan = -fsanitize=thread -fPIE -pie $(if $(JENKINS_BUILD),-Wl$(comma)-Ttext-segment=0x7e0000000000,) DEFINES_gcov = _DEBUG DEBUG GPR_GCOV
DEFINES_tsan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=5
VALID_CONFIG_msan = 1
REQUIRE_CUSTOM_LIBRARIES_msan = 1
CC_msan = clang
CXX_msan = clang++
LD_msan = clang
LDXX_msan = clang++
CPPFLAGS_msan = -O0 -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -Wno-unused-command-line-argument -fPIE -pie -DGPR_NO_DIRECT_SYSCALLS
LDFLAGS_msan = -fsanitize=memory -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -fPIE -pie $(if $(JENKINS_BUILD),-Wl$(comma)-Ttext-segment=0x7e0000000000,)
DEFINES_msan = NDEBUG
DEFINES_msan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=4
VALID_CONFIG_mutrace = 1
CC_mutrace = $(DEFAULT_CC)
CXX_mutrace = $(DEFAULT_CXX)
LD_mutrace = $(DEFAULT_CC)
LDXX_mutrace = $(DEFAULT_CXX)
CPPFLAGS_mutrace = -O0
LDFLAGS_mutrace = -rdynamic
DEFINES_mutrace = _DEBUG DEBUG
@ -849,6 +879,8 @@ chttp2_status_conversion_test: $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test
chttp2_stream_map_test: $(BINDIR)/$(CONFIG)/chttp2_stream_map_test chttp2_stream_map_test: $(BINDIR)/$(CONFIG)/chttp2_stream_map_test
chttp2_varint_test: $(BINDIR)/$(CONFIG)/chttp2_varint_test chttp2_varint_test: $(BINDIR)/$(CONFIG)/chttp2_varint_test
compression_test: $(BINDIR)/$(CONFIG)/compression_test compression_test: $(BINDIR)/$(CONFIG)/compression_test
concurrent_connectivity_test: $(BINDIR)/$(CONFIG)/concurrent_connectivity_test
dns_resolver_connectivity_test: $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test
dns_resolver_test: $(BINDIR)/$(CONFIG)/dns_resolver_test dns_resolver_test: $(BINDIR)/$(CONFIG)/dns_resolver_test
dualstack_socket_test: $(BINDIR)/$(CONFIG)/dualstack_socket_test dualstack_socket_test: $(BINDIR)/$(CONFIG)/dualstack_socket_test
endpoint_pair_test: $(BINDIR)/$(CONFIG)/endpoint_pair_test endpoint_pair_test: $(BINDIR)/$(CONFIG)/endpoint_pair_test
@ -944,6 +976,7 @@ channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test
cli_call_test: $(BINDIR)/$(CONFIG)/cli_call_test cli_call_test: $(BINDIR)/$(CONFIG)/cli_call_test
client_crash_test: $(BINDIR)/$(CONFIG)/client_crash_test client_crash_test: $(BINDIR)/$(CONFIG)/client_crash_test
client_crash_test_server: $(BINDIR)/$(CONFIG)/client_crash_test_server client_crash_test_server: $(BINDIR)/$(CONFIG)/client_crash_test_server
codegen_test: $(BINDIR)/$(CONFIG)/codegen_test
credentials_test: $(BINDIR)/$(CONFIG)/credentials_test credentials_test: $(BINDIR)/$(CONFIG)/credentials_test
cxx_byte_buffer_test: $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test cxx_byte_buffer_test: $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test
cxx_slice_test: $(BINDIR)/$(CONFIG)/cxx_slice_test cxx_slice_test: $(BINDIR)/$(CONFIG)/cxx_slice_test
@ -1113,7 +1146,7 @@ plugins: $(PROTOC_PLUGINS)
privatelibs: privatelibs_c privatelibs_cxx privatelibs: privatelibs_c privatelibs_cxx
privatelibs_c: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libz.a $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libbad_ssl_test_server.a $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a privatelibs_c: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libz.a $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libbad_ssl_test_server.a $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a
pc_c: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc.pc pc_c: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc.pc
pc_c_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_unsecure.pc pc_c_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_unsecure.pc
@ -1152,6 +1185,8 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/chttp2_stream_map_test \ $(BINDIR)/$(CONFIG)/chttp2_stream_map_test \
$(BINDIR)/$(CONFIG)/chttp2_varint_test \ $(BINDIR)/$(CONFIG)/chttp2_varint_test \
$(BINDIR)/$(CONFIG)/compression_test \ $(BINDIR)/$(CONFIG)/compression_test \
$(BINDIR)/$(CONFIG)/concurrent_connectivity_test \
$(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test \
$(BINDIR)/$(CONFIG)/dns_resolver_test \ $(BINDIR)/$(CONFIG)/dns_resolver_test \
$(BINDIR)/$(CONFIG)/dualstack_socket_test \ $(BINDIR)/$(CONFIG)/dualstack_socket_test \
$(BINDIR)/$(CONFIG)/endpoint_pair_test \ $(BINDIR)/$(CONFIG)/endpoint_pair_test \
@ -1280,6 +1315,7 @@ buildtests_cxx: buildtests_zookeeper privatelibs_cxx \
$(BINDIR)/$(CONFIG)/cli_call_test \ $(BINDIR)/$(CONFIG)/cli_call_test \
$(BINDIR)/$(CONFIG)/client_crash_test \ $(BINDIR)/$(CONFIG)/client_crash_test \
$(BINDIR)/$(CONFIG)/client_crash_test_server \ $(BINDIR)/$(CONFIG)/client_crash_test_server \
$(BINDIR)/$(CONFIG)/codegen_test \
$(BINDIR)/$(CONFIG)/credentials_test \ $(BINDIR)/$(CONFIG)/credentials_test \
$(BINDIR)/$(CONFIG)/cxx_byte_buffer_test \ $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test \
$(BINDIR)/$(CONFIG)/cxx_slice_test \ $(BINDIR)/$(CONFIG)/cxx_slice_test \
@ -1388,6 +1424,10 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/chttp2_varint_test || ( echo test chttp2_varint_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/chttp2_varint_test || ( echo test chttp2_varint_test failed ; exit 1 )
$(E) "[RUN] Testing compression_test" $(E) "[RUN] Testing compression_test"
$(Q) $(BINDIR)/$(CONFIG)/compression_test || ( echo test compression_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/compression_test || ( echo test compression_test failed ; exit 1 )
$(E) "[RUN] Testing concurrent_connectivity_test"
$(Q) $(BINDIR)/$(CONFIG)/concurrent_connectivity_test || ( echo test concurrent_connectivity_test failed ; exit 1 )
$(E) "[RUN] Testing dns_resolver_connectivity_test"
$(Q) $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test || ( echo test dns_resolver_connectivity_test failed ; exit 1 )
$(E) "[RUN] Testing dns_resolver_test" $(E) "[RUN] Testing dns_resolver_test"
$(Q) $(BINDIR)/$(CONFIG)/dns_resolver_test || ( echo test dns_resolver_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/dns_resolver_test || ( echo test dns_resolver_test failed ; exit 1 )
$(E) "[RUN] Testing dualstack_socket_test" $(E) "[RUN] Testing dualstack_socket_test"
@ -1584,6 +1624,8 @@ test_cxx: test_zookeeper buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/cli_call_test || ( echo test cli_call_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/cli_call_test || ( echo test cli_call_test failed ; exit 1 )
$(E) "[RUN] Testing client_crash_test" $(E) "[RUN] Testing client_crash_test"
$(Q) $(BINDIR)/$(CONFIG)/client_crash_test || ( echo test client_crash_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/client_crash_test || ( echo test client_crash_test failed ; exit 1 )
$(E) "[RUN] Testing codegen_test"
$(Q) $(BINDIR)/$(CONFIG)/codegen_test || ( echo test codegen_test failed ; exit 1 )
$(E) "[RUN] Testing credentials_test" $(E) "[RUN] Testing credentials_test"
$(Q) $(BINDIR)/$(CONFIG)/credentials_test || ( echo test credentials_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/credentials_test || ( echo test credentials_test failed ; exit 1 )
$(E) "[RUN] Testing cxx_byte_buffer_test" $(E) "[RUN] Testing cxx_byte_buffer_test"
@ -2501,17 +2543,17 @@ LIBGRPC_SRC = \
PUBLIC_HEADERS_C += \ PUBLIC_HEADERS_C += \
include/grpc/grpc_security.h \ include/grpc/grpc_security.h \
include/grpc/byte_buffer.h \
include/grpc/byte_buffer_reader.h \
include/grpc/compression.h \
include/grpc/grpc.h \
include/grpc/status.h \
include/grpc/impl/codegen/byte_buffer.h \ include/grpc/impl/codegen/byte_buffer.h \
include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/compression_types.h \
include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/connectivity_state.h \
include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/grpc_types.h \
include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/propagation_bits.h \
include/grpc/impl/codegen/status.h \ include/grpc/impl/codegen/status.h \
include/grpc/byte_buffer.h \
include/grpc/byte_buffer_reader.h \
include/grpc/compression.h \
include/grpc/grpc.h \
include/grpc/status.h \
include/grpc/census.h \ include/grpc/census.h \
LIBGRPC_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_SRC)))) LIBGRPC_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_SRC))))
@ -2566,6 +2608,50 @@ endif
endif endif
LIBGRPC_CODEGEN_LIB_SRC = \
PUBLIC_HEADERS_C += \
include/grpc/impl/codegen/alloc.h \
include/grpc/impl/codegen/atm.h \
include/grpc/impl/codegen/atm_gcc_atomic.h \
include/grpc/impl/codegen/atm_gcc_sync.h \
include/grpc/impl/codegen/atm_win32.h \
include/grpc/impl/codegen/log.h \
include/grpc/impl/codegen/port_platform.h \
include/grpc/impl/codegen/slice.h \
include/grpc/impl/codegen/slice_buffer.h \
include/grpc/impl/codegen/sync.h \
include/grpc/impl/codegen/sync_generic.h \
include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_win32.h \
include/grpc/impl/codegen/time.h \
include/grpc/impl/codegen/byte_buffer.h \
include/grpc/impl/codegen/compression_types.h \
include/grpc/impl/codegen/connectivity_state.h \
include/grpc/impl/codegen/grpc_types.h \
include/grpc/impl/codegen/propagation_bits.h \
include/grpc/impl/codegen/status.h \
LIBGRPC_CODEGEN_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_CODEGEN_LIB_SRC))))
$(LIBDIR)/$(CONFIG)/libgrpc_codegen_lib.a: $(ZLIB_DEP) $(LIBGRPC_CODEGEN_LIB_OBJS)
$(E) "[AR] Creating $@"
$(Q) mkdir -p `dirname $@`
$(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc_codegen_lib.a
$(Q) $(AR) $(LIBDIR)/$(CONFIG)/libgrpc_codegen_lib.a $(LIBGRPC_CODEGEN_LIB_OBJS)
ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc_codegen_lib.a
endif
ifneq ($(NO_DEPS),true)
-include $(LIBGRPC_CODEGEN_LIB_OBJS:.o=.dep)
endif
LIBGRPC_TEST_UTIL_SRC = \ LIBGRPC_TEST_UTIL_SRC = \
test/core/end2end/data/server1_cert.c \ test/core/end2end/data/server1_cert.c \
test/core/end2end/data/server1_key.c \ test/core/end2end/data/server1_key.c \
@ -2972,11 +3058,10 @@ LIBGRPC++_SRC = \
src/cpp/client/credentials.cc \ src/cpp/client/credentials.cc \
src/cpp/client/generic_stub.cc \ src/cpp/client/generic_stub.cc \
src/cpp/client/insecure_credentials.cc \ src/cpp/client/insecure_credentials.cc \
src/cpp/common/call.cc \
src/cpp/common/channel_arguments.cc \ src/cpp/common/channel_arguments.cc \
src/cpp/common/completion_queue.cc \ src/cpp/common/completion_queue.cc \
src/cpp/common/core_codegen.cc \
src/cpp/common/rpc_method.cc \ src/cpp/common/rpc_method.cc \
src/cpp/proto/proto_utils.cc \
src/cpp/server/async_generic_service.cc \ src/cpp/server/async_generic_service.cc \
src/cpp/server/create_default_thread_pool.cc \ src/cpp/server/create_default_thread_pool.cc \
src/cpp/server/dynamic_thread_pool.cc \ src/cpp/server/dynamic_thread_pool.cc \
@ -2990,7 +3075,7 @@ LIBGRPC++_SRC = \
src/cpp/util/status.cc \ src/cpp/util/status.cc \
src/cpp/util/string_ref.cc \ src/cpp/util/string_ref.cc \
src/cpp/util/time.cc \ src/cpp/util/time.cc \
src/cpp/codegen/grpc_library.cc \ src/cpp/codegen/codegen_init.cc \
PUBLIC_HEADERS_CXX += \ PUBLIC_HEADERS_CXX += \
include/grpc++/alarm.h \ include/grpc++/alarm.h \
@ -3048,6 +3133,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/codegen/completion_queue_tag.h \ include/grpc++/impl/codegen/completion_queue_tag.h \
include/grpc++/impl/codegen/config.h \ include/grpc++/impl/codegen/config.h \
include/grpc++/impl/codegen/config_protobuf.h \ include/grpc++/impl/codegen/config_protobuf.h \
include/grpc++/impl/codegen/core_codegen_interface.h \
include/grpc++/impl/codegen/grpc_library.h \ include/grpc++/impl/codegen/grpc_library.h \
include/grpc++/impl/codegen/method_handler_impl.h \ include/grpc++/impl/codegen/method_handler_impl.h \
include/grpc++/impl/codegen/proto_utils.h \ include/grpc++/impl/codegen/proto_utils.h \
@ -3131,6 +3217,93 @@ endif
endif endif
LIBGRPC++_CODEGEN_LIB_SRC = \
src/cpp/codegen/codegen_init.cc \
PUBLIC_HEADERS_CXX += \
include/grpc/impl/codegen/alloc.h \
include/grpc/impl/codegen/atm.h \
include/grpc/impl/codegen/atm_gcc_atomic.h \
include/grpc/impl/codegen/atm_gcc_sync.h \
include/grpc/impl/codegen/atm_win32.h \
include/grpc/impl/codegen/log.h \
include/grpc/impl/codegen/port_platform.h \
include/grpc/impl/codegen/slice.h \
include/grpc/impl/codegen/slice_buffer.h \
include/grpc/impl/codegen/sync.h \
include/grpc/impl/codegen/sync_generic.h \
include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_win32.h \
include/grpc/impl/codegen/time.h \
include/grpc/impl/codegen/byte_buffer.h \
include/grpc/impl/codegen/compression_types.h \
include/grpc/impl/codegen/connectivity_state.h \
include/grpc/impl/codegen/grpc_types.h \
include/grpc/impl/codegen/propagation_bits.h \
include/grpc/impl/codegen/status.h \
include/grpc++/impl/codegen/async_stream.h \
include/grpc++/impl/codegen/async_unary_call.h \
include/grpc++/impl/codegen/call.h \
include/grpc++/impl/codegen/call_hook.h \
include/grpc++/impl/codegen/channel_interface.h \
include/grpc++/impl/codegen/client_context.h \
include/grpc++/impl/codegen/client_unary_call.h \
include/grpc++/impl/codegen/completion_queue.h \
include/grpc++/impl/codegen/completion_queue_tag.h \
include/grpc++/impl/codegen/config.h \
include/grpc++/impl/codegen/config_protobuf.h \
include/grpc++/impl/codegen/core_codegen_interface.h \
include/grpc++/impl/codegen/grpc_library.h \
include/grpc++/impl/codegen/method_handler_impl.h \
include/grpc++/impl/codegen/proto_utils.h \
include/grpc++/impl/codegen/rpc_method.h \
include/grpc++/impl/codegen/rpc_service_method.h \
include/grpc++/impl/codegen/security/auth_context.h \
include/grpc++/impl/codegen/serialization_traits.h \
include/grpc++/impl/codegen/server_context.h \
include/grpc++/impl/codegen/server_interface.h \
include/grpc++/impl/codegen/service_type.h \
include/grpc++/impl/codegen/status.h \
include/grpc++/impl/codegen/status_code_enum.h \
include/grpc++/impl/codegen/string_ref.h \
include/grpc++/impl/codegen/stub_options.h \
include/grpc++/impl/codegen/sync.h \
include/grpc++/impl/codegen/sync_cxx11.h \
include/grpc++/impl/codegen/sync_no_cxx11.h \
include/grpc++/impl/codegen/sync_stream.h \
include/grpc++/impl/codegen/time.h \
LIBGRPC++_CODEGEN_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_CODEGEN_LIB_SRC))))
ifeq ($(NO_PROTOBUF),true)
# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay.
$(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a: protobuf_dep_error
else
$(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a: $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBGRPC++_CODEGEN_LIB_OBJS)
$(E) "[AR] Creating $@"
$(Q) mkdir -p `dirname $@`
$(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
$(Q) $(AR) $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a $(LIBGRPC++_CODEGEN_LIB_OBJS)
ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
endif
endif
ifneq ($(NO_DEPS),true)
-include $(LIBGRPC++_CODEGEN_LIB_OBJS:.o=.dep)
endif
LIBGRPC++_TEST_CONFIG_SRC = \ LIBGRPC++_TEST_CONFIG_SRC = \
test/cpp/util/test_config.cc \ test/cpp/util/test_config.cc \
@ -3252,11 +3425,10 @@ LIBGRPC++_UNSECURE_SRC = \
src/cpp/client/credentials.cc \ src/cpp/client/credentials.cc \
src/cpp/client/generic_stub.cc \ src/cpp/client/generic_stub.cc \
src/cpp/client/insecure_credentials.cc \ src/cpp/client/insecure_credentials.cc \
src/cpp/common/call.cc \
src/cpp/common/channel_arguments.cc \ src/cpp/common/channel_arguments.cc \
src/cpp/common/completion_queue.cc \ src/cpp/common/completion_queue.cc \
src/cpp/common/core_codegen.cc \
src/cpp/common/rpc_method.cc \ src/cpp/common/rpc_method.cc \
src/cpp/proto/proto_utils.cc \
src/cpp/server/async_generic_service.cc \ src/cpp/server/async_generic_service.cc \
src/cpp/server/create_default_thread_pool.cc \ src/cpp/server/create_default_thread_pool.cc \
src/cpp/server/dynamic_thread_pool.cc \ src/cpp/server/dynamic_thread_pool.cc \
@ -3270,7 +3442,7 @@ LIBGRPC++_UNSECURE_SRC = \
src/cpp/util/status.cc \ src/cpp/util/status.cc \
src/cpp/util/string_ref.cc \ src/cpp/util/string_ref.cc \
src/cpp/util/time.cc \ src/cpp/util/time.cc \
src/cpp/codegen/grpc_library.cc \ src/cpp/codegen/codegen_init.cc \
PUBLIC_HEADERS_CXX += \ PUBLIC_HEADERS_CXX += \
include/grpc++/alarm.h \ include/grpc++/alarm.h \
@ -3328,6 +3500,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/codegen/completion_queue_tag.h \ include/grpc++/impl/codegen/completion_queue_tag.h \
include/grpc++/impl/codegen/config.h \ include/grpc++/impl/codegen/config.h \
include/grpc++/impl/codegen/config_protobuf.h \ include/grpc++/impl/codegen/config_protobuf.h \
include/grpc++/impl/codegen/core_codegen_interface.h \
include/grpc++/impl/codegen/grpc_library.h \ include/grpc++/impl/codegen/grpc_library.h \
include/grpc++/impl/codegen/method_handler_impl.h \ include/grpc++/impl/codegen/method_handler_impl.h \
include/grpc++/impl/codegen/proto_utils.h \ include/grpc++/impl/codegen/proto_utils.h \
@ -3403,45 +3576,8 @@ LIBGRPC_PLUGIN_SUPPORT_SRC = \
src/compiler/objective_c_generator.cc \ src/compiler/objective_c_generator.cc \
src/compiler/python_generator.cc \ src/compiler/python_generator.cc \
src/compiler/ruby_generator.cc \ src/compiler/ruby_generator.cc \
src/cpp/codegen/grpc_library.cc \
PUBLIC_HEADERS_CXX += \ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/codegen/async_stream.h \
include/grpc++/impl/codegen/async_unary_call.h \
include/grpc++/impl/codegen/call.h \
include/grpc++/impl/codegen/call_hook.h \
include/grpc++/impl/codegen/channel_interface.h \
include/grpc++/impl/codegen/client_context.h \
include/grpc++/impl/codegen/client_unary_call.h \
include/grpc++/impl/codegen/completion_queue.h \
include/grpc++/impl/codegen/completion_queue_tag.h \
include/grpc++/impl/codegen/config.h \
include/grpc++/impl/codegen/config_protobuf.h \
include/grpc++/impl/codegen/grpc_library.h \
include/grpc++/impl/codegen/method_handler_impl.h \
include/grpc++/impl/codegen/proto_utils.h \
include/grpc++/impl/codegen/rpc_method.h \
include/grpc++/impl/codegen/rpc_service_method.h \
include/grpc++/impl/codegen/security/auth_context.h \
include/grpc++/impl/codegen/serialization_traits.h \
include/grpc++/impl/codegen/server_context.h \
include/grpc++/impl/codegen/server_interface.h \
include/grpc++/impl/codegen/service_type.h \
include/grpc++/impl/codegen/status.h \
include/grpc++/impl/codegen/status_code_enum.h \
include/grpc++/impl/codegen/string_ref.h \
include/grpc++/impl/codegen/stub_options.h \
include/grpc++/impl/codegen/sync.h \
include/grpc++/impl/codegen/sync_cxx11.h \
include/grpc++/impl/codegen/sync_no_cxx11.h \
include/grpc++/impl/codegen/sync_stream.h \
include/grpc++/impl/codegen/time.h \
include/grpc/impl/codegen/byte_buffer.h \
include/grpc/impl/codegen/compression_types.h \
include/grpc/impl/codegen/connectivity_state.h \
include/grpc/impl/codegen/grpc_types.h \
include/grpc/impl/codegen/propagation_bits.h \
include/grpc/impl/codegen/status.h \
include/grpc/impl/codegen/alloc.h \ include/grpc/impl/codegen/alloc.h \
include/grpc/impl/codegen/atm.h \ include/grpc/impl/codegen/atm.h \
include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_atomic.h \
@ -5629,46 +5765,6 @@ ifneq ($(NO_DEPS),true)
endif endif
LIBEND2END_CERTS_SRC = \
test/core/end2end/data/test_root_cert.c \
test/core/end2end/data/server1_cert.c \
test/core/end2end/data/server1_key.c \
LIBEND2END_CERTS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBEND2END_CERTS_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libend2end_certs.a: openssl_dep_error
else
$(LIBDIR)/$(CONFIG)/libend2end_certs.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(LIBEND2END_CERTS_OBJS)
$(E) "[AR] Creating $@"
$(Q) mkdir -p `dirname $@`
$(Q) rm -f $(LIBDIR)/$(CONFIG)/libend2end_certs.a
$(Q) $(AR) $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBEND2END_CERTS_OBJS)
ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libend2end_certs.a
endif
endif
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(LIBEND2END_CERTS_OBJS:.o=.dep)
endif
endif
# All of the test targets, and protoc plugins # All of the test targets, and protoc plugins
@ -6057,6 +6153,70 @@ endif
endif endif
CONCURRENT_CONNECTIVITY_TEST_SRC = \
test/core/surface/concurrent_connectivity_test.c \
CONCURRENT_CONNECTIVITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CONCURRENT_CONNECTIVITY_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/concurrent_connectivity_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/concurrent_connectivity_test: $(CONCURRENT_CONNECTIVITY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(CONCURRENT_CONNECTIVITY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/concurrent_connectivity_test
endif
$(OBJDIR)/$(CONFIG)/test/core/surface/concurrent_connectivity_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_concurrent_connectivity_test: $(CONCURRENT_CONNECTIVITY_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(CONCURRENT_CONNECTIVITY_TEST_OBJS:.o=.dep)
endif
endif
DNS_RESOLVER_CONNECTIVITY_TEST_SRC = \
test/core/client_config/resolvers/dns_resolver_connectivity_test.c \
DNS_RESOLVER_CONNECTIVITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(DNS_RESOLVER_CONNECTIVITY_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test: $(DNS_RESOLVER_CONNECTIVITY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(DNS_RESOLVER_CONNECTIVITY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test
endif
$(OBJDIR)/$(CONFIG)/test/core/client_config/resolvers/dns_resolver_connectivity_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_dns_resolver_connectivity_test: $(DNS_RESOLVER_CONNECTIVITY_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(DNS_RESOLVER_CONNECTIVITY_TEST_OBJS:.o=.dep)
endif
endif
DNS_RESOLVER_TEST_SRC = \ DNS_RESOLVER_TEST_SRC = \
test/core/client_config/resolvers/dns_resolver_test.c \ test/core/client_config/resolvers/dns_resolver_test.c \
@ -9196,6 +9356,68 @@ endif
endif endif
CODEGEN_TEST_SRC = \
$(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc \
$(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \
$(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc \
$(GENDIR)/src/proto/grpc/testing/perf_db.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.grpc.pb.cc \
$(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc \
$(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc \
test/cpp/codegen/codegen_test.cc \
CODEGEN_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CODEGEN_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/codegen_test: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
$(BINDIR)/$(CONFIG)/codegen_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/codegen_test: $(PROTOBUF_DEP) $(CODEGEN_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(CODEGEN_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/codegen_test
endif
endif
$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/control.o: $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/messages.o: $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/payloads.o: $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/perf_db.o: $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/services.o: $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/stats.o: $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
$(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_codegen_lib.a
deps_codegen_test: $(CODEGEN_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(CODEGEN_TEST_OBJS:.o=.dep)
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test.o: $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc
CREDENTIALS_TEST_SRC = \ CREDENTIALS_TEST_SRC = \
test/cpp/client/credentials_test.cc \ test/cpp/client/credentials_test.cc \
@ -12199,14 +12421,14 @@ else
$(BINDIR)/$(CONFIG)/h2_census_test: $(H2_CENSUS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(BINDIR)/$(CONFIG)/h2_census_test: $(H2_CENSUS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(H2_CENSUS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_census_test $(Q) $(LD) $(LDFLAGS) $(H2_CENSUS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_census_test
endif endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_census.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_census.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_h2_census_test: $(H2_CENSUS_TEST_OBJS:.o=.dep) deps_h2_census_test: $(H2_CENSUS_TEST_OBJS:.o=.dep)
@ -12231,14 +12453,14 @@ else
$(BINDIR)/$(CONFIG)/h2_compress_test: $(H2_COMPRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(BINDIR)/$(CONFIG)/h2_compress_test: $(H2_COMPRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(H2_COMPRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_compress_test $(Q) $(LD) $(LDFLAGS) $(H2_COMPRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_compress_test
endif endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_compress.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_compress.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_h2_compress_test: $(H2_COMPRESS_TEST_OBJS:.o=.dep) deps_h2_compress_test: $(H2_COMPRESS_TEST_OBJS:.o=.dep)
@ -12263,14 +12485,14 @@ else
$(BINDIR)/$(CONFIG)/h2_fakesec_test: $(H2_FAKESEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(BINDIR)/$(CONFIG)/h2_fakesec_test: $(H2_FAKESEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(H2_FAKESEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_fakesec_test $(Q) $(LD) $(LDFLAGS) $(H2_FAKESEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_fakesec_test
endif endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_fakesec.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_fakesec.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_h2_fakesec_test: $(H2_FAKESEC_TEST_OBJS:.o=.dep) deps_h2_fakesec_test: $(H2_FAKESEC_TEST_OBJS:.o=.dep)
@ -12295,14 +12517,14 @@ else
$(BINDIR)/$(CONFIG)/h2_full_test: $(H2_FULL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(BINDIR)/$(CONFIG)/h2_full_test: $(H2_FULL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(H2_FULL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_full_test $(Q) $(LD) $(LDFLAGS) $(H2_FULL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_full_test
endif endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_full.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_full.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_h2_full_test: $(H2_FULL_TEST_OBJS:.o=.dep) deps_h2_full_test: $(H2_FULL_TEST_OBJS:.o=.dep)
@ -12327,14 +12549,14 @@ else
$(BINDIR)/$(CONFIG)/h2_full+pipe_test: $(H2_FULL+PIPE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(BINDIR)/$(CONFIG)/h2_full+pipe_test: $(H2_FULL+PIPE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(H2_FULL+PIPE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_full+pipe_test $(Q) $(LD) $(LDFLAGS) $(H2_FULL+PIPE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_full+pipe_test
endif endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_full+pipe.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_full+pipe.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_h2_full+pipe_test: $(H2_FULL+PIPE_TEST_OBJS:.o=.dep) deps_h2_full+pipe_test: $(H2_FULL+PIPE_TEST_OBJS:.o=.dep)
@ -12359,14 +12581,14 @@ else
$(BINDIR)/$(CONFIG)/h2_oauth2_test: $(H2_OAUTH2_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(BINDIR)/$(CONFIG)/h2_oauth2_test: $(H2_OAUTH2_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(H2_OAUTH2_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_oauth2_test $(Q) $(LD) $(LDFLAGS) $(H2_OAUTH2_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_oauth2_test
endif endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_oauth2.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_oauth2.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_h2_oauth2_test: $(H2_OAUTH2_TEST_OBJS:.o=.dep) deps_h2_oauth2_test: $(H2_OAUTH2_TEST_OBJS:.o=.dep)
@ -12391,14 +12613,14 @@ else
$(BINDIR)/$(CONFIG)/h2_proxy_test: $(H2_PROXY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(BINDIR)/$(CONFIG)/h2_proxy_test: $(H2_PROXY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(H2_PROXY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_proxy_test $(Q) $(LD) $(LDFLAGS) $(H2_PROXY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_proxy_test
endif endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_proxy.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_proxy.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_h2_proxy_test: $(H2_PROXY_TEST_OBJS:.o=.dep) deps_h2_proxy_test: $(H2_PROXY_TEST_OBJS:.o=.dep)
@ -12423,14 +12645,14 @@ else
$(BINDIR)/$(CONFIG)/h2_sockpair_test: $(H2_SOCKPAIR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(BINDIR)/$(CONFIG)/h2_sockpair_test: $(H2_SOCKPAIR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(H2_SOCKPAIR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_sockpair_test $(Q) $(LD) $(LDFLAGS) $(H2_SOCKPAIR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_sockpair_test
endif endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_sockpair.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_sockpair.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_h2_sockpair_test: $(H2_SOCKPAIR_TEST_OBJS:.o=.dep) deps_h2_sockpair_test: $(H2_SOCKPAIR_TEST_OBJS:.o=.dep)
@ -12455,14 +12677,14 @@ else
$(BINDIR)/$(CONFIG)/h2_sockpair+trace_test: $(H2_SOCKPAIR+TRACE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(BINDIR)/$(CONFIG)/h2_sockpair+trace_test: $(H2_SOCKPAIR+TRACE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(H2_SOCKPAIR+TRACE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_sockpair+trace_test $(Q) $(LD) $(LDFLAGS) $(H2_SOCKPAIR+TRACE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_sockpair+trace_test
endif endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_sockpair+trace.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_sockpair+trace.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_h2_sockpair+trace_test: $(H2_SOCKPAIR+TRACE_TEST_OBJS:.o=.dep) deps_h2_sockpair+trace_test: $(H2_SOCKPAIR+TRACE_TEST_OBJS:.o=.dep)
@ -12487,14 +12709,14 @@ else
$(BINDIR)/$(CONFIG)/h2_sockpair_1byte_test: $(H2_SOCKPAIR_1BYTE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_test: $(H2_SOCKPAIR_1BYTE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(H2_SOCKPAIR_1BYTE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_test $(Q) $(LD) $(LDFLAGS) $(H2_SOCKPAIR_1BYTE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_test
endif endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_sockpair_1byte.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_sockpair_1byte.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_h2_sockpair_1byte_test: $(H2_SOCKPAIR_1BYTE_TEST_OBJS:.o=.dep) deps_h2_sockpair_1byte_test: $(H2_SOCKPAIR_1BYTE_TEST_OBJS:.o=.dep)
@ -12519,14 +12741,14 @@ else
$(BINDIR)/$(CONFIG)/h2_ssl_test: $(H2_SSL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(BINDIR)/$(CONFIG)/h2_ssl_test: $(H2_SSL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(H2_SSL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_ssl_test $(Q) $(LD) $(LDFLAGS) $(H2_SSL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_ssl_test
endif endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_ssl.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_ssl.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_h2_ssl_test: $(H2_SSL_TEST_OBJS:.o=.dep) deps_h2_ssl_test: $(H2_SSL_TEST_OBJS:.o=.dep)
@ -12551,14 +12773,14 @@ else
$(BINDIR)/$(CONFIG)/h2_ssl_proxy_test: $(H2_SSL_PROXY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(BINDIR)/$(CONFIG)/h2_ssl_proxy_test: $(H2_SSL_PROXY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(H2_SSL_PROXY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_ssl_proxy_test $(Q) $(LD) $(LDFLAGS) $(H2_SSL_PROXY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_ssl_proxy_test
endif endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_ssl_proxy.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_ssl_proxy.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_h2_ssl_proxy_test: $(H2_SSL_PROXY_TEST_OBJS:.o=.dep) deps_h2_ssl_proxy_test: $(H2_SSL_PROXY_TEST_OBJS:.o=.dep)
@ -12583,14 +12805,14 @@ else
$(BINDIR)/$(CONFIG)/h2_uchannel_test: $(H2_UCHANNEL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(BINDIR)/$(CONFIG)/h2_uchannel_test: $(H2_UCHANNEL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(H2_UCHANNEL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_uchannel_test $(Q) $(LD) $(LDFLAGS) $(H2_UCHANNEL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_uchannel_test
endif endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_uchannel.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_uchannel.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_h2_uchannel_test: $(H2_UCHANNEL_TEST_OBJS:.o=.dep) deps_h2_uchannel_test: $(H2_UCHANNEL_TEST_OBJS:.o=.dep)
@ -12615,14 +12837,14 @@ else
$(BINDIR)/$(CONFIG)/h2_uds_test: $(H2_UDS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(BINDIR)/$(CONFIG)/h2_uds_test: $(H2_UDS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(H2_UDS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_uds_test $(Q) $(LD) $(LDFLAGS) $(H2_UDS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_uds_test
endif endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_uds.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_uds.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_h2_uds_test: $(H2_UDS_TEST_OBJS:.o=.dep) deps_h2_uds_test: $(H2_UDS_TEST_OBJS:.o=.dep)

@ -173,6 +173,7 @@ filegroups:
- include/grpc++/support/time.h - include/grpc++/support/time.h
headers: headers:
- src/cpp/client/create_channel_internal.h - src/cpp/client/create_channel_internal.h
- src/cpp/common/core_codegen.h
- src/cpp/common/create_auth_context.h - src/cpp/common/create_auth_context.h
- src/cpp/server/dynamic_thread_pool.h - src/cpp/server/dynamic_thread_pool.h
- src/cpp/server/thread_pool_interface.h - src/cpp/server/thread_pool_interface.h
@ -184,11 +185,10 @@ filegroups:
- src/cpp/client/credentials.cc - src/cpp/client/credentials.cc
- src/cpp/client/generic_stub.cc - src/cpp/client/generic_stub.cc
- src/cpp/client/insecure_credentials.cc - src/cpp/client/insecure_credentials.cc
- src/cpp/common/call.cc
- src/cpp/common/channel_arguments.cc - src/cpp/common/channel_arguments.cc
- src/cpp/common/completion_queue.cc - src/cpp/common/completion_queue.cc
- src/cpp/common/core_codegen.cc
- src/cpp/common/rpc_method.cc - src/cpp/common/rpc_method.cc
- src/cpp/proto/proto_utils.cc
- src/cpp/server/async_generic_service.cc - src/cpp/server/async_generic_service.cc
- src/cpp/server/create_default_thread_pool.cc - src/cpp/server/create_default_thread_pool.cc
- src/cpp/server/dynamic_thread_pool.cc - src/cpp/server/dynamic_thread_pool.cc
@ -215,6 +215,7 @@ filegroups:
- include/grpc++/impl/codegen/completion_queue_tag.h - include/grpc++/impl/codegen/completion_queue_tag.h
- include/grpc++/impl/codegen/config.h - include/grpc++/impl/codegen/config.h
- include/grpc++/impl/codegen/config_protobuf.h - include/grpc++/impl/codegen/config_protobuf.h
- include/grpc++/impl/codegen/core_codegen_interface.h
- include/grpc++/impl/codegen/grpc_library.h - include/grpc++/impl/codegen/grpc_library.h
- include/grpc++/impl/codegen/method_handler_impl.h - include/grpc++/impl/codegen/method_handler_impl.h
- include/grpc++/impl/codegen/proto_utils.h - include/grpc++/impl/codegen/proto_utils.h
@ -235,7 +236,7 @@ filegroups:
- include/grpc++/impl/codegen/sync_stream.h - include/grpc++/impl/codegen/sync_stream.h
- include/grpc++/impl/codegen/time.h - include/grpc++/impl/codegen/time.h
src: src:
- src/cpp/codegen/grpc_library.cc - src/cpp/codegen/codegen_init.cc
- name: grpc_base - name: grpc_base
public_headers: public_headers:
- include/grpc/byte_buffer.h - include/grpc/byte_buffer.h
@ -593,9 +594,9 @@ libs:
deps_linkage: static deps_linkage: static
dll: true dll: true
filegroups: filegroups:
- grpc_codegen
- grpc_base - grpc_base
- grpc_secure - grpc_secure
- grpc_codegen
- census - census
- nanopb - nanopb
secure: true secure: true
@ -603,6 +604,16 @@ libs:
- grpc.dependencies.openssl - grpc.dependencies.openssl
- grpc.dependencies.zlib - grpc.dependencies.zlib
vs_project_guid: '{29D16885-7228-4C31-81ED-5F9187C7F2A9}' vs_project_guid: '{29D16885-7228-4C31-81ED-5F9187C7F2A9}'
- name: grpc_codegen_lib
build: protoc
language: c
headers: []
src: []
filegroups:
- gpr_codegen
- grpc_codegen
secure: false
vs_project_guid: '{A828FD72-44CE-4EA5-8966-6E4624458D58}'
- name: grpc_dll - name: grpc_dll
build: private build: private
language: c language: c
@ -717,6 +728,7 @@ libs:
language: c++ language: c++
headers: headers:
- src/cpp/client/secure_credentials.h - src/cpp/client/secure_credentials.h
- src/cpp/common/core_codegen.h
- src/cpp/common/secure_auth_context.h - src/cpp/common/secure_auth_context.h
- src/cpp/server/secure_server_credentials.h - src/cpp/server/secure_server_credentials.h
src: src:
@ -735,6 +747,17 @@ libs:
- grpc++_codegen - grpc++_codegen
secure: check secure: check
vs_project_guid: '{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}' vs_project_guid: '{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}'
- name: grpc++_codegen_lib
build: protoc
language: c++
headers: []
src: []
filegroups:
- gpr_codegen
- grpc_codegen
- grpc++_codegen
secure: false
vs_project_guid: '{AAC6AF12-94C8-4A3C-A1BF-DAA4738F4500}'
- name: grpc++_test_config - name: grpc++_test_config
build: private build: private
language: c++ language: c++
@ -807,10 +830,9 @@ libs:
- src/compiler/objective_c_generator.cc - src/compiler/objective_c_generator.cc
- src/compiler/python_generator.cc - src/compiler/python_generator.cc
- src/compiler/ruby_generator.cc - src/compiler/ruby_generator.cc
deps: [] deps:
- grpc++_codegen_lib
filegroups: filegroups:
- grpc++_codegen
- grpc_codegen
- gpr_codegen - gpr_codegen
secure: false secure: false
vs_project_guid: '{B6E81D84-2ACB-41B8-8781-493A944C7817}' vs_project_guid: '{B6E81D84-2ACB-41B8-8781-493A944C7817}'
@ -1055,6 +1077,27 @@ targets:
- grpc - grpc
- gpr_test_util - gpr_test_util
- gpr - gpr
- name: concurrent_connectivity_test
build: test
language: c
src:
- test/core/surface/concurrent_connectivity_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
- name: dns_resolver_connectivity_test
cpu_cost: 0.1
build: test
language: c
src:
- test/core/client_config/resolvers/dns_resolver_connectivity_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
- name: dns_resolver_test - name: dns_resolver_test
build: test build: test
language: c language: c
@ -2077,6 +2120,20 @@ targets:
- grpc - grpc
- gpr_test_util - gpr_test_util
- gpr - gpr
- name: codegen_test
gtest: true
build: test
language: c++
src:
- src/proto/grpc/testing/control.proto
- src/proto/grpc/testing/messages.proto
- src/proto/grpc/testing/payloads.proto
- src/proto/grpc/testing/perf_db.proto
- src/proto/grpc/testing/services.proto
- src/proto/grpc/testing/stats.proto
- test/cpp/codegen/codegen_test.cc
deps:
- grpc++_codegen_lib
- name: credentials_test - name: credentials_test
gtest: true gtest: true
build: test build: test
@ -2722,6 +2779,36 @@ configs:
dbg: dbg:
CPPFLAGS: -O0 CPPFLAGS: -O0
DEFINES: _DEBUG DEBUG DEFINES: _DEBUG DEBUG
easan:
CC: clang
CPPFLAGS: -O0 -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument
-DGPR_NO_DIRECT_SYSCALLS
CXX: clang++
DEFINES: _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
LD: clang
LDFLAGS: -fsanitize=address
LDXX: clang++
compile_the_world: true
test_environ:
ASAN_OPTIONS: detect_leaks=1:color=always
LSAN_OPTIONS: suppressions=tools/lsan_suppressions.txt:report_objects=1
timeout_multiplier: 3
edbg:
CPPFLAGS: -O0
DEFINES: _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
etsan:
CC: clang
CPPFLAGS: -O0 -fsanitize=thread -fno-omit-frame-pointer -Wno-unused-command-line-argument
-fPIE -pie -DGPR_NO_DIRECT_SYSCALLS
CXX: clang++
DEFINES: _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
LD: clang
LDFLAGS: -fsanitize=thread -fPIE -pie $(if $(JENKINS_BUILD),-Wl$(comma)-Ttext-segment=0x7e0000000000,)
LDXX: clang++
compile_the_world: true
test_environ:
TSAN_OPTIONS: suppressions=tools/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1
timeout_multiplier: 5
gcov: gcov:
CC: gcc CC: gcc
CPPFLAGS: -O0 -fprofile-arcs -ftest-coverage -Wno-return-type CPPFLAGS: -O0 -fprofile-arcs -ftest-coverage -Wno-return-type

@ -2,13 +2,20 @@
"name": "grpc/grpc", "name": "grpc/grpc",
"type": "library", "type": "library",
"description": "gRPC library for PHP", "description": "gRPC library for PHP",
"version": "0.6.0", "version": "0.14.0",
"keywords": ["rpc"], "keywords": ["rpc"],
"homepage": "http://grpc.io", "homepage": "http://grpc.io",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"repositories": [
{
"type": "vcs",
"url": "https://github.com/stanley-cheung/Protobuf-PHP"
}
],
"require": { "require": {
"php": ">=5.5.0", "php": ">=5.5.0",
"google/auth": "dev-master" "datto/protobuf-php": "dev-master",
"google/auth": "v0.7"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

@ -1,450 +1,27 @@
# Examples
# Getting started This directory contains code examples for all the C-based gRPC implementations: C++, Node.js, Python, Ruby, Objective-C, PHP, and C#. You can find examples and instructions specific to your
favourite language in the relevant subdirectory.
Examples for Go and Java gRPC live in their own repositories:
Welcome to the developer documentation for gRPC, a language-neutral, * [Java](https://github.com/grpc/grpc-java/tree/master/examples)
platform-neutral remote procedure call (RPC) system developed at Google. * [Android Java](https://github.com/grpc/grpc-java/tree/master/examples/android)
* [Go](https://github.com/grpc/grpc-go/tree/master/examples)
This document introduces you to gRPC with a quick overview and a simple For more comprehensive documentation, including an [overview](http://www.grpc.io/docs/) and tutorials that use this example code, visit [grpc.io](http://www.grpc.io/docs/).
Hello World example. You'll find more tutorials and reference docs in this repository - more documentation is coming soon!
<a name="quickstart"></a>
## Quick start ## Quick start
You can find quick start guides for each language, including installation instructions, examples, and tutorials here:
Each example directory has quick start instructions for the appropriate language, including installation instructions and how to run our simplest Hello World example:
* [C++](cpp) * [C++](cpp)
* [Java](https://github.com/grpc/grpc-java/tree/master/examples)
* [Go](https://github.com/grpc/grpc-go/tree/master/examples)
* [Ruby](ruby) * [Ruby](ruby)
* [Node.js](node) * [Node.js](node)
* [Android Java](https://github.com/grpc/grpc-java/tree/master/examples/android)
* [Python](python/helloworld) * [Python](python/helloworld)
* [C#](csharp) * [C#](csharp)
* [Objective-C](objective-c/helloworld) * [Objective-C](objective-c/helloworld)
* [PHP](php) * [PHP](php)
## What's in this repository?
The `examples` directory contains documentation, resources, and examples
for all gRPC users. You can find examples and instructions specific to your
favourite language in the relevant subdirectory.
You can find out about the gRPC source code repositories in
[`grpc`](https://github.com/grpc/grpc). Each repository provides instructions
for building the appropriate libraries for your language.
## What is gRPC?
In gRPC a *client* application can directly call
methods on a *server* application on a different machine as if it was a
local object, making it easier for you to create distributed applications and
services. As in many RPC systems, gRPC is based around the idea of defining
a *service*, specifying the methods that can be called remotely with their
parameters and return types. On the server side, the server implements this
interface and runs a gRPC server to handle client calls. On the client side,
the client has a *stub* that provides exactly the same methods as the server.
<!--TODO: diagram-->
gRPC clients and servers can run and talk to each other in a variety of
environments - from servers inside Google to your own desktop - and can
be written in any of gRPC's [supported languages](#quickstart). So, for
example, you can easily create a gRPC server in Java with clients in Go,
Python, or Ruby. In addition, the latest Google APIs will have gRPC versions
of their interfaces, letting you easily build Google functionality into
your applications.
<a name="protocolbuffers"></a>
### Working with protocol buffers
By default gRPC uses *protocol buffers*, Google’s
mature open source mechanism for serializing structured data (although it
can be used with other data formats such as JSON). As you'll
see in our example below, you define gRPC services using *proto files*,
with method parameters and return types specified as protocol buffer message
types. You
can find out lots more about protocol buffers in the [Protocol Buffers
documentation](https://developers.google.com/protocol-buffers/docs/overview).
#### Protocol buffer versions
While protocol buffers have been available for open source users for some
time, our examples use a new flavour of protocol buffers called proto3,
which has a slightly simplified syntax, some useful new features, and supports
lots more languages. This is currently available as an alpha release in
Java, C++, Java_nano (Android Java), Python, and Ruby from [the protocol buffers Github
repo](https://github.com/google/protobuf/releases), as well as a Go language
generator from [the golang/protobuf Github repo](https://github.com/golang/protobuf), with more languages in development. You can find out more in the [proto3 language guide](https://developers.google.com/protocol-buffers/docs/proto3), and see
the major differences from the current default version in the [release notes](https://github.com/google/protobuf/releases). More proto3 documentation is coming soon.
In general, while you *can* use proto2 (the current default protocol buffers version), we recommend that you use proto3 with gRPC as it lets you use the full range of gRPC-supported languages, as well as avoiding compatibility
issues with proto2 clients talking to proto3 servers and vice versa.
<a name="hello"></a>
## Hello gRPC!
Now that you know a bit more about gRPC, the easiest way to see how it
works is to look at a simple example. Our Hello World walks you through the
construction of a simple gRPC client-server application, showing you how to:
- Create a protocol buffers schema that defines a simple RPC service with
a single
Hello World method.
- Create a Java server that implements this interface.
- Create a Java client that accesses the Java server.
- Create a Go client that accesses
the same Java server.
The complete code for the example is available in the `examples`
directory. We use the Git versioning system for source code management:
however, you don't need to know anything about Git to follow along other
than how to install and run a few git commands.
This is an introductory example rather than a comprehensive tutorial, so
don't worry if you're not a Go or
Java developer - the concepts are similar for all languages, and you can
find more implementations of our Hello World example in other languages (and full tutorials where available) in
the [language-specific folders](#quickstart) in this repository. Complete tutorials and
reference documentation for all gRPC languages are coming soon.
<a name="setup"></a>
### Setup
This section explains how to set up your local machine to work with
the example code. If you just want to read the example, you can go straight
to the [next step](#servicedef).
#### Install Git
You can download and install Git from http://git-scm.com/download. Once
installed you should have access to the git command line tool. The main
commands that you will need to use are:
- git clone ... : clone a remote repository onto your local machine
- git checkout ... : check out a particular branch or a tagged version of
the code to hack on
#### Install gRPC
To build and install gRPC plugins and related tools:
- For Java, see the [Java quick start](https://github.com/grpc/grpc-java).
- For Go, see the [Go quick start](https://github.com/grpc/grpc-go).
#### Get the source code
The example code for our Java example lives in the `grpc-java`
GitHub repository. Clone this repository to your local machine by running the
following command:
```
git clone https://github.com/grpc/grpc-java.git
```
Change your current directory to grpc-java/examples
```
cd grpc-java/examples
```
<a name="servicedef"></a>
### Defining a service
The first step in creating our example is to define a *service*: an RPC
service specifies the methods that can be called remotely with their parameters
and return types. As you saw in the
[overview](#protocolbuffers) above, gRPC does this using [protocol
buffers](https://developers.google.com/protocol-buffers/docs/overview). We
use the protocol buffers interface definition language (IDL) to define our
service methods, and define the parameters and return
types as protocol buffer message types. Both the client and the
server use interface code generated from the service definition.
Here's our example service definition, defined using protocol buffers IDL in
[helloworld.proto](https://github.com/grpc/grpc-java/tree/master/examples/src/main/proto). The `Greeter`
service has one method, `SayHello`, that lets the server receive a single
`HelloRequest`
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 - you can find out about other types in the tutorial for your chosen language.
```proto
syntax = "proto3";
option java_package = "io.grpc.examples";
package helloworld;
// The greeter service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
```
<a name="generating"></a>
### Generating gRPC code
Once we've defined our service, we use the protocol buffer compiler
`protoc` to generate the special client and server code we need to create
our application - right now we're going to generate Java code, though you
can generate gRPC code in any gRPC-supported language (as you'll see later
in this example). The generated code contains both stub code for clients to
use and an abstract interface for servers to implement, both with the method
defined in our `Greeter` service.
(If you didn't install the gRPC plugins and protoc on your system and are just reading along with
the example, you can skip this step and move
onto the next one where we examine the generated code.)
For simplicity, we've provided a [Gradle build file](https://github.com/grpc/grpc-java/blob/master/examples/build.gradle) with our Java examples that runs `protoc` for you with the appropriate plugin, input, and output:
```shell
../gradlew build
```
This generates the following classes from our .proto, which contain all the generated code
we need to create our example:
- `Helloworld.java`, which
has all the protocol buffer code to populate, serialize, and retrieve our
`HelloRequest` and `HelloReply` message types
- `GreeterGrpc.java`, which contains (along with some other useful code):
- an interface for `Greeter` servers to implement
```java
public static interface Greeter {
public void sayHello(io.grpc.examples.Helloworld.HelloRequest request,
io.grpc.stub.StreamObserver<io.grpc.examples.Helloworld.HelloReply> responseObserver);
}
```
- _stub_ classes that clients can use to talk to a `Greeter` server. As you can see, they also implement the `Greeter` interface.
```java
public static class GreeterStub extends
io.grpc.stub.AbstractStub<GreeterStub, GreeterServiceDescriptor>
implements Greeter {
...
}
```
<a name="server"></a>
### Writing a server
Now let's write some code! First we'll create a server application to implement
our service. Note that we're not going to go into a lot of detail about how
to create a server in this section. More detailed information will be in the
tutorial for your chosen language: check if there's one available yet in the relevant [quick start](#quickstart).
Our server application has two classes:
- a main server class that hosts the service implementation and allows access over the
network: [HelloWorldServer.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java).
- a simple service implementation class [GreeterImpl.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java#L51).
#### Service implementation
[GreeterImpl.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java#L51)
actually implements our `Greeter` service's required behaviour.
As you can see, the class `GreeterImpl` implements the interface
`GreeterGrpc.Greeter` that we [generated](#generating) from our proto
[IDL](https://github.com/grpc/grpc-java/tree/master/examples/src/main/proto) by implementing the method `sayHello`:
```java
@Override
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
responseObserver.onValue(reply);
responseObserver.onCompleted();
}
```
- `sayHello` takes two parameters:
- `HelloRequest`: the request
- `StreamObserver<HelloReply>`: a response observer, which is
a special interface for the server to call with its response
To return our response to the client and complete the call:
1. We construct and populate a `HelloReply` response object with our exciting
message, as specified in our interface definition.
2. We return the `HelloReply` to the client and then specify that we've finished dealing with the RPC.
#### Server implementation
[HelloWorldServer.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java)
shows the other main feature required to provide a gRPC service; making the service
implementation available from the network.
```java
/* The port on which the server should run */
private int port = 50051;
private ServerImpl server;
private void start() throws Exception {
server = NettyServerBuilder.forPort(port)
.addService(GreeterGrpc.bindService(new GreeterImpl()))
.build().start();
logger.info("Server started, listening on " + port);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
System.err.println("*** shutting down gRPC server since JVM is shutting down");
HelloWorldServer.this.stop();
System.err.println("*** server shut down");
}
});
}
```
Here we create an appropriate gRPC server, binding the `Greeter` service
implementation that we created to a port. Then we start the server running: the server is now ready to receive
requests from `Greeter` service clients on our specified port. We'll cover
how all this works in a bit more detail in our language-specific documentation.
<a name="client"></a>
### Writing a client
Client-side gRPC is pretty simple. In this step, we'll use the generated code
to write a simple client that can access the `Greeter` server we created
in the [previous section](#server). You can see the complete client code in
[HelloWorldClient.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java).
Again, we're not going to go into much detail about how to implement a client;
we'll leave that for the tutorial.
#### Connecting to the service
First let's look at how we connect to the `Greeter` server. First we need
to create a gRPC channel, specifying the hostname and port of the server we
want to connect to. Then we use the channel to construct the stub instance.
```java
private final ChannelImpl channel;
private final GreeterGrpc.GreeterBlockingStub blockingStub;
public HelloWorldClient(String host, int port) {
channel =
NettyChannelBuilder.forAddress(host, port).negotiationType(NegotiationType.PLAINTEXT)
.build();
blockingStub = GreeterGrpc.newBlockingStub(channel);
}
```
In this case, we create a blocking stub. This means that the RPC call waits
for the server to respond, and will either return a response or raise an
exception. gRPC Java has other kinds of stubs that make non-blocking calls
to the server, where the response is returned asynchronously.
#### Calling an RPC
Now we can contact the service and obtain a greeting:
1. We construct and fill in a `HelloRequest` to send to the service.
2. We call the stub's `hello()` RPC with our request and get a `HelloReply`
back, from which we can get our greeting.
```java
HelloRequest req = HelloRequest.newBuilder().setName(name).build();
HelloReply reply = blockingStub.sayHello(req);
```
<a name="run"></a>
### Try it out!
Our [Gradle build file](https://github.com/grpc/grpc-java/blob/master/examples/build.gradle) simplifies building and running the examples.
You can build and run the server from the `grpc-java` root folder with:
```sh
$ ./gradlew :grpc-examples:helloWorldServer
```
and in another terminal window confirm that it receives a message.
```sh
$ ./gradlew :grpc-examples:helloWorldClient
```
### Adding another client
Finally, let's look at one of gRPC's most useful features - interoperability
between code in different languages. So far, we've just looked at Java code
generated from and implementing our `Greeter` service definition. However,
as you'll see if you look at the language-specific subdirectories
in this repository, we've also generated and implemented `Greeter`
in some of gRPC's other supported languages. Each service
and client uses interface code generated from the same proto
that we used for the Java example.
So, for example, if we visit the [`go` example
directory](https://github.com/grpc/grpc-go/tree/master/examples) and look at the
[`greeter_client`](https://github.com/grpc/grpc-go/blob/master/examples/greeter_client/main.go),
we can see that like the Java client, it connects to a `Greeter` service
at `localhost:50051` and uses a stub to call the `SayHello` method with a
`HelloRequest`:
```go
const (
address = "localhost:50051"
defaultName = "world"
)
func main() {
// Set up a connection to the server.
conn, err := grpc.Dial(address)
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
// Contact the server and print out its response.
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name:
name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.Message)
}
```
If we run the Java server from earlier in another terminal window, we can
run the Go client and connect to it just like the Java client, even though
it's written in a different language.
```
$ greeter_client
```
## Read more!
- You can find links to language-specific tutorials, examples, and other docs in each language's [quick start](#quickstart).
- [gRPC Authentication Support](http://www.grpc.io/docs/guides/auth.html) introduces authentication support in gRPC with supported mechanisms and examples.

@ -2,7 +2,7 @@
## Installation ## Installation
To install gRPC on your system, follow the instructions [here](../../INSTALL.md). To install gRPC on your system, follow the instructions to build from source [here](../../INSTALL.md). This also installs the protocol buffer compiler `protoc` (if you don't have it already), and the C++ gRPC plugin for `protoc`.
## Hello C++ gRPC! ## Hello C++ gRPC!

@ -4,16 +4,15 @@ gRPC in 3 minutes (PHP)
PREREQUISITES PREREQUISITES
------------- -------------
This requires PHP 5.5 or greater. This requires `php` >=5.5, `phpize`, `pecl`, `phpunit`
INSTALL INSTALL
------- -------
- On Mac OS X, install [homebrew][]. Run the following command to install gRPC. - Install the gRPC PHP extension
```sh ```sh
$ curl -fsSL https://goo.gl/getgrpc | bash -s php $ [sudo] pecl install grpc-beta
``` ```
This will download and run the [gRPC install script][] and compile the gRPC PHP extension.
- Clone this repository - Clone this repository
@ -37,6 +36,7 @@ TRY IT!
Please follow the instruction in [Node][] to run the server Please follow the instruction in [Node][] to run the server
``` ```
$ cd examples/node $ cd examples/node
$ npm install
$ nodejs greeter_server.js $ nodejs greeter_server.js
``` ```
@ -58,7 +58,5 @@ TUTORIAL
You can find a more detailed tutorial in [gRPC Basics: PHP][] You can find a more detailed tutorial in [gRPC Basics: PHP][]
[homebrew]:http://brew.sh
[gRPC install script]:https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install
[Node]:https://github.com/grpc/grpc/tree/master/examples/node [Node]:https://github.com/grpc/grpc/tree/master/examples/node
[gRPC Basics: PHP]:http://www.grpc.io/docs/tutorials/basic/php.html [gRPC Basics: PHP]:http://www.grpc.io/docs/tutorials/basic/php.html

@ -1,17 +1,14 @@
{ {
"name": "grpc/grpc-demo",
"description": "gRPC example for PHP",
"minimum-stability": "dev",
"repositories": [ "repositories": [
{ {
"type": "vcs", "type": "vcs",
"url": "https://github.com/stanley-cheung/Protobuf-PHP" "url": "https://github.com/stanley-cheung/Protobuf-PHP"
} }
], ],
"name": "grpc/grpc-demo",
"description": "gRPC example for PHP",
"minimum-stability": "dev",
"require": { "require": {
"php": ">=5.5.0", "grpc/grpc": "dev-release-0_13"
"datto/protobuf-php": "dev-master",
"google/auth": "dev-master",
"grpc/grpc": "dev-release-0_11"
} }
} }

@ -1,7 +1,7 @@
<?php <?php
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2015-2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -36,7 +36,9 @@ require dirname(__FILE__) . '/vendor/autoload.php';
require dirname(__FILE__) . '/helloworld.php'; require dirname(__FILE__) . '/helloworld.php';
function greet($name) { function greet($name) {
$client = new helloworld\GreeterClient('localhost:50051', []); $client = new helloworld\GreeterClient('localhost:50051', [
'credentials' => Grpc\ChannelCredentials::createInsecure()
]);
$request = new helloworld\HelloRequest(); $request = new helloworld\HelloRequest();
$request->setName($name); $request->setName($name);
list($reply, $status) = $client->SayHello($request)->wait(); list($reply, $status) = $client->SayHello($request)->wait();

@ -1,7 +1,7 @@
<?php <?php
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2015-2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -37,7 +37,9 @@ require dirname(__FILE__) . '/route_guide.php';
define('COORD_FACTOR', 1e7); define('COORD_FACTOR', 1e7);
$client = new routeguide\RouteGuideClient('localhost:50051', []); $client = new routeguide\RouteGuideClient('localhost:50051', [
'credentials' => Grpc\ChannelCredentials::createInsecure()
]);
function printFeature($feature) { function printFeature($feature) {
$name = $feature->getName(); $name = $feature->getName();

@ -1,4 +1,4 @@
# Copyright 2015, Google Inc. # Copyright 2015-2016, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without

@ -296,17 +296,17 @@ Pod::Spec.new do |s|
'third_party/nanopb/pb_decode.h', 'third_party/nanopb/pb_decode.h',
'third_party/nanopb/pb_encode.h', 'third_party/nanopb/pb_encode.h',
'include/grpc/grpc_security.h', 'include/grpc/grpc_security.h',
'include/grpc/byte_buffer.h',
'include/grpc/byte_buffer_reader.h',
'include/grpc/compression.h',
'include/grpc/grpc.h',
'include/grpc/status.h',
'include/grpc/impl/codegen/byte_buffer.h', 'include/grpc/impl/codegen/byte_buffer.h',
'include/grpc/impl/codegen/compression_types.h', 'include/grpc/impl/codegen/compression_types.h',
'include/grpc/impl/codegen/connectivity_state.h', 'include/grpc/impl/codegen/connectivity_state.h',
'include/grpc/impl/codegen/grpc_types.h', 'include/grpc/impl/codegen/grpc_types.h',
'include/grpc/impl/codegen/propagation_bits.h', 'include/grpc/impl/codegen/propagation_bits.h',
'include/grpc/impl/codegen/status.h', 'include/grpc/impl/codegen/status.h',
'include/grpc/byte_buffer.h',
'include/grpc/byte_buffer_reader.h',
'include/grpc/compression.h',
'include/grpc/grpc.h',
'include/grpc/status.h',
'include/grpc/census.h', 'include/grpc/census.h',
'src/core/census/grpc_context.c', 'src/core/census/grpc_context.c',
'src/core/census/grpc_filter.c', 'src/core/census/grpc_filter.c',

@ -143,17 +143,17 @@ Gem::Specification.new do |s|
s.files += %w( src/core/support/tmpfile_win32.c ) s.files += %w( src/core/support/tmpfile_win32.c )
s.files += %w( src/core/support/wrap_memcpy.c ) s.files += %w( src/core/support/wrap_memcpy.c )
s.files += %w( include/grpc/grpc_security.h ) s.files += %w( include/grpc/grpc_security.h )
s.files += %w( include/grpc/byte_buffer.h )
s.files += %w( include/grpc/byte_buffer_reader.h )
s.files += %w( include/grpc/compression.h )
s.files += %w( include/grpc/grpc.h )
s.files += %w( include/grpc/status.h )
s.files += %w( include/grpc/impl/codegen/byte_buffer.h ) s.files += %w( include/grpc/impl/codegen/byte_buffer.h )
s.files += %w( include/grpc/impl/codegen/compression_types.h ) s.files += %w( include/grpc/impl/codegen/compression_types.h )
s.files += %w( include/grpc/impl/codegen/connectivity_state.h ) s.files += %w( include/grpc/impl/codegen/connectivity_state.h )
s.files += %w( include/grpc/impl/codegen/grpc_types.h ) s.files += %w( include/grpc/impl/codegen/grpc_types.h )
s.files += %w( include/grpc/impl/codegen/propagation_bits.h ) s.files += %w( include/grpc/impl/codegen/propagation_bits.h )
s.files += %w( include/grpc/impl/codegen/status.h ) s.files += %w( include/grpc/impl/codegen/status.h )
s.files += %w( include/grpc/byte_buffer.h )
s.files += %w( include/grpc/byte_buffer_reader.h )
s.files += %w( include/grpc/compression.h )
s.files += %w( include/grpc/grpc.h )
s.files += %w( include/grpc/status.h )
s.files += %w( include/grpc/census.h ) s.files += %w( include/grpc/census.h )
s.files += %w( src/core/census/grpc_filter.h ) s.files += %w( src/core/census/grpc_filter.h )
s.files += %w( src/core/channel/channel_args.h ) s.files += %w( src/core/channel/channel_args.h )

@ -50,7 +50,7 @@ namespace grpc {
class CompletionQueue; class CompletionQueue;
/// A thin wrapper around \a grpc_alarm (see / \a / src/core/surface/alarm.h). /// A thin wrapper around \a grpc_alarm (see / \a / src/core/surface/alarm.h).
class Alarm : private GrpcLibrary { class Alarm : private GrpcLibraryCodegen {
public: public:
/// Create a completion queue alarm instance associated to \a cq. /// Create a completion queue alarm instance associated to \a cq.
/// ///

@ -49,7 +49,7 @@ namespace grpc {
class Channel GRPC_FINAL : public ChannelInterface, class Channel GRPC_FINAL : public ChannelInterface,
public CallHook, public CallHook,
public std::enable_shared_from_this<Channel>, public std::enable_shared_from_this<Channel>,
private GrpcLibrary { private GrpcLibraryCodegen {
public: public:
~Channel(); ~Channel();

@ -34,10 +34,11 @@
#ifndef GRPCXX_IMPL_CODEGEN_ASYNC_STREAM_H #ifndef GRPCXX_IMPL_CODEGEN_ASYNC_STREAM_H
#define GRPCXX_IMPL_CODEGEN_ASYNC_STREAM_H #define GRPCXX_IMPL_CODEGEN_ASYNC_STREAM_H
#include <grpc++/impl/codegen/channel_interface.h>
#include <grpc++/impl/codegen/call.h> #include <grpc++/impl/codegen/call.h>
#include <grpc++/impl/codegen/service_type.h> #include <grpc++/impl/codegen/channel_interface.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/server_context.h> #include <grpc++/impl/codegen/server_context.h>
#include <grpc++/impl/codegen/service_type.h>
#include <grpc++/impl/codegen/status.h> #include <grpc++/impl/codegen/status.h>
namespace grpc { namespace grpc {
@ -109,13 +110,13 @@ class ClientAsyncReader GRPC_FINAL : public ClientAsyncReaderInterface<R> {
init_ops_.set_output_tag(tag); init_ops_.set_output_tag(tag);
init_ops_.SendInitialMetadata(context->send_initial_metadata_); init_ops_.SendInitialMetadata(context->send_initial_metadata_);
// TODO(ctiller): don't assert // TODO(ctiller): don't assert
GPR_ASSERT(init_ops_.SendMessage(request).ok()); GPR_CODEGEN_ASSERT(init_ops_.SendMessage(request).ok());
init_ops_.ClientSendClose(); init_ops_.ClientSendClose();
call_.PerformOps(&init_ops_); call_.PerformOps(&init_ops_);
} }
void ReadInitialMetadata(void* tag) GRPC_OVERRIDE { void ReadInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_ASSERT(!context_->initial_metadata_received_); GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag); meta_ops_.set_output_tag(tag);
meta_ops_.RecvInitialMetadata(context_); meta_ops_.RecvInitialMetadata(context_);
@ -177,7 +178,7 @@ class ClientAsyncWriter GRPC_FINAL : public ClientAsyncWriterInterface<W> {
} }
void ReadInitialMetadata(void* tag) GRPC_OVERRIDE { void ReadInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_ASSERT(!context_->initial_metadata_received_); GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag); meta_ops_.set_output_tag(tag);
meta_ops_.RecvInitialMetadata(context_); meta_ops_.RecvInitialMetadata(context_);
@ -187,7 +188,7 @@ class ClientAsyncWriter GRPC_FINAL : public ClientAsyncWriterInterface<W> {
void Write(const W& msg, void* tag) GRPC_OVERRIDE { void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag); write_ops_.set_output_tag(tag);
// TODO(ctiller): don't assert // TODO(ctiller): don't assert
GPR_ASSERT(write_ops_.SendMessage(msg).ok()); GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_); call_.PerformOps(&write_ops_);
} }
@ -243,7 +244,7 @@ class ClientAsyncReaderWriter GRPC_FINAL
} }
void ReadInitialMetadata(void* tag) GRPC_OVERRIDE { void ReadInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_ASSERT(!context_->initial_metadata_received_); GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag); meta_ops_.set_output_tag(tag);
meta_ops_.RecvInitialMetadata(context_); meta_ops_.RecvInitialMetadata(context_);
@ -262,7 +263,7 @@ class ClientAsyncReaderWriter GRPC_FINAL
void Write(const W& msg, void* tag) GRPC_OVERRIDE { void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag); write_ops_.set_output_tag(tag);
// TODO(ctiller): don't assert // TODO(ctiller): don't assert
GPR_ASSERT(write_ops_.SendMessage(msg).ok()); GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_); call_.PerformOps(&write_ops_);
} }
@ -300,7 +301,7 @@ class ServerAsyncReader GRPC_FINAL : public ServerAsyncStreamingInterface,
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {} : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) GRPC_OVERRIDE { void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_ASSERT(!ctx_->sent_initial_metadata_); GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag); meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_); meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
@ -331,7 +332,7 @@ class ServerAsyncReader GRPC_FINAL : public ServerAsyncStreamingInterface,
} }
void FinishWithError(const Status& status, void* tag) { void FinishWithError(const Status& status, void* tag) {
GPR_ASSERT(!status.ok()); GPR_CODEGEN_ASSERT(!status.ok());
finish_ops_.set_output_tag(tag); finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) { if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_); finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
@ -360,7 +361,7 @@ class ServerAsyncWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {} : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) GRPC_OVERRIDE { void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_ASSERT(!ctx_->sent_initial_metadata_); GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag); meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_); meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
@ -375,7 +376,7 @@ class ServerAsyncWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
ctx_->sent_initial_metadata_ = true; ctx_->sent_initial_metadata_ = true;
} }
// TODO(ctiller): don't assert // TODO(ctiller): don't assert
GPR_ASSERT(write_ops_.SendMessage(msg).ok()); GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_); call_.PerformOps(&write_ops_);
} }
@ -409,7 +410,7 @@ class ServerAsyncReaderWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {} : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) GRPC_OVERRIDE { void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_ASSERT(!ctx_->sent_initial_metadata_); GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag); meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_); meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
@ -430,7 +431,7 @@ class ServerAsyncReaderWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
ctx_->sent_initial_metadata_ = true; ctx_->sent_initial_metadata_ = true;
} }
// TODO(ctiller): don't assert // TODO(ctiller): don't assert
GPR_ASSERT(write_ops_.SendMessage(msg).ok()); GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_); call_.PerformOps(&write_ops_);
} }

@ -45,6 +45,7 @@
namespace grpc { namespace grpc {
class CompletionQueue; class CompletionQueue;
extern CoreCodegenInterface* g_core_codegen_interface;
template <class R> template <class R>
class ClientAsyncResponseReaderInterface { class ClientAsyncResponseReaderInterface {
@ -68,13 +69,13 @@ class ClientAsyncResponseReader GRPC_FINAL
collection_->init_buf_.SetCollection(collection_); collection_->init_buf_.SetCollection(collection_);
collection_->init_buf_.SendInitialMetadata(context->send_initial_metadata_); collection_->init_buf_.SendInitialMetadata(context->send_initial_metadata_);
// TODO(ctiller): don't assert // TODO(ctiller): don't assert
GPR_ASSERT(collection_->init_buf_.SendMessage(request).ok()); GPR_CODEGEN_ASSERT(collection_->init_buf_.SendMessage(request).ok());
collection_->init_buf_.ClientSendClose(); collection_->init_buf_.ClientSendClose();
call_.PerformOps(&collection_->init_buf_); call_.PerformOps(&collection_->init_buf_);
} }
void ReadInitialMetadata(void* tag) { void ReadInitialMetadata(void* tag) {
GPR_ASSERT(!context_->initial_metadata_received_); GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
collection_->meta_buf_.SetCollection(collection_); collection_->meta_buf_.SetCollection(collection_);
collection_->meta_buf_.set_output_tag(tag); collection_->meta_buf_.set_output_tag(tag);
@ -116,7 +117,7 @@ class ServerAsyncResponseWriter GRPC_FINAL
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {} : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) GRPC_OVERRIDE { void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_ASSERT(!ctx_->sent_initial_metadata_); GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_buf_.set_output_tag(tag); meta_buf_.set_output_tag(tag);
meta_buf_.SendInitialMetadata(ctx_->initial_metadata_); meta_buf_.SendInitialMetadata(ctx_->initial_metadata_);
@ -141,7 +142,7 @@ class ServerAsyncResponseWriter GRPC_FINAL
} }
void FinishWithError(const Status& status, void* tag) { void FinishWithError(const Status& status, void* tag) {
GPR_ASSERT(!status.ok()); GPR_CODEGEN_ASSERT(!status.ok());
finish_buf_.set_output_tag(tag); finish_buf_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) { if (!ctx_->sent_initial_metadata_) {
finish_buf_.SendInitialMetadata(ctx_->initial_metadata_); finish_buf_.SendInitialMetadata(ctx_->initial_metadata_);

@ -34,19 +34,21 @@
#ifndef GRPCXX_IMPL_CODEGEN_CALL_H #ifndef GRPCXX_IMPL_CODEGEN_CALL_H
#define GRPCXX_IMPL_CODEGEN_CALL_H #define GRPCXX_IMPL_CODEGEN_CALL_H
#include <cstring>
#include <functional> #include <functional>
#include <memory>
#include <map> #include <map>
#include <cstring> #include <memory>
#include <grpc/impl/codegen/alloc.h>
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc++/impl/codegen/client_context.h>
#include <grpc++/impl/codegen/call_hook.h> #include <grpc++/impl/codegen/call_hook.h>
#include <grpc++/impl/codegen/client_context.h>
#include <grpc++/impl/codegen/completion_queue_tag.h> #include <grpc++/impl/codegen/completion_queue_tag.h>
#include <grpc++/impl/codegen/serialization_traits.h>
#include <grpc++/impl/codegen/config.h> #include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/serialization_traits.h>
#include <grpc++/impl/codegen/status.h> #include <grpc++/impl/codegen/status.h>
#include <grpc++/impl/codegen/string_ref.h>
#include <grpc/impl/codegen/alloc.h>
#include <grpc/impl/codegen/grpc_types.h>
struct grpc_byte_buffer; struct grpc_byte_buffer;
@ -56,12 +58,39 @@ class ByteBuffer;
class Call; class Call;
class CallHook; class CallHook;
class CompletionQueue; class CompletionQueue;
extern CoreCodegenInterface* g_core_codegen_interface;
void FillMetadataMap( inline void FillMetadataMap(
grpc_metadata_array* arr, grpc_metadata_array* arr,
std::multimap<grpc::string_ref, grpc::string_ref>* metadata); std::multimap<grpc::string_ref, grpc::string_ref>* metadata) {
grpc_metadata* FillMetadataArray( for (size_t i = 0; i < arr->count; i++) {
const std::multimap<grpc::string, grpc::string>& metadata); // TODO(yangg) handle duplicates?
metadata->insert(std::pair<grpc::string_ref, grpc::string_ref>(
arr->metadata[i].key, grpc::string_ref(arr->metadata[i].value,
arr->metadata[i].value_length)));
}
g_core_codegen_interface->grpc_metadata_array_destroy(arr);
g_core_codegen_interface->grpc_metadata_array_init(arr);
}
// TODO(yangg) if the map is changed before we send, the pointers will be a
// mess. Make sure it does not happen.
inline grpc_metadata* FillMetadataArray(
const std::multimap<grpc::string, grpc::string>& metadata) {
if (metadata.empty()) {
return nullptr;
}
grpc_metadata* metadata_array =
(grpc_metadata*)(g_core_codegen_interface->gpr_malloc(
metadata.size() * sizeof(grpc_metadata)));
size_t i = 0;
for (auto iter = metadata.cbegin(); iter != metadata.cend(); ++iter, ++i) {
metadata_array[i].key = iter->first.c_str();
metadata_array[i].value = iter->second.c_str();
metadata_array[i].value_length = iter->second.size();
}
return metadata_array;
}
/// Per-message write options. /// Per-message write options.
class WriteOptions { class WriteOptions {
@ -170,7 +199,7 @@ class CallOpSendInitialMetadata {
} }
void FinishOp(bool* status, int max_message_size) { void FinishOp(bool* status, int max_message_size) {
if (!send_) return; if (!send_) return;
gpr_free(initial_metadata_); g_core_codegen_interface->gpr_free(initial_metadata_);
send_ = false; send_ = false;
} }
@ -204,7 +233,7 @@ class CallOpSendMessage {
write_options_.Clear(); write_options_.Clear();
} }
void FinishOp(bool* status, int max_message_size) { void FinishOp(bool* status, int max_message_size) {
if (own_buf_) grpc_byte_buffer_destroy(send_buf_); if (own_buf_) g_core_codegen_interface->grpc_byte_buffer_destroy(send_buf_);
send_buf_ = nullptr; send_buf_ = nullptr;
} }
@ -254,7 +283,7 @@ class CallOpRecvMessage {
max_message_size).ok(); max_message_size).ok();
} else { } else {
got_message = false; got_message = false;
grpc_byte_buffer_destroy(recv_buf_); g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);
} }
} else { } else {
got_message = false; got_message = false;
@ -321,7 +350,7 @@ class CallOpGenericRecvMessage {
*status = deserialize_->Deserialize(recv_buf_, max_message_size).ok(); *status = deserialize_->Deserialize(recv_buf_, max_message_size).ok();
} else { } else {
got_message = false; got_message = false;
grpc_byte_buffer_destroy(recv_buf_); g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);
} }
} else { } else {
got_message = false; got_message = false;
@ -386,7 +415,7 @@ class CallOpServerSendStatus {
void FinishOp(bool* status, int max_message_size) { void FinishOp(bool* status, int max_message_size) {
if (!send_status_available_) return; if (!send_status_available_) return;
gpr_free(trailing_metadata_); g_core_codegen_interface->gpr_free(trailing_metadata_);
send_status_available_ = false; send_status_available_ = false;
} }
@ -462,7 +491,7 @@ class CallOpClientRecvStatus {
*recv_status_ = Status( *recv_status_ = Status(
static_cast<StatusCode>(status_code_), static_cast<StatusCode>(status_code_),
status_details_ ? grpc::string(status_details_) : grpc::string()); status_details_ ? grpc::string(status_details_) : grpc::string());
gpr_free(status_details_); g_core_codegen_interface->gpr_free(status_details_);
recv_status_ = nullptr; recv_status_ = nullptr;
} }
@ -576,11 +605,22 @@ class SneakyCallOpSet : public CallOpSet<Op1, Op2, Op3, Op4, Op5, Op6> {
class Call GRPC_FINAL { class Call GRPC_FINAL {
public: public:
/* call is owned by the caller */ /* call is owned by the caller */
Call(grpc_call* call, CallHook* call_hook_, CompletionQueue* cq); Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq)
Call(grpc_call* call, CallHook* call_hook_, CompletionQueue* cq, : call_hook_(call_hook), cq_(cq), call_(call), max_message_size_(-1) {}
int max_message_size);
Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq,
int max_message_size)
: call_hook_(call_hook),
cq_(cq),
call_(call),
max_message_size_(max_message_size) {}
void PerformOps(CallOpSetInterface* ops); void PerformOps(CallOpSetInterface* ops) {
if (max_message_size_ > 0) {
ops->set_max_message_size(max_message_size_);
}
call_hook_->PerformOpsOnCall(ops, this);
}
grpc_call* call() { return call_; } grpc_call* call() { return call_; }
CompletionQueue* cq() { return cq_; } CompletionQueue* cq() { return cq_; }

@ -54,6 +54,7 @@
#include <string> #include <string>
#include <grpc++/impl/codegen/config.h> #include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/security/auth_context.h> #include <grpc++/impl/codegen/security/auth_context.h>
#include <grpc++/impl/codegen/status.h> #include <grpc++/impl/codegen/status.h>
#include <grpc++/impl/codegen/string_ref.h> #include <grpc++/impl/codegen/string_ref.h>
@ -192,7 +193,7 @@ class ClientContext {
/// \return A multimap of initial metadata key-value pairs from the server. /// \return A multimap of initial metadata key-value pairs from the server.
const std::multimap<grpc::string_ref, grpc::string_ref>& const std::multimap<grpc::string_ref, grpc::string_ref>&
GetServerInitialMetadata() { GetServerInitialMetadata() {
GPR_ASSERT(initial_metadata_received_); GPR_CODEGEN_ASSERT(initial_metadata_received_);
return recv_initial_metadata_; return recv_initial_metadata_;
} }

@ -37,6 +37,7 @@
#include <grpc++/impl/codegen/call.h> #include <grpc++/impl/codegen/call.h>
#include <grpc++/impl/codegen/channel_interface.h> #include <grpc++/impl/codegen/channel_interface.h>
#include <grpc++/impl/codegen/config.h> #include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/status.h> #include <grpc++/impl/codegen/status.h>
namespace grpc { namespace grpc {
@ -66,7 +67,7 @@ Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method,
ops.ClientSendClose(); ops.ClientSendClose();
ops.ClientRecvStatus(context, &status); ops.ClientRecvStatus(context, &status);
call.PerformOps(&ops); call.PerformOps(&ops);
GPR_ASSERT((cq.Pluck(&ops) && ops.got_message) || !status.ok()); GPR_CODEGEN_ASSERT((cq.Pluck(&ops) && ops.got_message) || !status.ok());
return status; return status;
} }

@ -36,9 +36,12 @@
#ifndef GRPCXX_IMPL_CODEGEN_COMPLETION_QUEUE_H #ifndef GRPCXX_IMPL_CODEGEN_COMPLETION_QUEUE_H
#define GRPCXX_IMPL_CODEGEN_COMPLETION_QUEUE_H #define GRPCXX_IMPL_CODEGEN_COMPLETION_QUEUE_H
#include <grpc++/impl/codegen/completion_queue_tag.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/grpc_library.h> #include <grpc++/impl/codegen/grpc_library.h>
#include <grpc++/impl/codegen/status.h> #include <grpc++/impl/codegen/status.h>
#include <grpc++/impl/codegen/time.h> #include <grpc++/impl/codegen/time.h>
#include <grpc/impl/codegen/time.h>
struct grpc_completion_queue; struct grpc_completion_queue;
@ -76,13 +79,17 @@ class Server;
class ServerBuilder; class ServerBuilder;
class ServerContext; class ServerContext;
extern CoreCodegenInterface* g_core_codegen_interface;
/// A thin wrapper around \a grpc_completion_queue (see / \a /// A thin wrapper around \a grpc_completion_queue (see / \a
/// src/core/surface/completion_queue.h). /// src/core/surface/completion_queue.h).
class CompletionQueue : private GrpcLibrary { class CompletionQueue : private GrpcLibraryCodegen {
public: public:
/// Default constructor. Implicitly creates a \a grpc_completion_queue /// Default constructor. Implicitly creates a \a grpc_completion_queue
/// instance. /// instance.
CompletionQueue(); CompletionQueue() {
cq_ = g_core_codegen_interface->grpc_completion_queue_create(nullptr);
}
/// Wrap \a take, taking ownership of the instance. /// Wrap \a take, taking ownership of the instance.
/// ///
@ -90,7 +97,9 @@ class CompletionQueue : private GrpcLibrary {
explicit CompletionQueue(grpc_completion_queue* take); explicit CompletionQueue(grpc_completion_queue* take);
/// Destructor. Destroys the owned wrapped completion queue / instance. /// Destructor. Destroys the owned wrapped completion queue / instance.
~CompletionQueue(); ~CompletionQueue() {
g_core_codegen_interface->grpc_completion_queue_destroy(cq_);
}
/// Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT. /// Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT.
enum NextStatus { enum NextStatus {
@ -124,8 +133,8 @@ class CompletionQueue : private GrpcLibrary {
/// ///
/// \return true if read a regular event, false if the queue is shutting down. /// \return true if read a regular event, false if the queue is shutting down.
bool Next(void** tag, bool* ok) { bool Next(void** tag, bool* ok) {
return (AsyncNextInternal(tag, ok, gpr_inf_future(GPR_CLOCK_REALTIME)) != return (AsyncNextInternal(tag, ok, g_core_codegen_interface->gpr_inf_future(
SHUTDOWN); GPR_CLOCK_REALTIME)) != SHUTDOWN);
} }
/// Request the shutdown of the queue. /// Request the shutdown of the queue.
@ -181,10 +190,31 @@ class CompletionQueue : private GrpcLibrary {
/// Wraps \a grpc_completion_queue_pluck. /// Wraps \a grpc_completion_queue_pluck.
/// \warning Must not be mixed with calls to \a Next. /// \warning Must not be mixed with calls to \a Next.
bool Pluck(CompletionQueueTag* tag); bool Pluck(CompletionQueueTag* tag) {
auto deadline =
g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME);
auto ev = g_core_codegen_interface->grpc_completion_queue_pluck(
cq_, tag, deadline, nullptr);
bool ok = ev.success != 0;
void* ignored = tag;
GPR_CODEGEN_ASSERT(tag->FinalizeResult(&ignored, &ok));
GPR_CODEGEN_ASSERT(ignored == tag);
// Ignore mutations by FinalizeResult: Pluck returns the C API status
return ev.success != 0;
}
/// Performs a single polling pluck on \a tag. /// Performs a single polling pluck on \a tag.
void TryPluck(CompletionQueueTag* tag); /// \warning Must not be mixed with calls to \a Next.
void TryPluck(CompletionQueueTag* tag) {
auto deadline = gpr_time_0(GPR_CLOCK_REALTIME);
auto ev = g_core_codegen_interface->grpc_completion_queue_pluck(
cq_, tag, deadline, nullptr);
if (ev.type == GRPC_QUEUE_TIMEOUT) return;
bool ok = ev.success != 0;
void* ignored = tag;
// the tag must be swallowed if using TryPluck
GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok));
}
grpc_completion_queue* cq_; // owned grpc_completion_queue* cq_; // owned
}; };

@ -0,0 +1,97 @@
/*
*
* Copyright 2015-2016, 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 GRPCXX_IMPL_CODEGEN_CORE_CODEGEN_INTERFACE_H
#define GRPCXX_IMPL_CODEGEN_CORE_CODEGEN_INTERFACE_H
#include <grpc++/impl/codegen/config_protobuf.h>
#include <grpc++/impl/codegen/status.h>
#include <grpc/impl/codegen/grpc_types.h>
namespace grpc {
/// Interface between the codegen library and the minimal subset of core
/// features required by the generated code.
///
/// All undocumented methods are simply forwarding the call to their namesakes.
/// Please refer to their corresponding documentation for details.
///
/// \warning This interface should be considered internal and private.
class CoreCodegenInterface {
public:
// Serialize the msg into a buffer created inside the function. The caller
// should destroy the returned buffer when done with it. If serialization
// fails,
// false is returned and buffer is left unchanged.
virtual Status SerializeProto(const grpc::protobuf::Message& msg,
grpc_byte_buffer** buffer) = 0;
// The caller keeps ownership of buffer and msg.
virtual Status DeserializeProto(grpc_byte_buffer* buffer,
grpc::protobuf::Message* msg,
int max_message_size) = 0;
/// Upon a failed assertion, log the error.
virtual void assert_fail(const char* failed_assertion) = 0;
virtual grpc_completion_queue* grpc_completion_queue_create(
void* reserved) = 0;
virtual void grpc_completion_queue_destroy(grpc_completion_queue* cq) = 0;
virtual grpc_event grpc_completion_queue_pluck(grpc_completion_queue* cq,
void* tag,
gpr_timespec deadline,
void* reserved) = 0;
virtual void* gpr_malloc(size_t size) = 0;
virtual void gpr_free(void* p) = 0;
virtual void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) = 0;
virtual void grpc_metadata_array_init(grpc_metadata_array* array) = 0;
virtual void grpc_metadata_array_destroy(grpc_metadata_array* array) = 0;
virtual gpr_timespec gpr_inf_future(gpr_clock_type type) = 0;
};
extern CoreCodegenInterface* g_core_codegen_interface;
/// Codegen specific version of \a GPR_ASSERT.
#define GPR_CODEGEN_ASSERT(x) \
do { \
if (!(x)) { \
grpc::g_core_codegen_interface->assert_fail(#x); \
} \
} while (0)
} // namespace grpc
#endif // GRPCXX_IMPL_CODEGEN_CORE_CODEGEN_INTERFACE_H

@ -34,6 +34,7 @@
#ifndef GRPCXX_IMPL_CODEGEN_GRPC_LIBRARY_H #ifndef GRPCXX_IMPL_CODEGEN_GRPC_LIBRARY_H
#define GRPCXX_IMPL_CODEGEN_GRPC_LIBRARY_H #define GRPCXX_IMPL_CODEGEN_GRPC_LIBRARY_H
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc/impl/codegen/log.h> #include <grpc/impl/codegen/log.h>
namespace grpc { namespace grpc {
@ -44,18 +45,21 @@ class GrpcLibraryInterface {
virtual void shutdown() = 0; virtual void shutdown() = 0;
}; };
/// Initialized by \a grpc::GrpcLibraryInitializer from
/// <grpc++/impl/grpc_library.h>
extern GrpcLibraryInterface* g_glip; extern GrpcLibraryInterface* g_glip;
class GrpcLibrary { /// Classes that require gRPC to be initialized should inherit from this class.
class GrpcLibraryCodegen {
public: public:
GrpcLibrary() { GrpcLibraryCodegen() {
GPR_ASSERT(g_glip && GPR_CODEGEN_ASSERT(g_glip &&
"gRPC library not initialized. See " "gRPC library not initialized. See "
"grpc::internal::GrpcLibraryInitializer."); "grpc::internal::GrpcLibraryInitializer.");
g_glip->init(); g_glip->init();
} }
virtual ~GrpcLibrary() { virtual ~GrpcLibraryCodegen() {
GPR_ASSERT(g_glip && GPR_CODEGEN_ASSERT(g_glip &&
"gRPC library not initialized. See " "gRPC library not initialized. See "
"grpc::internal::GrpcLibraryInitializer."); "grpc::internal::GrpcLibraryInitializer.");
g_glip->shutdown(); g_glip->shutdown();
@ -64,4 +68,4 @@ class GrpcLibrary {
} // namespace grpc } // namespace grpc
#endif // GRPCXX_IMPL_GRPC_LIBRARY_H #endif // GRPCXX_IMPL_CODEGEN_GRPC_LIBRARY_H

@ -0,0 +1,463 @@
/*
*
* Copyright 2015-2016, 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 GRPCXX_IMPL_CODEGEN_ASYNC_STREAM_H
#define GRPCXX_IMPL_CODEGEN_ASYNC_STREAM_H
#include <grpc++/impl/codegen/call.h>
#include <grpc++/impl/codegen/channel_interface.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/server_context.h>
#include <grpc++/impl/codegen/service_type.h>
#include <grpc++/impl/codegen/status.h>
namespace grpc {
class CompletionQueue;
/// Common interface for all client side asynchronous streaming.
class ClientAsyncStreamingInterface {
public:
virtual ~ClientAsyncStreamingInterface() {}
/// Request notification of the reading of the initial metadata. Completion
/// will be notified by \a tag on the associated completion queue.
///
/// \param[in] tag Tag identifying this request.
virtual void ReadInitialMetadata(void* tag) = 0;
/// Request notification completion.
///
/// \param[out] status To be updated with the operation status.
/// \param[in] tag Tag identifying this request.
virtual void Finish(Status* status, void* tag) = 0;
};
/// An interface that yields a sequence of messages of type \a R.
template <class R>
class AsyncReaderInterface {
public:
virtual ~AsyncReaderInterface() {}
/// Read a message of type \a R into \a msg. Completion will be notified by \a
/// tag on the associated completion queue.
///
/// \param[out] msg Where to eventually store the read message.
/// \param[in] tag The tag identifying the operation.
virtual void Read(R* msg, void* tag) = 0;
};
/// An interface that can be fed a sequence of messages of type \a W.
template <class W>
class AsyncWriterInterface {
public:
virtual ~AsyncWriterInterface() {}
/// Request the writing of \a msg with identifying tag \a tag.
///
/// Only one write may be outstanding at any given time. This means that
/// after calling Write, one must wait to receive \a tag from the completion
/// queue BEFORE calling Write again.
///
/// \param[in] msg The message to be written.
/// \param[in] tag The tag identifying the operation.
virtual void Write(const W& msg, void* tag) = 0;
};
template <class R>
class ClientAsyncReaderInterface : public ClientAsyncStreamingInterface,
public AsyncReaderInterface<R> {};
template <class R>
class ClientAsyncReader GRPC_FINAL : public ClientAsyncReaderInterface<R> {
public:
/// Create a stream and write the first request out.
template <class W>
ClientAsyncReader(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
const W& request, void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
init_ops_.set_output_tag(tag);
init_ops_.SendInitialMetadata(context->send_initial_metadata_);
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(init_ops_.SendMessage(request).ok());
init_ops_.ClientSendClose();
call_.PerformOps(&init_ops_);
}
void ReadInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag);
meta_ops_.RecvInitialMetadata(context_);
call_.PerformOps(&meta_ops_);
}
void Read(R* msg, void* tag) GRPC_OVERRIDE {
read_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
read_ops_.RecvInitialMetadata(context_);
}
read_ops_.RecvMessage(msg);
call_.PerformOps(&read_ops_);
}
void Finish(Status* status, void* tag) GRPC_OVERRIDE {
finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
finish_ops_.RecvInitialMetadata(context_);
}
finish_ops_.ClientRecvStatus(context_, status);
call_.PerformOps(&finish_ops_);
}
private:
ClientContext* context_;
Call call_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose>
init_ops_;
CallOpSet<CallOpRecvInitialMetadata> meta_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> read_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> finish_ops_;
};
/// Common interface for client side asynchronous writing.
template <class W>
class ClientAsyncWriterInterface : public ClientAsyncStreamingInterface,
public AsyncWriterInterface<W> {
public:
/// Signal the client is done with the writes.
///
/// \param[in] tag The tag identifying the operation.
virtual void WritesDone(void* tag) = 0;
};
template <class W>
class ClientAsyncWriter GRPC_FINAL : public ClientAsyncWriterInterface<W> {
public:
template <class R>
ClientAsyncWriter(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
R* response, void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
finish_ops_.RecvMessage(response);
init_ops_.set_output_tag(tag);
init_ops_.SendInitialMetadata(context->send_initial_metadata_);
call_.PerformOps(&init_ops_);
}
void ReadInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag);
meta_ops_.RecvInitialMetadata(context_);
call_.PerformOps(&meta_ops_);
}
void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag);
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}
void WritesDone(void* tag) GRPC_OVERRIDE {
writes_done_ops_.set_output_tag(tag);
writes_done_ops_.ClientSendClose();
call_.PerformOps(&writes_done_ops_);
}
void Finish(Status* status, void* tag) GRPC_OVERRIDE {
finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
finish_ops_.RecvInitialMetadata(context_);
}
finish_ops_.ClientRecvStatus(context_, status);
call_.PerformOps(&finish_ops_);
}
private:
ClientContext* context_;
Call call_;
CallOpSet<CallOpSendInitialMetadata> init_ops_;
CallOpSet<CallOpRecvInitialMetadata> meta_ops_;
CallOpSet<CallOpSendMessage> write_ops_;
CallOpSet<CallOpClientSendClose> writes_done_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpGenericRecvMessage,
CallOpClientRecvStatus> finish_ops_;
};
/// Client-side interface for asynchronous bi-directional streaming.
template <class W, class R>
class ClientAsyncReaderWriterInterface : public ClientAsyncStreamingInterface,
public AsyncWriterInterface<W>,
public AsyncReaderInterface<R> {
public:
/// Signal the client is done with the writes.
///
/// \param[in] tag The tag identifying the operation.
virtual void WritesDone(void* tag) = 0;
};
template <class W, class R>
class ClientAsyncReaderWriter GRPC_FINAL
: public ClientAsyncReaderWriterInterface<W, R> {
public:
ClientAsyncReaderWriter(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
init_ops_.set_output_tag(tag);
init_ops_.SendInitialMetadata(context->send_initial_metadata_);
call_.PerformOps(&init_ops_);
}
void ReadInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag);
meta_ops_.RecvInitialMetadata(context_);
call_.PerformOps(&meta_ops_);
}
void Read(R* msg, void* tag) GRPC_OVERRIDE {
read_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
read_ops_.RecvInitialMetadata(context_);
}
read_ops_.RecvMessage(msg);
call_.PerformOps(&read_ops_);
}
void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag);
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}
void WritesDone(void* tag) GRPC_OVERRIDE {
writes_done_ops_.set_output_tag(tag);
writes_done_ops_.ClientSendClose();
call_.PerformOps(&writes_done_ops_);
}
void Finish(Status* status, void* tag) GRPC_OVERRIDE {
finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
finish_ops_.RecvInitialMetadata(context_);
}
finish_ops_.ClientRecvStatus(context_, status);
call_.PerformOps(&finish_ops_);
}
private:
ClientContext* context_;
Call call_;
CallOpSet<CallOpSendInitialMetadata> init_ops_;
CallOpSet<CallOpRecvInitialMetadata> meta_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> read_ops_;
CallOpSet<CallOpSendMessage> write_ops_;
CallOpSet<CallOpClientSendClose> writes_done_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> finish_ops_;
};
template <class W, class R>
class ServerAsyncReader GRPC_FINAL : public ServerAsyncStreamingInterface,
public AsyncReaderInterface<R> {
public:
explicit ServerAsyncReader(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_ops_);
}
void Read(R* msg, void* tag) GRPC_OVERRIDE {
read_ops_.set_output_tag(tag);
read_ops_.RecvMessage(msg);
call_.PerformOps(&read_ops_);
}
void Finish(const W& msg, const Status& status, void* tag) {
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
// The response is dropped if the status is not OK.
if (status.ok()) {
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_,
finish_ops_.SendMessage(msg));
} else {
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
}
call_.PerformOps(&finish_ops_);
}
void FinishWithError(const Status& status, void* tag) {
GPR_CODEGEN_ASSERT(!status.ok());
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_ops_);
}
private:
void BindCall(Call* call) GRPC_OVERRIDE { call_ = *call; }
Call call_;
ServerContext* ctx_;
CallOpSet<CallOpSendInitialMetadata> meta_ops_;
CallOpSet<CallOpRecvMessage<R>> read_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpServerSendStatus> finish_ops_;
};
template <class W>
class ServerAsyncWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
public AsyncWriterInterface<W> {
public:
explicit ServerAsyncWriter(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_ops_);
}
void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
write_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}
void Finish(const Status& status, void* tag) {
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_ops_);
}
private:
void BindCall(Call* call) GRPC_OVERRIDE { call_ = *call; }
Call call_;
ServerContext* ctx_;
CallOpSet<CallOpSendInitialMetadata> meta_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage> write_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> finish_ops_;
};
/// Server-side interface for asynchronous bi-directional streaming.
template <class W, class R>
class ServerAsyncReaderWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
public AsyncWriterInterface<W>,
public AsyncReaderInterface<R> {
public:
explicit ServerAsyncReaderWriter(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_ops_);
}
void Read(R* msg, void* tag) GRPC_OVERRIDE {
read_ops_.set_output_tag(tag);
read_ops_.RecvMessage(msg);
call_.PerformOps(&read_ops_);
}
void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
write_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}
void Finish(const Status& status, void* tag) {
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_ops_);
}
private:
friend class ::grpc::Server;
void BindCall(Call* call) GRPC_OVERRIDE { call_ = *call; }
Call call_;
ServerContext* ctx_;
CallOpSet<CallOpSendInitialMetadata> meta_ops_;
CallOpSet<CallOpRecvMessage<R>> read_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage> write_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> finish_ops_;
};
} // namespace grpc
#endif // GRPCXX_IMPL_CODEGEN_ASYNC_STREAM_H

@ -0,0 +1,152 @@
/*
*
* Copyright 2016, 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 GRPCXX_IMPL_CODEGEN_STATUS_CODE_ENUM_H
#define GRPCXX_IMPL_CODEGEN_STATUS_CODE_ENUM_H
namespace grpc {
enum StatusCode {
/// Not an error; returned on success.
OK = 0,
/// The operation was cancelled (typically by the caller).
CANCELLED = 1,
/// Unknown error. An example of where this error may be returned is if a
/// Status value received from another address space belongs to an error-space
/// that is not known in this address space. Also errors raised by APIs that
/// do not return enough error information may be converted to this error.
UNKNOWN = 2,
/// Client specified an invalid argument. Note that this differs from
/// FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments that are
/// problematic regardless of the state of the system (e.g., a malformed file
/// name).
INVALID_ARGUMENT = 3,
/// Deadline expired before operation could complete. For operations that
/// change the state of the system, this error may be returned even if the
/// operation has completed successfully. For example, a successful response
/// from a server could have been delayed long enough for the deadline to
/// expire.
DEADLINE_EXCEEDED = 4,
/// Some requested entity (e.g., file or directory) was not found.
NOT_FOUND = 5,
/// Some entity that we attempted to create (e.g., file or directory) already
/// exists.
ALREADY_EXISTS = 6,
/// The caller does not have permission to execute the specified operation.
/// PERMISSION_DENIED must not be used for rejections caused by exhausting
/// some resource (use RESOURCE_EXHAUSTED instead for those errors).
/// PERMISSION_DENIED must not be used if the caller can not be identified
/// (use UNAUTHENTICATED instead for those errors).
PERMISSION_DENIED = 7,
/// The request does not have valid authentication credentials for the
/// operation.
UNAUTHENTICATED = 16,
/// Some resource has been exhausted, perhaps a per-user quota, or perhaps the
/// entire file system is out of space.
RESOURCE_EXHAUSTED = 8,
/// Operation was rejected because the system is not in a state required for
/// the operation's execution. For example, directory to be deleted may be
/// non-empty, an rmdir operation is applied to a non-directory, etc.
///
/// A litmus test that may help a service implementor in deciding
/// between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE:
/// (a) Use UNAVAILABLE if the client can retry just the failing call.
/// (b) Use ABORTED if the client should retry at a higher-level
/// (e.g., restarting a read-modify-write sequence).
/// (c) Use FAILED_PRECONDITION if the client should not retry until
/// the system state has been explicitly fixed. E.g., if an "rmdir"
/// fails because the directory is non-empty, FAILED_PRECONDITION
/// should be returned since the client should not retry unless
/// they have first fixed up the directory by deleting files from it.
/// (d) Use FAILED_PRECONDITION if the client performs conditional
/// REST Get/Update/Delete on a resource and the resource on the
/// server does not match the condition. E.g., conflicting
/// read-modify-write on the same resource.
FAILED_PRECONDITION = 9,
/// The operation was aborted, typically due to a concurrency issue like
/// sequencer check failures, transaction aborts, etc.
///
/// See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,
/// and UNAVAILABLE.
ABORTED = 10,
/// Operation was attempted past the valid range. E.g., seeking or reading
/// past end of file.
///
/// Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed
/// if the system state changes. For example, a 32-bit file system will
/// generate INVALID_ARGUMENT if asked to read at an offset that is not in the
/// range [0,2^32-1], but it will generate OUT_OF_RANGE if asked to read from
/// an offset past the current file size.
///
/// There is a fair bit of overlap between FAILED_PRECONDITION and
/// OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific error)
/// when it applies so that callers who are iterating through a space can
/// easily look for an OUT_OF_RANGE error to detect when they are done.
OUT_OF_RANGE = 11,
/// Operation is not implemented or not supported/enabled in this service.
UNIMPLEMENTED = 12,
/// Internal errors. Means some invariants expected by underlying System has
/// been broken. If you see one of these errors, Something is very broken.
INTERNAL = 13,
/// The service is currently unavailable. This is a most likely a transient
/// condition and may be corrected by retrying with a backoff.
///
/// See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,
/// and UNAVAILABLE.
UNAVAILABLE = 14,
/// Unrecoverable data loss or corruption.
DATA_LOSS = 15,
/// Force users to include a default branch:
DO_NOT_USE = -1
};
} // namespace grpc
#endif // GRPCXX_IMPL_CODEGEN_STATUS_CODE_ENUM_H

@ -0,0 +1,45 @@
/*
*
* Copyright 2015-2016, 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 GRPCXX_IMPL_CODEGEN_SYNC_H
#define GRPCXX_IMPL_CODEGEN_SYNC_H
#include <grpc++/impl/codegen/config.h>
#ifdef GRPC_CXX0X_NO_THREAD
#include <grpc++/impl/codegen/sync_no_cxx11.h>
#else
#include <grpc++/impl/codegen/sync_cxx11.h>
#endif
#endif // GRPCXX_IMPL_CODEGEN_SYNC_H

@ -34,6 +34,7 @@
#ifndef GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H #ifndef GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H
#define GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H #define GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/rpc_service_method.h> #include <grpc++/impl/codegen/rpc_service_method.h>
#include <grpc++/impl/codegen/sync_stream.h> #include <grpc++/impl/codegen/sync_stream.h>
@ -58,7 +59,7 @@ class RpcMethodHandler : public MethodHandler {
status = func_(service_, param.server_context, &req, &rsp); status = func_(service_, param.server_context, &req, &rsp);
} }
GPR_ASSERT(!param.server_context->sent_initial_metadata_); GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_);
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpServerSendStatus> ops; CallOpServerSendStatus> ops;
ops.SendInitialMetadata(param.server_context->initial_metadata_); ops.SendInitialMetadata(param.server_context->initial_metadata_);
@ -93,7 +94,7 @@ class ClientStreamingHandler : public MethodHandler {
ResponseType rsp; ResponseType rsp;
Status status = func_(service_, param.server_context, &reader, &rsp); Status status = func_(service_, param.server_context, &reader, &rsp);
GPR_ASSERT(!param.server_context->sent_initial_metadata_); GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_);
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpServerSendStatus> ops; CallOpServerSendStatus> ops;
ops.SendInitialMetadata(param.server_context->initial_metadata_); ops.SendInitialMetadata(param.server_context->initial_metadata_);

@ -36,22 +36,16 @@
#include <type_traits> #include <type_traits>
#include <grpc/impl/codegen/byte_buffer.h>
#include <grpc++/impl/codegen/serialization_traits.h>
#include <grpc++/impl/codegen/config_protobuf.h> #include <grpc++/impl/codegen/config_protobuf.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/serialization_traits.h>
#include <grpc++/impl/codegen/status.h> #include <grpc++/impl/codegen/status.h>
#include <grpc/impl/codegen/byte_buffer.h>
#include <grpc/impl/codegen/log.h>
namespace grpc { namespace grpc {
// Serialize the msg into a buffer created inside the function. The caller extern CoreCodegenInterface* g_core_codegen_interface;
// should destroy the returned buffer when done with it. If serialization fails,
// false is returned and buffer is left unchanged.
Status SerializeProto(const grpc::protobuf::Message& msg,
grpc_byte_buffer** buffer);
// The caller keeps ownership of buffer and msg.
Status DeserializeProto(grpc_byte_buffer* buffer, grpc::protobuf::Message* msg,
int max_message_size);
template <class T> template <class T>
class SerializationTraits<T, typename std::enable_if<std::is_base_of< class SerializationTraits<T, typename std::enable_if<std::is_base_of<
@ -60,14 +54,13 @@ class SerializationTraits<T, typename std::enable_if<std::is_base_of<
static Status Serialize(const grpc::protobuf::Message& msg, static Status Serialize(const grpc::protobuf::Message& msg,
grpc_byte_buffer** buffer, bool* own_buffer) { grpc_byte_buffer** buffer, bool* own_buffer) {
*own_buffer = true; *own_buffer = true;
return SerializeProto(msg, buffer); return g_core_codegen_interface->SerializeProto(msg, buffer);
} }
static Status Deserialize(grpc_byte_buffer* buffer, static Status Deserialize(grpc_byte_buffer* buffer,
grpc::protobuf::Message* msg, grpc::protobuf::Message* msg,
int max_message_size) { int max_message_size) {
auto status = DeserializeProto(buffer, msg, max_message_size); return g_core_codegen_interface->DeserializeProto(buffer, msg,
grpc_byte_buffer_destroy(buffer); max_message_size);
return status;
} }
}; };

@ -103,6 +103,9 @@ class ServerContext {
void AddInitialMetadata(const grpc::string& key, const grpc::string& value); void AddInitialMetadata(const grpc::string& key, const grpc::string& value);
void AddTrailingMetadata(const grpc::string& key, const grpc::string& value); void AddTrailingMetadata(const grpc::string& key, const grpc::string& value);
// IsCancelled is always safe to call when using sync API
// When using async API, it is only safe to call IsCancelled after
// the AsyncNotifyWhenDone tag has been delivered
bool IsCancelled() const; bool IsCancelled() const;
// Cancel the Call from the server. This is a best-effort API and depending on // Cancel the Call from the server. This is a best-effort API and depending on

@ -34,10 +34,11 @@
#ifndef GRPCXX_IMPL_CODEGEN_SERVER_INTERFACE_H #ifndef GRPCXX_IMPL_CODEGEN_SERVER_INTERFACE_H
#define GRPCXX_IMPL_CODEGEN_SERVER_INTERFACE_H #define GRPCXX_IMPL_CODEGEN_SERVER_INTERFACE_H
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc++/impl/codegen/call_hook.h> #include <grpc++/impl/codegen/call_hook.h>
#include <grpc++/impl/codegen/completion_queue_tag.h> #include <grpc++/impl/codegen/completion_queue_tag.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/rpc_service_method.h> #include <grpc++/impl/codegen/rpc_service_method.h>
#include <grpc/impl/codegen/grpc_types.h>
namespace grpc { namespace grpc {
@ -223,7 +224,7 @@ class ServerInterface : public CallHook {
CompletionQueue* call_cq, CompletionQueue* call_cq,
ServerCompletionQueue* notification_cq, void* tag, ServerCompletionQueue* notification_cq, void* tag,
Message* message) { Message* message) {
GPR_ASSERT(method); GPR_CODEGEN_ASSERT(method);
new PayloadAsyncRequest<Message>(method->server_tag(), this, context, new PayloadAsyncRequest<Message>(method->server_tag(), this, context,
stream, call_cq, notification_cq, tag, stream, call_cq, notification_cq, tag,
message); message);
@ -233,7 +234,7 @@ class ServerInterface : public CallHook {
ServerAsyncStreamingInterface* stream, ServerAsyncStreamingInterface* stream,
CompletionQueue* call_cq, CompletionQueue* call_cq,
ServerCompletionQueue* notification_cq, void* tag) { ServerCompletionQueue* notification_cq, void* tag) {
GPR_ASSERT(method); GPR_CODEGEN_ASSERT(method);
new NoPayloadAsyncRequest(method->server_tag(), this, context, stream, new NoPayloadAsyncRequest(method->server_tag(), this, context, stream,
call_cq, notification_cq, tag); call_cq, notification_cq, tag);
} }

@ -35,6 +35,7 @@
#define GRPCXX_IMPL_CODEGEN_SERVICE_TYPE_H #define GRPCXX_IMPL_CODEGEN_SERVICE_TYPE_H
#include <grpc++/impl/codegen/config.h> #include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/rpc_service_method.h> #include <grpc++/impl/codegen/rpc_service_method.h>
#include <grpc++/impl/codegen/serialization_traits.h> #include <grpc++/impl/codegen/serialization_traits.h>
#include <grpc++/impl/codegen/server_interface.h> #include <grpc++/impl/codegen/server_interface.h>
@ -131,21 +132,18 @@ class Service {
void AddMethod(RpcServiceMethod* method) { methods_.emplace_back(method); } void AddMethod(RpcServiceMethod* method) { methods_.emplace_back(method); }
void MarkMethodAsync(int index) { void MarkMethodAsync(int index) {
if (methods_[index].get() == nullptr) { GPR_CODEGEN_ASSERT(
gpr_log(GPR_ERROR, methods_[index].get() != nullptr &&
"Cannot mark the method as 'async' because it has already been " "Cannot mark the method as 'async' because it has already been "
"marked as 'generic'."); "marked as 'generic'.");
return;
}
methods_[index]->ResetHandler(); methods_[index]->ResetHandler();
} }
void MarkMethodGeneric(int index) { void MarkMethodGeneric(int index) {
if (methods_[index]->handler() == nullptr) { GPR_CODEGEN_ASSERT(
gpr_log(GPR_ERROR, methods_[index]->handler() != nullptr &&
"Cannot mark the method as 'generic' because it has already been " "Cannot mark the method as 'generic' because it has already been "
"marked as 'async'."); "marked as 'async'.");
}
methods_[index].reset(); methods_[index].reset();
} }

@ -34,8 +34,12 @@
#ifndef GRPCXX_IMPL_CODEGEN_STRING_REF_H #ifndef GRPCXX_IMPL_CODEGEN_STRING_REF_H
#define GRPCXX_IMPL_CODEGEN_STRING_REF_H #define GRPCXX_IMPL_CODEGEN_STRING_REF_H
#include <iterator> #include <string.h>
#include <algorithm>
#include <iosfwd> #include <iosfwd>
#include <iostream>
#include <iterator>
#include <grpc++/impl/codegen/config.h> #include <grpc++/impl/codegen/config.h>
@ -62,8 +66,13 @@ class string_ref {
string_ref() : data_(nullptr), length_(0) {} string_ref() : data_(nullptr), length_(0) {}
string_ref(const string_ref& other) string_ref(const string_ref& other)
: data_(other.data_), length_(other.length_) {} : data_(other.data_), length_(other.length_) {}
string_ref& operator=(const string_ref& rhs); string_ref& operator=(const string_ref& rhs) {
string_ref(const char* s); data_ = rhs.data_;
length_ = rhs.length_;
return *this;
}
string_ref(const char* s) : data_(s), length_(strlen(s)) {}
string_ref(const char* s, size_t l) : data_(s), length_(l) {} string_ref(const char* s, size_t l) : data_(s), length_(l) {}
string_ref(const grpc::string& s) : data_(s.data()), length_(s.length()) {} string_ref(const grpc::string& s) : data_(s.data()), length_(s.length()) {}
@ -95,13 +104,40 @@ class string_ref {
const char* data() const { return data_; } const char* data() const { return data_; }
// string operations // string operations
int compare(string_ref x) const; int compare(string_ref x) const {
bool starts_with(string_ref x) const; size_t min_size = length_ < x.length_ ? length_ : x.length_;
bool ends_with(string_ref x) const; int r = memcmp(data_, x.data_, min_size);
size_t find(string_ref s) const; if (r < 0) return -1;
size_t find(char c) const; if (r > 0) return 1;
if (length_ < x.length_) return -1;
if (length_ > x.length_) return 1;
return 0;
}
bool starts_with(string_ref x) const {
return length_ >= x.length_ && (memcmp(data_, x.data_, x.length_) == 0);
}
string_ref substr(size_t pos, size_t n = npos) const; bool ends_with(string_ref x) const {
return length_ >= x.length_ &&
(memcmp(data_ + (length_ - x.length_), x.data_, x.length_) == 0);
}
size_t find(string_ref s) const {
auto it = std::search(cbegin(), cend(), s.cbegin(), s.cend());
return it == cend() ? npos : std::distance(cbegin(), it);
}
size_t find(char c) const {
auto it = std::find(cbegin(), cend(), c);
return it == cend() ? npos : std::distance(cbegin(), it);
}
string_ref substr(size_t pos, size_t n = npos) const {
if (pos > length_) pos = length_;
if (n > (length_ - pos)) n = length_ - pos;
return string_ref(data_ + pos, n);
}
private: private:
const char* data_; const char* data_;
@ -109,14 +145,16 @@ class string_ref {
}; };
// Comparison operators // Comparison operators
bool operator==(string_ref x, string_ref y); inline bool operator==(string_ref x, string_ref y) { return x.compare(y) == 0; }
bool operator!=(string_ref x, string_ref y); inline bool operator!=(string_ref x, string_ref y) { return x.compare(y) != 0; }
bool operator<(string_ref x, string_ref y); inline bool operator<(string_ref x, string_ref y) { return x.compare(y) < 0; }
bool operator>(string_ref x, string_ref y); inline bool operator<=(string_ref x, string_ref y) { return x.compare(y) <= 0; }
bool operator<=(string_ref x, string_ref y); inline bool operator>(string_ref x, string_ref y) { return x.compare(y) > 0; }
bool operator>=(string_ref x, string_ref y); inline bool operator>=(string_ref x, string_ref y) { return x.compare(y) >= 0; }
std::ostream& operator<<(std::ostream& stream, const string_ref& string); inline std::ostream& operator<<(std::ostream& out, const string_ref& string) {
return out << grpc::string(string.begin(), string.end());
}
} // namespace grpc } // namespace grpc

@ -38,6 +38,7 @@
#include <grpc++/impl/codegen/channel_interface.h> #include <grpc++/impl/codegen/channel_interface.h>
#include <grpc++/impl/codegen/client_context.h> #include <grpc++/impl/codegen/client_context.h>
#include <grpc++/impl/codegen/completion_queue.h> #include <grpc++/impl/codegen/completion_queue.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/server_context.h> #include <grpc++/impl/codegen/server_context.h>
#include <grpc++/impl/codegen/service_type.h> #include <grpc++/impl/codegen/service_type.h>
#include <grpc++/impl/codegen/status.h> #include <grpc++/impl/codegen/status.h>
@ -125,14 +126,14 @@ class ClientReader GRPC_FINAL : public ClientReaderInterface<R> {
CallOpClientSendClose> ops; CallOpClientSendClose> ops;
ops.SendInitialMetadata(context->send_initial_metadata_); ops.SendInitialMetadata(context->send_initial_metadata_);
// TODO(ctiller): don't assert // TODO(ctiller): don't assert
GPR_ASSERT(ops.SendMessage(request).ok()); GPR_CODEGEN_ASSERT(ops.SendMessage(request).ok());
ops.ClientSendClose(); ops.ClientSendClose();
call_.PerformOps(&ops); call_.PerformOps(&ops);
cq_.Pluck(&ops); cq_.Pluck(&ops);
} }
void WaitForInitialMetadata() GRPC_OVERRIDE { void WaitForInitialMetadata() GRPC_OVERRIDE {
GPR_ASSERT(!context_->initial_metadata_received_); GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
CallOpSet<CallOpRecvInitialMetadata> ops; CallOpSet<CallOpRecvInitialMetadata> ops;
ops.RecvInitialMetadata(context_); ops.RecvInitialMetadata(context_);
@ -155,7 +156,7 @@ class ClientReader GRPC_FINAL : public ClientReaderInterface<R> {
Status status; Status status;
ops.ClientRecvStatus(context_, &status); ops.ClientRecvStatus(context_, &status);
call_.PerformOps(&ops); call_.PerformOps(&ops);
GPR_ASSERT(cq_.Pluck(&ops)); GPR_CODEGEN_ASSERT(cq_.Pluck(&ops));
return status; return status;
} }
@ -194,7 +195,7 @@ class ClientWriter : public ClientWriterInterface<W> {
} }
void WaitForInitialMetadata() { void WaitForInitialMetadata() {
GPR_ASSERT(!context_->initial_metadata_received_); GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
CallOpSet<CallOpRecvInitialMetadata> ops; CallOpSet<CallOpRecvInitialMetadata> ops;
ops.RecvInitialMetadata(context_); ops.RecvInitialMetadata(context_);
@ -227,7 +228,7 @@ class ClientWriter : public ClientWriterInterface<W> {
} }
finish_ops_.ClientRecvStatus(context_, &status); finish_ops_.ClientRecvStatus(context_, &status);
call_.PerformOps(&finish_ops_); call_.PerformOps(&finish_ops_);
GPR_ASSERT(cq_.Pluck(&finish_ops_)); GPR_CODEGEN_ASSERT(cq_.Pluck(&finish_ops_));
return status; return status;
} }
@ -271,7 +272,7 @@ class ClientReaderWriter GRPC_FINAL : public ClientReaderWriterInterface<W, R> {
} }
void WaitForInitialMetadata() GRPC_OVERRIDE { void WaitForInitialMetadata() GRPC_OVERRIDE {
GPR_ASSERT(!context_->initial_metadata_received_); GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
CallOpSet<CallOpRecvInitialMetadata> ops; CallOpSet<CallOpRecvInitialMetadata> ops;
ops.RecvInitialMetadata(context_); ops.RecvInitialMetadata(context_);
@ -312,7 +313,7 @@ class ClientReaderWriter GRPC_FINAL : public ClientReaderWriterInterface<W, R> {
Status status; Status status;
ops.ClientRecvStatus(context_, &status); ops.ClientRecvStatus(context_, &status);
call_.PerformOps(&ops); call_.PerformOps(&ops);
GPR_ASSERT(cq_.Pluck(&ops)); GPR_CODEGEN_ASSERT(cq_.Pluck(&ops));
return status; return status;
} }
@ -328,7 +329,7 @@ class ServerReader GRPC_FINAL : public ReaderInterface<R> {
ServerReader(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {} ServerReader(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
void SendInitialMetadata() { void SendInitialMetadata() {
GPR_ASSERT(!ctx_->sent_initial_metadata_); GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
CallOpSet<CallOpSendInitialMetadata> ops; CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(ctx_->initial_metadata_); ops.SendInitialMetadata(ctx_->initial_metadata_);
@ -355,7 +356,7 @@ class ServerWriter GRPC_FINAL : public WriterInterface<W> {
ServerWriter(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {} ServerWriter(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
void SendInitialMetadata() { void SendInitialMetadata() {
GPR_ASSERT(!ctx_->sent_initial_metadata_); GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
CallOpSet<CallOpSendInitialMetadata> ops; CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(ctx_->initial_metadata_); ops.SendInitialMetadata(ctx_->initial_metadata_);
@ -391,7 +392,7 @@ class ServerReaderWriter GRPC_FINAL : public WriterInterface<W>,
ServerReaderWriter(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {} ServerReaderWriter(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
void SendInitialMetadata() { void SendInitialMetadata() {
GPR_ASSERT(!ctx_->sent_initial_metadata_); GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
CallOpSet<CallOpSendInitialMetadata> ops; CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(ctx_->initial_metadata_); ops.SendInitialMetadata(ctx_->initial_metadata_);

@ -40,21 +40,27 @@
#include <grpc++/impl/codegen/grpc_library.h> #include <grpc++/impl/codegen/grpc_library.h>
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include "src/cpp/common/core_codegen.h"
namespace grpc { namespace grpc {
namespace internal { namespace internal {
class GrpcLibrary GRPC_FINAL : public GrpcLibraryInterface { class GrpcLibrary GRPC_FINAL : public GrpcLibraryInterface {
public: public:
void init() GRPC_OVERRIDE { grpc_init(); } void init() GRPC_OVERRIDE { grpc_init(); }
void shutdown() GRPC_OVERRIDE { grpc_shutdown(); } void shutdown() GRPC_OVERRIDE { grpc_shutdown(); }
}; };
static GrpcLibrary g_gli; static GrpcLibrary g_gli;
static CoreCodegen g_core_codegen;
/// Instantiating this class ensures the proper initialization of gRPC.
class GrpcLibraryInitializer GRPC_FINAL { class GrpcLibraryInitializer GRPC_FINAL {
public: public:
GrpcLibraryInitializer() { grpc::g_glip = &g_gli; } GrpcLibraryInitializer() {
grpc::g_glip = &g_gli;
grpc::g_core_codegen_interface = &g_core_codegen;
}
/// A no-op method to force the linker to reference this class, which will /// A no-op method to force the linker to reference this class, which will
/// take care of initializing and shutting down the gRPC runtime. /// take care of initializing and shutting down the gRPC runtime.

@ -57,7 +57,7 @@ class SecureCallCredentials;
/// for all the calls on that channel. /// for all the calls on that channel.
/// ///
/// \see http://www.grpc.io/docs/guides/auth.html /// \see http://www.grpc.io/docs/guides/auth.html
class ChannelCredentials : private GrpcLibrary { class ChannelCredentials : private GrpcLibraryCodegen {
public: public:
ChannelCredentials(); ChannelCredentials();
~ChannelCredentials(); ~ChannelCredentials();
@ -83,7 +83,7 @@ class ChannelCredentials : private GrpcLibrary {
/// authenticate with a server for a given call on a channel. /// authenticate with a server for a given call on a channel.
/// ///
/// \see http://www.grpc.io/docs/guides/auth.html /// \see http://www.grpc.io/docs/guides/auth.html
class CallCredentials : private GrpcLibrary { class CallCredentials : private GrpcLibraryCodegen {
public: public:
CallCredentials(); CallCredentials();
~CallCredentials(); ~CallCredentials();

@ -62,7 +62,7 @@ class ThreadPoolInterface;
/// Models a gRPC server. /// Models a gRPC server.
/// ///
/// Servers are configured and started via \a grpc::ServerBuilder. /// Servers are configured and started via \a grpc::ServerBuilder.
class Server GRPC_FINAL : public ServerInterface, private GrpcLibrary { class Server GRPC_FINAL : public ServerInterface, private GrpcLibraryCodegen {
public: public:
~Server(); ~Server();

@ -247,8 +247,41 @@
#else /* _LP64 */ #else /* _LP64 */
#define GPR_ARCH_32 1 #define GPR_ARCH_32 1
#endif /* _LP64 */ #endif /* _LP64 */
#elif defined(__native_client__)
#define GPR_PLATFORM_STRING "nacl"
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#define GPR_CPU_POSIX 1
#define GPR_GCC_ATOMIC 1
#define GPR_GCC_TLS 1
#define GPR_POSIX_LOG 1
#define GPR_POSIX_MULTIPOLL_WITH_POLL 1
#define GPR_POSIX_WAKEUP_FD 1
#define GPR_POSIX_NO_SPECIAL_WAKEUP_FD 1
#define GPR_POSIX_SOCKET 1
#define GPR_POSIX_SOCKETADDR 1
#define GPR_POSIX_SOCKETUTILS 1
#define GPR_POSIX_ENV 1
#define GPR_POSIX_FILE 1
#define GPR_POSIX_STRING 1
#define GPR_POSIX_SUBPROCESS 1
#define GPR_POSIX_SYNC 1
#define GPR_POSIX_TIME 1
#define GPR_GETPID_IN_UNISTD_H 1
#ifdef _LP64
#define GPR_ARCH_64 1
#else /* _LP64 */
#define GPR_ARCH_32 1
#endif /* _LP64 */
#else #else
#error Could not auto-detect platform #error "Could not auto-detect platform"
#endif #endif
#endif /* GPR_NO_AUTODETECT_PLATFORM */ #endif /* GPR_NO_AUTODETECT_PLATFORM */

@ -87,17 +87,17 @@
"src/node/src/metadata.js", "src/node/src/metadata.js",
"src/node/src/server.js", "src/node/src/server.js",
"include/grpc/grpc_security.h", "include/grpc/grpc_security.h",
"include/grpc/byte_buffer.h",
"include/grpc/byte_buffer_reader.h",
"include/grpc/compression.h",
"include/grpc/grpc.h",
"include/grpc/status.h",
"include/grpc/impl/codegen/byte_buffer.h", "include/grpc/impl/codegen/byte_buffer.h",
"include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/compression_types.h",
"include/grpc/impl/codegen/connectivity_state.h", "include/grpc/impl/codegen/connectivity_state.h",
"include/grpc/impl/codegen/grpc_types.h", "include/grpc/impl/codegen/grpc_types.h",
"include/grpc/impl/codegen/propagation_bits.h", "include/grpc/impl/codegen/propagation_bits.h",
"include/grpc/impl/codegen/status.h", "include/grpc/impl/codegen/status.h",
"include/grpc/byte_buffer.h",
"include/grpc/byte_buffer_reader.h",
"include/grpc/compression.h",
"include/grpc/grpc.h",
"include/grpc/status.h",
"include/grpc/census.h", "include/grpc/census.h",
"src/core/census/grpc_filter.h", "src/core/census/grpc_filter.h",
"src/core/channel/channel_args.h", "src/core/channel/channel_args.h",

@ -27,9 +27,9 @@
<contents> <contents>
<dir baseinstalldir="/" name="/"> <dir baseinstalldir="/" name="/">
<file baseinstalldir="/" name="config.m4" role="src" /> <file baseinstalldir="/" name="config.m4" role="src" />
<file baseinstalldir="/" name="src/php/README.md" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/CREDITS" role="src" /> <file baseinstalldir="/" name="src/php/ext/grpc/CREDITS" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/LICENSE" role="src" /> <file baseinstalldir="/" name="src/php/ext/grpc/LICENSE" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/README.md" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/byte_buffer.c" role="src" /> <file baseinstalldir="/" name="src/php/ext/grpc/byte_buffer.c" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/call.c" role="src" /> <file baseinstalldir="/" name="src/php/ext/grpc/call.c" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/call_credentials.c" role="src" /> <file baseinstalldir="/" name="src/php/ext/grpc/call_credentials.c" role="src" />
@ -147,17 +147,17 @@
<file baseinstalldir="/" name="src/core/support/tmpfile_win32.c" role="src" /> <file baseinstalldir="/" name="src/core/support/tmpfile_win32.c" role="src" />
<file baseinstalldir="/" name="src/core/support/wrap_memcpy.c" role="src" /> <file baseinstalldir="/" name="src/core/support/wrap_memcpy.c" role="src" />
<file baseinstalldir="/" name="include/grpc/grpc_security.h" role="src" /> <file baseinstalldir="/" name="include/grpc/grpc_security.h" role="src" />
<file baseinstalldir="/" name="include/grpc/byte_buffer.h" role="src" />
<file baseinstalldir="/" name="include/grpc/byte_buffer_reader.h" role="src" />
<file baseinstalldir="/" name="include/grpc/compression.h" role="src" />
<file baseinstalldir="/" name="include/grpc/grpc.h" role="src" />
<file baseinstalldir="/" name="include/grpc/status.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/byte_buffer.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/byte_buffer.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/compression_types.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/compression_types.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/connectivity_state.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/connectivity_state.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/grpc_types.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/grpc_types.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/propagation_bits.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/propagation_bits.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/status.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/status.h" role="src" />
<file baseinstalldir="/" name="include/grpc/byte_buffer.h" role="src" />
<file baseinstalldir="/" name="include/grpc/byte_buffer_reader.h" role="src" />
<file baseinstalldir="/" name="include/grpc/compression.h" role="src" />
<file baseinstalldir="/" name="include/grpc/grpc.h" role="src" />
<file baseinstalldir="/" name="include/grpc/status.h" role="src" />
<file baseinstalldir="/" name="include/grpc/census.h" role="src" /> <file baseinstalldir="/" name="include/grpc/census.h" role="src" />
<file baseinstalldir="/" name="src/core/census/grpc_filter.h" role="src" /> <file baseinstalldir="/" name="src/core/census/grpc_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/channel/channel_args.h" role="src" /> <file baseinstalldir="/" name="src/core/channel/channel_args.h" role="src" />

@ -108,8 +108,13 @@ if "linux" in sys.platform or "darwin" in sys.platform:
def cython_extensions(package_names, module_names, extra_sources, include_dirs, def cython_extensions(package_names, module_names, extra_sources, include_dirs,
libraries, define_macros, build_with_cython=False): libraries, define_macros, build_with_cython=False):
# Set compiler directives linetrace argument only if we care about tracing;
# this is due to Cython having different behavior between linetrace being
# False and linetrace being unset. See issue #5689.
cython_compiler_directives = {}
if ENABLE_CYTHON_TRACING: if ENABLE_CYTHON_TRACING:
define_macros = define_macros + [('CYTHON_TRACE_NOGIL', 1)] define_macros = define_macros + [('CYTHON_TRACE_NOGIL', 1)]
cython_compiler_directives['linetrace'] = True
file_extension = 'pyx' if build_with_cython else 'c' file_extension = 'pyx' if build_with_cython else 'c'
module_files = [os.path.join(PYTHON_STEM, module_files = [os.path.join(PYTHON_STEM,
name.replace('.', '/') + '.' + file_extension) name.replace('.', '/') + '.' + file_extension)
@ -129,7 +134,7 @@ def cython_extensions(package_names, module_names, extra_sources, include_dirs,
return Cython.Build.cythonize( return Cython.Build.cythonize(
extensions, extensions,
include_path=include_dirs, include_path=include_dirs,
compiler_directives={'linetrace': bool(ENABLE_CYTHON_TRACING)}) compiler_directives=cython_compiler_directives)
else: else:
return extensions return extensions
@ -154,6 +159,7 @@ INSTALL_REQUIRES = (
SETUP_REQUIRES = ( SETUP_REQUIRES = (
'sphinx>=1.3', 'sphinx>=1.3',
'sphinx_rtd_theme>=0.1.8'
) + INSTALL_REQUIRES ) + INSTALL_REQUIRES
COMMAND_CLASS = { COMMAND_CLASS = {

@ -165,7 +165,6 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
channel_data *chand = arg; channel_data *chand = arg;
grpc_lb_policy *lb_policy = NULL; grpc_lb_policy *lb_policy = NULL;
grpc_lb_policy *old_lb_policy; grpc_lb_policy *old_lb_policy;
grpc_resolver *old_resolver;
grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE; grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
int exit_idle = 0; int exit_idle = 0;
@ -201,28 +200,25 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
} }
if (iomgr_success && chand->resolver) { if (iomgr_success && chand->resolver) {
grpc_resolver *resolver = chand->resolver;
GRPC_RESOLVER_REF(resolver, "channel-next");
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state,
"new_lb+resolver"); "new_lb+resolver");
if (lb_policy != NULL) { if (lb_policy != NULL) {
watch_lb_policy(exec_ctx, chand, lb_policy, state); watch_lb_policy(exec_ctx, chand, lb_policy, state);
} }
gpr_mu_unlock(&chand->mu_config);
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver"); GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
grpc_resolver_next(exec_ctx, resolver, &chand->incoming_configuration, grpc_resolver_next(exec_ctx, chand->resolver,
&chand->incoming_configuration,
&chand->on_config_changed); &chand->on_config_changed);
GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel-next"); gpr_mu_unlock(&chand->mu_config);
} else { } else {
old_resolver = chand->resolver; if (chand->resolver != NULL) {
grpc_resolver_shutdown(exec_ctx, chand->resolver);
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL; chand->resolver = NULL;
}
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
GRPC_CHANNEL_FATAL_FAILURE, "resolver_gone"); GRPC_CHANNEL_FATAL_FAILURE, "resolver_gone");
gpr_mu_unlock(&chand->mu_config); gpr_mu_unlock(&chand->mu_config);
if (old_resolver != NULL) {
grpc_resolver_shutdown(exec_ctx, old_resolver);
GRPC_RESOLVER_UNREF(exec_ctx, old_resolver, "channel");
}
} }
if (exit_idle) { if (exit_idle) {
@ -247,7 +243,6 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel_element *elem,
grpc_transport_op *op) { grpc_transport_op *op) {
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
grpc_resolver *destroy_resolver = NULL;
grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL); grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
@ -279,7 +274,8 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
if (op->disconnect && chand->resolver != NULL) { if (op->disconnect && chand->resolver != NULL) {
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
GRPC_CHANNEL_FATAL_FAILURE, "disconnect"); GRPC_CHANNEL_FATAL_FAILURE, "disconnect");
destroy_resolver = chand->resolver; grpc_resolver_shutdown(exec_ctx, chand->resolver);
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL; chand->resolver = NULL;
if (chand->lb_policy != NULL) { if (chand->lb_policy != NULL) {
grpc_pollset_set_del_pollset_set(exec_ctx, grpc_pollset_set_del_pollset_set(exec_ctx,
@ -290,11 +286,6 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
} }
} }
gpr_mu_unlock(&chand->mu_config); gpr_mu_unlock(&chand->mu_config);
if (destroy_resolver) {
grpc_resolver_shutdown(exec_ctx, destroy_resolver);
GRPC_RESOLVER_UNREF(exec_ctx, destroy_resolver, "channel");
}
} }
typedef struct { typedef struct {

@ -174,18 +174,16 @@ static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING; holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
if (holder->connected_subchannel == NULL) { if (holder->connected_subchannel == NULL) {
fail_locked(exec_ctx, holder); fail_locked(exec_ctx, holder);
} else { } else if (1 == gpr_atm_acq_load(&holder->subchannel_call)) {
if (!gpr_atm_rel_cas( /* already cancelled before subchannel became ready */
&holder->subchannel_call, 0,
(gpr_atm)(uintptr_t)grpc_connected_subchannel_create_call(
exec_ctx, holder->connected_subchannel, holder->pollset))) {
GPR_ASSERT(gpr_atm_acq_load(&holder->subchannel_call) == 1);
/* if this cas fails, the call was cancelled before the pick completed */
fail_locked(exec_ctx, holder); fail_locked(exec_ctx, holder);
} else { } else {
gpr_atm_rel_store(
&holder->subchannel_call,
(gpr_atm)(uintptr_t)grpc_connected_subchannel_create_call(
exec_ctx, holder->connected_subchannel, holder->pollset));
retry_waiting_locked(exec_ctx, holder); retry_waiting_locked(exec_ctx, holder);
} }
}
gpr_mu_unlock(&holder->mu); gpr_mu_unlock(&holder->mu);
GRPC_CALL_STACK_UNREF(exec_ctx, holder->owning_call, "pick_subchannel"); GRPC_CALL_STACK_UNREF(exec_ctx, holder->owning_call, "pick_subchannel");
} }

@ -1,6 +1,6 @@
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2015-2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -53,7 +53,9 @@ void grpc_client_config_ref(grpc_client_config *c) { gpr_ref(&c->refs); }
void grpc_client_config_unref(grpc_exec_ctx *exec_ctx, grpc_client_config *c) { void grpc_client_config_unref(grpc_exec_ctx *exec_ctx, grpc_client_config *c) {
if (gpr_unref(&c->refs)) { if (gpr_unref(&c->refs)) {
if (c->lb_policy != NULL) {
GRPC_LB_POLICY_UNREF(exec_ctx, c->lb_policy, "client_config"); GRPC_LB_POLICY_UNREF(exec_ctx, c->lb_policy, "client_config");
}
gpr_free(c); gpr_free(c);
} }
} }

@ -387,8 +387,8 @@ static void pick_first_factory_unref(grpc_lb_policy_factory *factory) {}
static grpc_lb_policy *create_pick_first(grpc_lb_policy_factory *factory, static grpc_lb_policy *create_pick_first(grpc_lb_policy_factory *factory,
grpc_lb_policy_args *args) { grpc_lb_policy_args *args) {
if (args->num_subchannels == 0) return NULL;
pick_first_lb_policy *p = gpr_malloc(sizeof(*p)); pick_first_lb_policy *p = gpr_malloc(sizeof(*p));
GPR_ASSERT(args->num_subchannels > 0);
memset(p, 0, sizeof(*p)); memset(p, 0, sizeof(*p));
grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable); grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable);
p->subchannels = p->subchannels =

@ -41,6 +41,7 @@
#include "src/core/client_config/lb_policy_registry.h" #include "src/core/client_config/lb_policy_registry.h"
#include "src/core/iomgr/resolve_address.h" #include "src/core/iomgr/resolve_address.h"
#include "src/core/iomgr/timer.h"
#include "src/core/support/string.h" #include "src/core/support/string.h"
typedef struct { typedef struct {
@ -71,6 +72,9 @@ typedef struct {
grpc_client_config **target_config; grpc_client_config **target_config;
/** current (fully resolved) config */ /** current (fully resolved) config */
grpc_client_config *resolved_config; grpc_client_config *resolved_config;
/** retry timer */
bool have_retry_timer;
grpc_timer retry_timer;
} dns_resolver; } dns_resolver;
static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r); static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
@ -91,6 +95,9 @@ static const grpc_resolver_vtable dns_resolver_vtable = {
static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) { static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
dns_resolver *r = (dns_resolver *)resolver; dns_resolver *r = (dns_resolver *)resolver;
gpr_mu_lock(&r->mu); gpr_mu_lock(&r->mu);
if (r->have_retry_timer) {
grpc_timer_cancel(exec_ctx, &r->retry_timer);
}
if (r->next_completion != NULL) { if (r->next_completion != NULL) {
*r->target_config = NULL; *r->target_config = NULL;
grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL); grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
@ -125,6 +132,22 @@ static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
gpr_mu_unlock(&r->mu); gpr_mu_unlock(&r->mu);
} }
static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
bool success) {
dns_resolver *r = arg;
gpr_mu_lock(&r->mu);
r->have_retry_timer = false;
if (success) {
if (!r->resolving) {
dns_start_resolving_locked(r);
}
}
gpr_mu_unlock(&r->mu);
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "retry-timer");
}
static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg, static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
grpc_resolved_addresses *addresses) { grpc_resolved_addresses *addresses) {
dns_resolver *r = arg; dns_resolver *r = arg;
@ -133,29 +156,47 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
grpc_subchannel_args args; grpc_subchannel_args args;
grpc_lb_policy *lb_policy; grpc_lb_policy *lb_policy;
size_t i; size_t i;
if (addresses) { gpr_mu_lock(&r->mu);
GPR_ASSERT(r->resolving);
r->resolving = 0;
if (addresses != NULL) {
grpc_lb_policy_args lb_policy_args; grpc_lb_policy_args lb_policy_args;
config = grpc_client_config_create(); config = grpc_client_config_create();
subchannels = gpr_malloc(sizeof(grpc_subchannel *) * addresses->naddrs); subchannels = gpr_malloc(sizeof(grpc_subchannel *) * addresses->naddrs);
size_t naddrs = 0;
for (i = 0; i < addresses->naddrs; i++) { for (i = 0; i < addresses->naddrs; i++) {
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
args.addr = (struct sockaddr *)(addresses->addrs[i].addr); args.addr = (struct sockaddr *)(addresses->addrs[i].addr);
args.addr_len = (size_t)addresses->addrs[i].len; args.addr_len = (size_t)addresses->addrs[i].len;
subchannels[i] = grpc_subchannel_factory_create_subchannel( grpc_subchannel *subchannel = grpc_subchannel_factory_create_subchannel(
exec_ctx, r->subchannel_factory, &args); exec_ctx, r->subchannel_factory, &args);
if (subchannel != NULL) {
subchannels[naddrs++] = subchannel;
}
} }
memset(&lb_policy_args, 0, sizeof(lb_policy_args)); memset(&lb_policy_args, 0, sizeof(lb_policy_args));
lb_policy_args.subchannels = subchannels; lb_policy_args.subchannels = subchannels;
lb_policy_args.num_subchannels = addresses->naddrs; lb_policy_args.num_subchannels = naddrs;
lb_policy = grpc_lb_policy_create(r->lb_policy_name, &lb_policy_args); lb_policy = grpc_lb_policy_create(r->lb_policy_name, &lb_policy_args);
if (lb_policy != NULL) {
grpc_client_config_set_lb_policy(config, lb_policy); grpc_client_config_set_lb_policy(config, lb_policy);
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction"); GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
}
grpc_resolved_addresses_destroy(addresses); grpc_resolved_addresses_destroy(addresses);
gpr_free(subchannels); gpr_free(subchannels);
} else {
int retry_seconds = 15;
gpr_log(GPR_DEBUG, "dns resolution failed: retrying in %d seconds",
retry_seconds);
GPR_ASSERT(!r->have_retry_timer);
r->have_retry_timer = true;
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
GRPC_RESOLVER_REF(&r->base, "retry-timer");
grpc_timer_init(
exec_ctx, &r->retry_timer,
gpr_time_add(now, gpr_time_from_seconds(retry_seconds, GPR_TIMESPAN)),
dns_on_retry_timer, r, now);
} }
gpr_mu_lock(&r->mu);
GPR_ASSERT(r->resolving);
r->resolving = 0;
if (r->resolved_config) { if (r->resolved_config) {
grpc_client_config_unref(exec_ctx, r->resolved_config); grpc_client_config_unref(exec_ctx, r->resolved_config);
} }

@ -505,7 +505,8 @@ void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx,
elem->filter->start_transport_op(exec_ctx, elem, &op); elem->filter->start_transport_op(exec_ctx, elem, &op);
} }
static void publish_transport(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) { static void publish_transport_locked(grpc_exec_ctx *exec_ctx,
grpc_subchannel *c) {
size_t channel_stack_size; size_t channel_stack_size;
grpc_connected_subchannel *con; grpc_connected_subchannel *con;
grpc_channel_stack *stk; grpc_channel_stack *stk;
@ -541,8 +542,6 @@ static void publish_transport(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
grpc_closure_init(&sw_subchannel->closure, subchannel_on_child_state_changed, grpc_closure_init(&sw_subchannel->closure, subchannel_on_child_state_changed,
sw_subchannel); sw_subchannel);
gpr_mu_lock(&c->mu);
if (c->disconnected) { if (c->disconnected) {
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
gpr_free(sw_subchannel); gpr_free(sw_subchannel);
@ -575,7 +574,6 @@ static void publish_transport(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
grpc_connectivity_state_set(exec_ctx, &c->state_tracker, GRPC_CHANNEL_READY, grpc_connectivity_state_set(exec_ctx, &c->state_tracker, GRPC_CHANNEL_READY,
"connected"); "connected");
gpr_mu_unlock(&c->mu);
gpr_free((void *)filters); gpr_free((void *)filters);
} }
@ -644,21 +642,23 @@ static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
bool iomgr_success) { bool iomgr_success) {
grpc_subchannel *c = arg; grpc_subchannel *c = arg;
GRPC_SUBCHANNEL_WEAK_REF(c, "connected");
gpr_mu_lock(&c->mu);
if (c->connecting_result.transport != NULL) { if (c->connecting_result.transport != NULL) {
publish_transport(exec_ctx, c); publish_transport_locked(exec_ctx, c);
} else if (c->disconnected) { } else if (c->disconnected) {
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
} else { } else {
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
gpr_mu_lock(&c->mu);
GPR_ASSERT(!c->have_alarm); GPR_ASSERT(!c->have_alarm);
c->have_alarm = 1; c->have_alarm = 1;
grpc_connectivity_state_set(exec_ctx, &c->state_tracker, grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_CHANNEL_TRANSIENT_FAILURE,
"connect_failed"); "connect_failed");
grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now); grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now);
gpr_mu_unlock(&c->mu);
} }
gpr_mu_unlock(&c->mu);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
} }
static gpr_timespec compute_connect_deadline(grpc_subchannel *c) { static gpr_timespec compute_connect_deadline(grpc_subchannel *c) {

@ -34,9 +34,12 @@
#include "src/core/iomgr/exec_ctx.h" #include "src/core/iomgr/exec_ctx.h"
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd.h>
#include "src/core/profiling/timers.h" #include "src/core/profiling/timers.h"
#ifndef GRPC_EXECUTION_CONTEXT_SANITIZER
bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) { bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) {
bool did_something = 0; bool did_something = 0;
GPR_TIMER_BEGIN("grpc_exec_ctx_flush", 0); GPR_TIMER_BEGIN("grpc_exec_ctx_flush", 0);
@ -74,3 +77,75 @@ void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
GPR_ASSERT(offload_target_or_null == NULL); GPR_ASSERT(offload_target_or_null == NULL);
grpc_closure_list_move(list, &exec_ctx->closure_list); grpc_closure_list_move(list, &exec_ctx->closure_list);
} }
void grpc_exec_ctx_global_init(void) {}
void grpc_exec_ctx_global_shutdown(void) {}
#else
static gpr_mu g_mu;
static gpr_cv g_cv;
static int g_threads = 0;
static void run_closure(void *arg) {
grpc_closure *closure = arg;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
closure->cb(&exec_ctx, closure->cb_arg, (closure->final_data & 1) != 0);
grpc_exec_ctx_finish(&exec_ctx);
gpr_mu_lock(&g_mu);
if (--g_threads == 0) {
gpr_cv_signal(&g_cv);
}
gpr_mu_unlock(&g_mu);
}
static void start_closure(grpc_closure *closure) {
gpr_thd_id id;
gpr_mu_lock(&g_mu);
g_threads++;
gpr_mu_unlock(&g_mu);
gpr_thd_new(&id, run_closure, closure, NULL);
}
bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) { return false; }
void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) {}
void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
bool success,
grpc_workqueue *offload_target_or_null) {
GPR_ASSERT(offload_target_or_null == NULL);
if (closure == NULL) return;
closure->final_data = success;
start_closure(closure);
}
void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
grpc_closure_list *list,
grpc_workqueue *offload_target_or_null) {
GPR_ASSERT(offload_target_or_null == NULL);
if (list == NULL) return;
grpc_closure *p = list->head;
while (p) {
grpc_closure *start = p;
p = grpc_closure_next(start);
start_closure(start);
}
grpc_closure_list r = GRPC_CLOSURE_LIST_INIT;
*list = r;
}
void grpc_exec_ctx_global_init(void) {
gpr_mu_init(&g_mu);
gpr_cv_init(&g_cv);
}
void grpc_exec_ctx_global_shutdown(void) {
gpr_mu_lock(&g_mu);
while (g_threads != 0) {
gpr_cv_wait(&g_cv, &g_mu, gpr_inf_future(GPR_CLOCK_REALTIME));
}
gpr_mu_unlock(&g_mu);
gpr_mu_destroy(&g_mu);
gpr_cv_destroy(&g_cv);
}
#endif

@ -36,6 +36,14 @@
#include "src/core/iomgr/closure.h" #include "src/core/iomgr/closure.h"
/* #define GRPC_EXECUTION_CONTEXT_SANITIZER 1 */
/** A workqueue represents a list of work to be executed asynchronously.
Forward declared here to avoid a circular dependency with workqueue.h. */
struct grpc_workqueue;
typedef struct grpc_workqueue grpc_workqueue;
#ifndef GRPC_EXECUTION_CONTEXT_SANITIZER
/** Execution context. /** Execution context.
* A bag of data that collects information along a callstack. * A bag of data that collects information along a callstack.
* Generally created at public API entry points, and passed down as * Generally created at public API entry points, and passed down as
@ -57,13 +65,15 @@ struct grpc_exec_ctx {
grpc_closure_list closure_list; grpc_closure_list closure_list;
}; };
/** A workqueue represents a list of work to be executed asynchronously.
Forward declared here to avoid a circular dependency with workqueue.h. */
struct grpc_workqueue;
typedef struct grpc_workqueue grpc_workqueue;
#define GRPC_EXEC_CTX_INIT \ #define GRPC_EXEC_CTX_INIT \
{ GRPC_CLOSURE_LIST_INIT } { GRPC_CLOSURE_LIST_INIT }
#else
struct grpc_exec_ctx {
int unused;
};
#define GRPC_EXEC_CTX_INIT \
{ 0 }
#endif
/** Flush any work that has been enqueued onto this grpc_exec_ctx. /** Flush any work that has been enqueued onto this grpc_exec_ctx.
* Caller must guarantee that no interfering locks are held. * Caller must guarantee that no interfering locks are held.
@ -82,4 +92,7 @@ void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
grpc_closure_list *list, grpc_closure_list *list,
grpc_workqueue *offload_target_or_null); grpc_workqueue *offload_target_or_null);
void grpc_exec_ctx_global_init(void);
void grpc_exec_ctx_global_shutdown(void);
#endif #endif

@ -71,7 +71,8 @@ static DWORD deadline_to_millis_timeout(gpr_timespec deadline,
timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN))); timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN)));
} }
void grpc_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline) { grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx,
gpr_timespec deadline) {
BOOL success; BOOL success;
DWORD bytes = 0; DWORD bytes = 0;
DWORD flags = 0; DWORD flags = 0;
@ -84,14 +85,14 @@ void grpc_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline) {
g_iocp, &bytes, &completion_key, &overlapped, g_iocp, &bytes, &completion_key, &overlapped,
deadline_to_millis_timeout(deadline, gpr_now(deadline.clock_type))); deadline_to_millis_timeout(deadline, gpr_now(deadline.clock_type)));
if (success == 0 && overlapped == NULL) { if (success == 0 && overlapped == NULL) {
return; return GRPC_IOCP_WORK_TIMEOUT;
} }
GPR_ASSERT(completion_key && overlapped); GPR_ASSERT(completion_key && overlapped);
if (overlapped == &g_iocp_custom_overlap) { if (overlapped == &g_iocp_custom_overlap) {
gpr_atm_full_fetch_add(&g_custom_events, -1); gpr_atm_full_fetch_add(&g_custom_events, -1);
if (completion_key == (ULONG_PTR)&g_iocp_kick_token) { if (completion_key == (ULONG_PTR)&g_iocp_kick_token) {
/* We were awoken from a kick. */ /* We were awoken from a kick. */
return; return GRPC_IOCP_WORK_KICK;
} }
gpr_log(GPR_ERROR, "Unknown custom completion key."); gpr_log(GPR_ERROR, "Unknown custom completion key.");
abort(); abort();
@ -121,6 +122,7 @@ void grpc_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline) {
} }
gpr_mu_unlock(&socket->state_mu); gpr_mu_unlock(&socket->state_mu);
grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL); grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
return GRPC_IOCP_WORK_WORK;
} }
void grpc_iocp_init(void) { void grpc_iocp_init(void) {
@ -140,10 +142,12 @@ void grpc_iocp_kick(void) {
void grpc_iocp_flush(void) { void grpc_iocp_flush(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_iocp_work_status work_status;
do { do {
grpc_iocp_work(&exec_ctx, gpr_inf_past(GPR_CLOCK_MONOTONIC)); work_status = grpc_iocp_work(&exec_ctx, gpr_inf_past(GPR_CLOCK_MONOTONIC));
} while (grpc_exec_ctx_flush(&exec_ctx)); } while (work_status == GRPC_IOCP_WORK_KICK ||
grpc_exec_ctx_flush(&exec_ctx));
} }
void grpc_iocp_shutdown(void) { void grpc_iocp_shutdown(void) {

@ -1,6 +1,6 @@
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2015-2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -38,7 +38,14 @@
#include "src/core/iomgr/socket_windows.h" #include "src/core/iomgr/socket_windows.h"
void grpc_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline); typedef enum {
GRPC_IOCP_WORK_WORK,
GRPC_IOCP_WORK_TIMEOUT,
GRPC_IOCP_WORK_KICK
} grpc_iocp_work_status;
grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx,
gpr_timespec deadline);
void grpc_iocp_init(void); void grpc_iocp_init(void);
void grpc_iocp_kick(void); void grpc_iocp_kick(void);
void grpc_iocp_flush(void); void grpc_iocp_flush(void);

@ -43,6 +43,7 @@
#include <grpc/support/thd.h> #include <grpc/support/thd.h>
#include <grpc/support/useful.h> #include <grpc/support/useful.h>
#include "src/core/iomgr/exec_ctx.h"
#include "src/core/iomgr/iomgr_internal.h" #include "src/core/iomgr/iomgr_internal.h"
#include "src/core/iomgr/timer.h" #include "src/core/iomgr/timer.h"
#include "src/core/support/env.h" #include "src/core/support/env.h"
@ -57,6 +58,7 @@ void grpc_iomgr_init(void) {
g_shutdown = 0; g_shutdown = 0;
gpr_mu_init(&g_mu); gpr_mu_init(&g_mu);
gpr_cv_init(&g_rcv); gpr_cv_init(&g_rcv);
grpc_exec_ctx_global_init();
grpc_timer_list_init(gpr_now(GPR_CLOCK_MONOTONIC)); grpc_timer_list_init(gpr_now(GPR_CLOCK_MONOTONIC));
g_root_object.next = g_root_object.prev = &g_root_object; g_root_object.next = g_root_object.prev = &g_root_object;
g_root_object.name = "root"; g_root_object.name = "root";
@ -136,6 +138,7 @@ void grpc_iomgr_shutdown(void) {
gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_mu);
grpc_iomgr_platform_shutdown(); grpc_iomgr_platform_shutdown();
grpc_exec_ctx_global_shutdown();
gpr_mu_destroy(&g_mu); gpr_mu_destroy(&g_mu);
gpr_cv_destroy(&g_rcv); gpr_cv_destroy(&g_rcv);
} }

@ -55,7 +55,7 @@ typedef struct grpc_pollset_worker grpc_pollset_worker;
size_t grpc_pollset_size(void); size_t grpc_pollset_size(void);
void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu); void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu);
/* Begin shutting down the pollset, and call closure when done. /* Begin shutting down the pollset, and call closure when done.
* GRPC_POLLSET_MU(pollset) must be held */ * pollset's mutex must be held */
void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_closure *closure); grpc_closure *closure);
/** Reset the pollset to its initial state (perhaps with some cached objects); /** Reset the pollset to its initial state (perhaps with some cached objects);
@ -66,16 +66,16 @@ void grpc_pollset_destroy(grpc_pollset *pollset);
/* Do some work on a pollset. /* Do some work on a pollset.
May involve invoking asynchronous callbacks, or actually polling file May involve invoking asynchronous callbacks, or actually polling file
descriptors. descriptors.
Requires GRPC_POLLSET_MU(pollset) locked. Requires pollset's mutex locked.
May unlock GRPC_POLLSET_MU(pollset) during its execution. May unlock its mutex during its execution.
worker is a (platform-specific) handle that can be used to wake up worker is a (platform-specific) handle that can be used to wake up
from grpc_pollset_work before any events are received and before the timeout from grpc_pollset_work before any events are received and before the timeout
has expired. It is both initialized and destroyed by grpc_pollset_work. has expired. It is both initialized and destroyed by grpc_pollset_work.
Initialization of worker is guaranteed to occur BEFORE the Initialization of worker is guaranteed to occur BEFORE the
GRPC_POLLSET_MU(pollset) is released for the first time by pollset's mutex is released for the first time by grpc_pollset_work
grpc_pollset_work, and it is guaranteed that GRPC_POLLSET_MU(pollset) will and it is guaranteed that it will not be released by grpc_pollset_work
not be released by grpc_pollset_work AFTER worker has been destroyed. AFTER worker has been destroyed.
Tries not to block past deadline. Tries not to block past deadline.
May call grpc_closure_list_run on grpc_closure_list, without holding the May call grpc_closure_list_run on grpc_closure_list, without holding the

@ -1,6 +1,6 @@
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2015-2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -66,7 +66,7 @@ void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addresses);
/* Resolve addr in a blocking fashion. Returns NULL on failure. On success, /* Resolve addr in a blocking fashion. Returns NULL on failure. On success,
result must be freed with grpc_resolved_addresses_destroy. */ result must be freed with grpc_resolved_addresses_destroy. */
grpc_resolved_addresses *grpc_blocking_resolve_address( extern grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
const char *addr, const char *default_port); const char *name, const char *default_port);
#endif /* GRPC_INTERNAL_CORE_IOMGR_RESOLVE_ADDRESS_H */ #endif /* GRPC_INTERNAL_CORE_IOMGR_RESOLVE_ADDRESS_H */

@ -34,18 +34,13 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#ifdef GPR_POSIX_SOCKET #ifdef GPR_POSIX_SOCKET
#include "src/core/iomgr/sockaddr.h"
#include "src/core/iomgr/resolve_address.h" #include "src/core/iomgr/resolve_address.h"
#include "src/core/iomgr/sockaddr.h"
#include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/un.h> #include <sys/un.h>
#include <string.h>
#include "src/core/iomgr/executor.h"
#include "src/core/iomgr/iomgr_internal.h"
#include "src/core/iomgr/sockaddr_utils.h"
#include "src/core/support/block_annotate.h"
#include "src/core/support/string.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/host_port.h> #include <grpc/support/host_port.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
@ -53,6 +48,11 @@
#include <grpc/support/thd.h> #include <grpc/support/thd.h>
#include <grpc/support/time.h> #include <grpc/support/time.h>
#include <grpc/support/useful.h> #include <grpc/support/useful.h>
#include "src/core/iomgr/executor.h"
#include "src/core/iomgr/iomgr_internal.h"
#include "src/core/iomgr/sockaddr_utils.h"
#include "src/core/support/block_annotate.h"
#include "src/core/support/string.h"
typedef struct { typedef struct {
char *name; char *name;
@ -62,7 +62,7 @@ typedef struct {
void *arg; void *arg;
} request; } request;
grpc_resolved_addresses *grpc_blocking_resolve_address( static grpc_resolved_addresses *blocking_resolve_address_impl(
const char *name, const char *default_port) { const char *name, const char *default_port) {
struct addrinfo hints; struct addrinfo hints;
struct addrinfo *result = NULL, *resp; struct addrinfo *result = NULL, *resp;
@ -150,6 +150,9 @@ done:
return addrs; return addrs;
} }
grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
const char *name, const char *default_port) = blocking_resolve_address_impl;
/* Callback to be passed to grpc_executor to asynch-ify /* Callback to be passed to grpc_executor to asynch-ify
* grpc_blocking_resolve_address */ * grpc_blocking_resolve_address */
static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) { static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) {

@ -34,17 +34,12 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#ifdef GPR_WINSOCK_SOCKET #ifdef GPR_WINSOCK_SOCKET
#include "src/core/iomgr/sockaddr.h"
#include "src/core/iomgr/resolve_address.h" #include "src/core/iomgr/resolve_address.h"
#include "src/core/iomgr/sockaddr.h"
#include <sys/types.h>
#include <string.h> #include <string.h>
#include <sys/types.h>
#include "src/core/iomgr/executor.h"
#include "src/core/iomgr/iomgr_internal.h"
#include "src/core/iomgr/sockaddr_utils.h"
#include "src/core/support/block_annotate.h"
#include "src/core/support/string.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/host_port.h> #include <grpc/support/host_port.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
@ -52,6 +47,11 @@
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include <grpc/support/thd.h> #include <grpc/support/thd.h>
#include <grpc/support/time.h> #include <grpc/support/time.h>
#include "src/core/iomgr/executor.h"
#include "src/core/iomgr/iomgr_internal.h"
#include "src/core/iomgr/sockaddr_utils.h"
#include "src/core/support/block_annotate.h"
#include "src/core/support/string.h"
typedef struct { typedef struct {
char *name; char *name;
@ -61,7 +61,7 @@ typedef struct {
void *arg; void *arg;
} request; } request;
grpc_resolved_addresses *grpc_blocking_resolve_address( static grpc_resolved_addresses *blocking_resolve_address_impl(
const char *name, const char *default_port) { const char *name, const char *default_port) {
struct addrinfo hints; struct addrinfo hints;
struct addrinfo *result = NULL, *resp; struct addrinfo *result = NULL, *resp;
@ -133,6 +133,9 @@ done:
return addrs; return addrs;
} }
grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
const char *name, const char *default_port) = blocking_resolve_address_impl;
/* Callback to be passed to grpc_executor to asynch-ify /* Callback to be passed to grpc_executor to asynch-ify
* grpc_blocking_resolve_address */ * grpc_blocking_resolve_address */
static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) { static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) {

@ -240,8 +240,7 @@ static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx,
sp->shutting_down = 0; sp->shutting_down = 0;
gpr_mu_lock(&sp->server->mu); gpr_mu_lock(&sp->server->mu);
GPR_ASSERT(sp->server->active_ports > 0); GPR_ASSERT(sp->server->active_ports > 0);
if (0 == --sp->server->active_ports && if (0 == --sp->server->active_ports) {
sp->server->shutdown_complete != NULL) {
notify = 1; notify = 1;
} }
gpr_mu_unlock(&sp->server->mu); gpr_mu_unlock(&sp->server->mu);

@ -33,11 +33,11 @@
#include "src/core/iomgr/timer.h" #include "src/core/iomgr/timer.h"
#include "src/core/iomgr/timer_heap.h"
#include "src/core/iomgr/time_averaged_stats.h"
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/sync.h> #include <grpc/support/sync.h>
#include <grpc/support/useful.h> #include <grpc/support/useful.h>
#include "src/core/iomgr/time_averaged_stats.h"
#include "src/core/iomgr/timer_heap.h"
#define INVALID_HEAP_INDEX 0xffffffffu #define INVALID_HEAP_INDEX 0xffffffffu
@ -330,6 +330,18 @@ static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now,
gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_mu);
gpr_mu_unlock(&g_checker_mu); gpr_mu_unlock(&g_checker_mu);
} else if (next != NULL) {
/* TODO(ctiller): this forces calling code to do an short poll, and
then retry the timer check (because this time through the timer list was
contended).
We could reduce the cost here dramatically by keeping a count of how many
currently active pollers got through the uncontended case above
successfully, and waking up other pollers IFF that count drops to zero.
Once that count is in place, this entire else branch could disappear. */
*next = gpr_time_min(
*next, gpr_time_add(now, gpr_time_from_millis(1, GPR_TIMESPAN)));
} }
return (int)n; return (int)n;

@ -96,7 +96,6 @@ void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer);
*next is never guaranteed to be updated on any given execution; however, *next is never guaranteed to be updated on any given execution; however,
with high probability at least one thread in the system will see an update with high probability at least one thread in the system will see an update
at any time slice. */ at any time slice. */
bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now, bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now,
gpr_timespec *next); gpr_timespec *next);
void grpc_timer_list_init(gpr_timespec now); void grpc_timer_list_init(gpr_timespec now);

@ -1,6 +1,6 @@
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2015-2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -46,7 +46,7 @@
static void adjust_upwards(grpc_timer **first, uint32_t i, grpc_timer *t) { static void adjust_upwards(grpc_timer **first, uint32_t i, grpc_timer *t) {
while (i > 0) { while (i > 0) {
uint32_t parent = (uint32_t)(((int)i - 1) / 2); uint32_t parent = (uint32_t)(((int)i - 1) / 2);
if (gpr_time_cmp(first[parent]->deadline, t->deadline) >= 0) break; if (gpr_time_cmp(first[parent]->deadline, t->deadline) <= 0) break;
first[i] = first[parent]; first[i] = first[parent];
first[i]->heap_index = i; first[i]->heap_index = i;
i = parent; i = parent;
@ -62,16 +62,14 @@ static void adjust_downwards(grpc_timer **first, uint32_t i, uint32_t length,
grpc_timer *t) { grpc_timer *t) {
for (;;) { for (;;) {
uint32_t left_child = 1u + 2u * i; uint32_t left_child = 1u + 2u * i;
uint32_t right_child;
uint32_t next_i;
if (left_child >= length) break; if (left_child >= length) break;
right_child = left_child + 1; uint32_t right_child = left_child + 1;
next_i = right_child < length && uint32_t next_i = right_child < length &&
gpr_time_cmp(first[left_child]->deadline, gpr_time_cmp(first[left_child]->deadline,
first[right_child]->deadline) < 0 first[right_child]->deadline) > 0
? right_child ? right_child
: left_child; : left_child;
if (gpr_time_cmp(t->deadline, first[next_i]->deadline) >= 0) break; if (gpr_time_cmp(t->deadline, first[next_i]->deadline) <= 0) break;
first[i] = first[next_i]; first[i] = first[next_i];
first[i]->heap_index = i; first[i]->heap_index = i;
i = next_i; i = next_i;
@ -95,7 +93,7 @@ static void maybe_shrink(grpc_timer_heap *heap) {
static void note_changed_priority(grpc_timer_heap *heap, grpc_timer *timer) { static void note_changed_priority(grpc_timer_heap *heap, grpc_timer *timer) {
uint32_t i = timer->heap_index; uint32_t i = timer->heap_index;
uint32_t parent = (uint32_t)(((int)i - 1) / 2); uint32_t parent = (uint32_t)(((int)i - 1) / 2);
if (gpr_time_cmp(heap->timers[parent]->deadline, timer->deadline) < 0) { if (gpr_time_cmp(heap->timers[parent]->deadline, timer->deadline) > 0) {
adjust_upwards(heap->timers, i, timer); adjust_upwards(heap->timers, i, timer);
} else { } else {
adjust_downwards(heap->timers, i, heap->timer_count, timer); adjust_downwards(heap->timers, i, heap->timer_count, timer);

@ -106,7 +106,7 @@ void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {
if (grpc_closure_list_empty(workqueue->closure_list)) { if (grpc_closure_list_empty(workqueue->closure_list)) {
grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd); grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd);
} }
grpc_closure_list_move(&exec_ctx->closure_list, &workqueue->closure_list); grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL);
gpr_mu_unlock(&workqueue->mu); gpr_mu_unlock(&workqueue->mu);
} }
@ -122,7 +122,7 @@ static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
gpr_free(workqueue); gpr_free(workqueue);
} else { } else {
gpr_mu_lock(&workqueue->mu); gpr_mu_lock(&workqueue->mu);
grpc_closure_list_move(&workqueue->closure_list, &exec_ctx->closure_list); grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL);
grpc_wakeup_fd_consume_wakeup(&workqueue->wakeup_fd); grpc_wakeup_fd_consume_wakeup(&workqueue->wakeup_fd);
gpr_mu_unlock(&workqueue->mu); gpr_mu_unlock(&workqueue->mu);
grpc_fd_notify_on_read(exec_ctx, workqueue->wakeup_read_fd, grpc_fd_notify_on_read(exec_ctx, workqueue->wakeup_read_fd,

@ -1,6 +1,6 @@
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2015-2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -87,4 +87,4 @@ void *gpr_malloc_aligned(size_t size, size_t alignment_log) {
return (void *)ret; return (void *)ret;
} }
void gpr_free_aligned(void *ptr) { free(((void **)ptr)[-1]); } void gpr_free_aligned(void *ptr) { gpr_free(((void **)ptr)[-1]); }

@ -86,7 +86,7 @@ struct grpc_completion_queue {
#define POLLSET_FROM_CQ(cq) ((grpc_pollset *)(cq + 1)) #define POLLSET_FROM_CQ(cq) ((grpc_pollset *)(cq + 1))
static gpr_mu g_freelist_mu; static gpr_mu g_freelist_mu;
grpc_completion_queue *g_freelist; static grpc_completion_queue *g_freelist;
static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *cc, static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *cc,
bool success); bool success);

@ -851,11 +851,13 @@ static void perform_stream_op_locked(
if (stream_global->write_closed) { if (stream_global->write_closed) {
grpc_chttp2_complete_closure_step( grpc_chttp2_complete_closure_step(
exec_ctx, &stream_global->send_message_finished, 0); exec_ctx, &stream_global->send_message_finished, 0);
} else if (stream_global->id != 0) { } else {
stream_global->send_message = op->send_message; stream_global->send_message = op->send_message;
if (stream_global->id != 0) {
grpc_chttp2_become_writable(transport_global, stream_global); grpc_chttp2_become_writable(transport_global, stream_global);
} }
} }
}
if (op->send_trailing_metadata != NULL) { if (op->send_trailing_metadata != NULL) {
GPR_ASSERT(stream_global->send_trailing_metadata_finished == NULL); GPR_ASSERT(stream_global->send_trailing_metadata_finished == NULL);

@ -1,6 +1,6 @@
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2015-2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -33,9 +33,18 @@
#include "src/core/tsi/ssl_transport_security.h" #include "src/core/tsi/ssl_transport_security.h"
#include <grpc/support/port_platform.h>
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
/* TODO(jboeuf): refactor inet_ntop into a portability header. */
#ifdef GPR_WINSOCK_SOCKET
#include <ws2tcpip.h>
#else
#include <arpa/inet.h>
#endif
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/sync.h> #include <grpc/support/sync.h>
#include <grpc/support/thd.h> #include <grpc/support/thd.h>
@ -197,13 +206,16 @@ static void ssl_info_callback(const SSL *ssl, int where, int ret) {
} }
/* Returns 1 if name looks like an IP address, 0 otherwise. /* Returns 1 if name looks like an IP address, 0 otherwise.
This is a very rough heuristic as it does not handle IPV6 or things like: This is a very rough heuristic, and only handles IPv6 in hexadecimal form. */
0300.0250.00.01, 0xC0.0Xa8.0x0.0x1, 000030052000001, 0xc0.052000001 */
static int looks_like_ip_address(const char *name) { static int looks_like_ip_address(const char *name) {
size_t i; size_t i;
size_t dot_count = 0; size_t dot_count = 0;
size_t num_size = 0; size_t num_size = 0;
for (i = 0; i < strlen(name); i++) { for (i = 0; i < strlen(name); i++) {
if (name[i] == ':') {
/* IPv6 Address in hexadecimal form, : is not allowed in DNS names. */
return 1;
}
if (name[i] >= '0' && name[i] <= '9') { if (name[i] >= '0' && name[i] <= '9') {
if (num_size > 3) return 0; if (num_size > 3) return 0;
num_size++; num_size++;
@ -296,21 +308,44 @@ static tsi_result add_subject_alt_names_properties_to_peer(
sk_GENERAL_NAME_value(subject_alt_names, TSI_SIZE_AS_SIZE(i)); sk_GENERAL_NAME_value(subject_alt_names, TSI_SIZE_AS_SIZE(i));
/* Filter out the non-dns entries names. */ /* Filter out the non-dns entries names. */
if (subject_alt_name->type == GEN_DNS) { if (subject_alt_name->type == GEN_DNS) {
unsigned char *dns_name = NULL; unsigned char *name = NULL;
int dns_name_size = int name_size;
ASN1_STRING_to_UTF8(&dns_name, subject_alt_name->d.dNSName); name_size = ASN1_STRING_to_UTF8(&name, subject_alt_name->d.dNSName);
if (dns_name_size < 0) { if (name_size < 0) {
gpr_log(GPR_ERROR, "Could not get utf8 from asn1 string."); gpr_log(GPR_ERROR, "Could not get utf8 from asn1 string.");
result = TSI_INTERNAL_ERROR; result = TSI_INTERNAL_ERROR;
break; break;
} }
result = tsi_construct_string_peer_property( result = tsi_construct_string_peer_property(
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, (const char *)name,
(const char *)dns_name, (size_t)dns_name_size, (size_t)name_size, &peer->properties[peer->property_count++]);
OPENSSL_free(name);
} else if (subject_alt_name->type == GEN_IPADD) {
char ntop_buf[INET6_ADDRSTRLEN];
int af;
if (subject_alt_name->d.iPAddress->length == 4) {
af = AF_INET;
} else if (subject_alt_name->d.iPAddress->length == 16) {
af = AF_INET6;
} else {
gpr_log(GPR_ERROR, "SAN IP Address contained invalid IP");
result = TSI_INTERNAL_ERROR;
break;
}
const char *name = inet_ntop(af, subject_alt_name->d.iPAddress->data,
ntop_buf, INET6_ADDRSTRLEN);
if (name == NULL) {
gpr_log(GPR_ERROR, "Could not get IP string from asn1 octet.");
result = TSI_INTERNAL_ERROR;
break;
}
result = tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, name,
&peer->properties[peer->property_count++]); &peer->properties[peer->property_count++]);
OPENSSL_free(dns_name);
if (result != TSI_OK) break;
} }
if (result != TSI_OK) break;
} }
return result; return result;
} }
@ -1436,9 +1471,7 @@ int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name) {
size_t i = 0; size_t i = 0;
size_t san_count = 0; size_t san_count = 0;
const tsi_peer_property *cn_property = NULL; const tsi_peer_property *cn_property = NULL;
int like_ip = looks_like_ip_address(name);
/* For now reject what looks like an IP address. */
if (looks_like_ip_address(name)) return 0;
/* Check the SAN first. */ /* Check the SAN first. */
for (i = 0; i < peer->property_count; i++) { for (i = 0; i < peer->property_count; i++) {
@ -1447,8 +1480,15 @@ int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name) {
if (strcmp(property->name, if (strcmp(property->name,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) { TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
san_count++; san_count++;
if (does_entry_match_name(property->value.data, property->value.length,
name)) { if (!like_ip && does_entry_match_name(property->value.data,
property->value.length, name)) {
return 1;
} else if (like_ip &&
strncmp(name, property->value.data, property->value.length) ==
0 &&
strlen(name) == property->value.length) {
/* IP Addresses are exact matches only. */
return 1; return 1;
} }
} else if (strcmp(property->name, } else if (strcmp(property->name,
@ -1457,8 +1497,8 @@ int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name) {
} }
} }
/* If there's no SAN, try the CN. */ /* If there's no SAN, try the CN, but only if its not like an IP Address */
if (san_count == 0 && cn_property != NULL) { if (san_count == 0 && cn_property != NULL && !like_ip) {
if (does_entry_match_name(cn_property->value.data, if (does_entry_match_name(cn_property->value.data,
cn_property->value.length, name)) { cn_property->value.length, name)) {
return 1; return 1;

@ -1,6 +1,6 @@
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2015-2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -162,8 +162,7 @@ void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory *self);
Still TODO(jboeuf): Still TODO(jboeuf):
- handle mixed case. - handle mixed case.
- handle %encoded chars. - handle %encoded chars.
- handle public suffix wildchar more strictly (e.g. *.co.uk) - handle public suffix wildchar more strictly (e.g. *.co.uk) */
- handle IP addresses in SAN. */
int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name); int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name);
#ifdef __cplusplus #ifdef __cplusplus

@ -6,3 +6,77 @@ This directory contains source code for C++ implementation of gRPC.
#Status #Status
Beta Beta
#Pre-requisites
##Linux
```sh
$ [sudo] apt-get install build-essential autoconf libtool
```
##Mac OSX
For a Mac system, git is not available by default. You will first need to
install Xcode from the Mac AppStore and then run the following command from a
terminal:
```sh
$ [sudo] xcode-select --install
```
##Protoc
By default gRPC uses [protocol buffers](https://github.com/google/protobuf),
you will need the `protoc` compiler to generate stub server and client code.
If you compile gRPC from source, as described below, this also installs the
`protoc` compiler.
If it hasn't been installed, you can run the following commands to install it.
```sh
$ cd grpc/third_party/protobuf
$ sudo make install # 'make' should have been run by core grpc
```
Alternatively, you can download `protoc` binaries from
[the protocol buffers Github repository](https://github.com/google/protobuf/releases).
#Installation
Currently to install gRPC for C++, you need to build from source as described
below.
#Build from Source
```sh
$ git clone https://github.com/grpc/grpc.git
$ cd grpc
$ git submodule update --init
$ make
$ [sudo] make install
```
#Documentation
You can find out how to build and run our simplest gRPC C++ example in our
[C++ quick start](https://github.com/grpc/grpc/tree/{{ site.data.config.grpc_release_branch }}/examples/cpp).
For more detailed documentation on using gRPC in C++ , see our main
documentation site at [grpc.io](http://grpc.io), specifically:
* [Overview](http://www.grpc.io/docs/): An introduction to gRPC with a simple
Hello World example in all our supported languages, including C++.
* [gRPC Basics - C++](http://www.grpc.io/docs/tutorials/basic/c.html):
A tutorial that steps you through creating a simple gRPC C++ example
application.
* [Asynchronous Basics - C++](http://www.grpc.io/docs/tutorials/async/helloasync-cpp.html):
A tutorial that shows you how to use gRPC C++'s asynchronous/non-blocking
APIs.
# Examples
Code examples for gRPC C++ live in this repository's
[examples/cpp](https://github.com/grpc/grpc/tree/{{ site.data.config.grpc_release_branch }}/examples/cpp) directory.

@ -83,14 +83,14 @@ std::shared_ptr<CallCredentials> WrapCallCredentials(
} // namespace } // namespace
std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials() { std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials() {
GrpcLibrary init; // To call grpc_init(). GrpcLibraryCodegen init; // To call grpc_init().
return WrapChannelCredentials(grpc_google_default_credentials_create()); return WrapChannelCredentials(grpc_google_default_credentials_create());
} }
// Builds SSL Credentials given SSL specific options // Builds SSL Credentials given SSL specific options
std::shared_ptr<ChannelCredentials> SslCredentials( std::shared_ptr<ChannelCredentials> SslCredentials(
const SslCredentialsOptions& options) { const SslCredentialsOptions& options) {
GrpcLibrary init; // To call grpc_init(). GrpcLibraryCodegen init; // To call grpc_init().
grpc_ssl_pem_key_cert_pair pem_key_cert_pair = { grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {
options.pem_private_key.c_str(), options.pem_cert_chain.c_str()}; options.pem_private_key.c_str(), options.pem_cert_chain.c_str()};
@ -102,7 +102,7 @@ std::shared_ptr<ChannelCredentials> SslCredentials(
// Builds credentials for use when running in GCE // Builds credentials for use when running in GCE
std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials() { std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials() {
GrpcLibrary init; // To call grpc_init(). GrpcLibraryCodegen init; // To call grpc_init().
return WrapCallCredentials( return WrapCallCredentials(
grpc_google_compute_engine_credentials_create(nullptr)); grpc_google_compute_engine_credentials_create(nullptr));
} }
@ -110,7 +110,7 @@ std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials() {
// Builds JWT credentials. // Builds JWT credentials.
std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials( std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
const grpc::string& json_key, long token_lifetime_seconds) { const grpc::string& json_key, long token_lifetime_seconds) {
GrpcLibrary init; // To call grpc_init(). GrpcLibraryCodegen init; // To call grpc_init().
if (token_lifetime_seconds <= 0) { if (token_lifetime_seconds <= 0) {
gpr_log(GPR_ERROR, gpr_log(GPR_ERROR,
"Trying to create JWTCredentials with non-positive lifetime"); "Trying to create JWTCredentials with non-positive lifetime");
@ -125,7 +125,7 @@ std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
// Builds refresh token credentials. // Builds refresh token credentials.
std::shared_ptr<CallCredentials> GoogleRefreshTokenCredentials( std::shared_ptr<CallCredentials> GoogleRefreshTokenCredentials(
const grpc::string& json_refresh_token) { const grpc::string& json_refresh_token) {
GrpcLibrary init; // To call grpc_init(). GrpcLibraryCodegen init; // To call grpc_init().
return WrapCallCredentials(grpc_google_refresh_token_credentials_create( return WrapCallCredentials(grpc_google_refresh_token_credentials_create(
json_refresh_token.c_str(), nullptr)); json_refresh_token.c_str(), nullptr));
} }
@ -133,7 +133,7 @@ std::shared_ptr<CallCredentials> GoogleRefreshTokenCredentials(
// Builds access token credentials. // Builds access token credentials.
std::shared_ptr<CallCredentials> AccessTokenCredentials( std::shared_ptr<CallCredentials> AccessTokenCredentials(
const grpc::string& access_token) { const grpc::string& access_token) {
GrpcLibrary init; // To call grpc_init(). GrpcLibraryCodegen init; // To call grpc_init().
return WrapCallCredentials( return WrapCallCredentials(
grpc_access_token_credentials_create(access_token.c_str(), nullptr)); grpc_access_token_credentials_create(access_token.c_str(), nullptr));
} }
@ -142,7 +142,7 @@ std::shared_ptr<CallCredentials> AccessTokenCredentials(
std::shared_ptr<CallCredentials> GoogleIAMCredentials( std::shared_ptr<CallCredentials> GoogleIAMCredentials(
const grpc::string& authorization_token, const grpc::string& authorization_token,
const grpc::string& authority_selector) { const grpc::string& authority_selector) {
GrpcLibrary init; // To call grpc_init(). GrpcLibraryCodegen init; // To call grpc_init().
return WrapCallCredentials(grpc_google_iam_credentials_create( return WrapCallCredentials(grpc_google_iam_credentials_create(
authorization_token.c_str(), authority_selector.c_str(), nullptr)); authorization_token.c_str(), authority_selector.c_str(), nullptr));
} }
@ -224,7 +224,7 @@ MetadataCredentialsPluginWrapper::MetadataCredentialsPluginWrapper(
std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin( std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin(
std::unique_ptr<MetadataCredentialsPlugin> plugin) { std::unique_ptr<MetadataCredentialsPlugin> plugin) {
GrpcLibrary init; // To call grpc_init(). GrpcLibraryCodegen init; // To call grpc_init().
const char* type = plugin->GetType(); const char* type = plugin->GetType();
MetadataCredentialsPluginWrapper* wrapper = MetadataCredentialsPluginWrapper* wrapper =
new MetadataCredentialsPluginWrapper(std::move(plugin)); new MetadataCredentialsPluginWrapper(std::move(plugin));

@ -0,0 +1,45 @@
/*
*
* Copyright 2016, 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 <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/grpc_library.h>
/// Initializes the global gRPC variables for the codegen library. These will
/// stay null in the absence of of grpc++ library. In this case, no gRPC
/// features such as the ability to perform calls will be available. Trying to
/// perform them would result in a segmentation fault when trying to deference
/// the following nulled globals. These should be associated with actual
/// as part of the instantiation of a \a grpc::GrpcLibraryInitializer variable.
grpc::CoreCodegenInterface* grpc::g_core_codegen_interface = nullptr;
grpc::GrpcLibraryInterface* grpc::g_glip = nullptr;

@ -1,92 +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 <grpc++/impl/call.h>
#include <grpc/support/alloc.h>
#include <grpc++/channel.h>
#include <grpc++/client_context.h>
#include <grpc++/support/byte_buffer.h>
#include "src/core/profiling/timers.h"
namespace grpc {
void FillMetadataMap(
grpc_metadata_array* arr,
std::multimap<grpc::string_ref, grpc::string_ref>* metadata) {
for (size_t i = 0; i < arr->count; i++) {
// TODO(yangg) handle duplicates?
metadata->insert(std::pair<grpc::string_ref, grpc::string_ref>(
arr->metadata[i].key, grpc::string_ref(arr->metadata[i].value,
arr->metadata[i].value_length)));
}
grpc_metadata_array_destroy(arr);
grpc_metadata_array_init(arr);
}
// TODO(yangg) if the map is changed before we send, the pointers will be a
// mess. Make sure it does not happen.
grpc_metadata* FillMetadataArray(
const std::multimap<grpc::string, grpc::string>& metadata) {
if (metadata.empty()) {
return nullptr;
}
grpc_metadata* metadata_array =
(grpc_metadata*)gpr_malloc(metadata.size() * sizeof(grpc_metadata));
size_t i = 0;
for (auto iter = metadata.cbegin(); iter != metadata.cend(); ++iter, ++i) {
metadata_array[i].key = iter->first.c_str();
metadata_array[i].value = iter->second.c_str();
metadata_array[i].value_length = iter->second.size();
}
return metadata_array;
}
Call::Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq)
: call_hook_(call_hook), cq_(cq), call_(call), max_message_size_(-1) {}
Call::Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq,
int max_message_size)
: call_hook_(call_hook),
cq_(cq),
call_(call),
max_message_size_(max_message_size) {}
void Call::PerformOps(CallOpSetInterface* ops) {
if (max_message_size_ > 0) {
ops->set_max_message_size(max_message_size_);
}
call_hook_->PerformOpsOnCall(ops, this);
}
} // namespace grpc

@ -34,7 +34,6 @@
#include <memory> #include <memory>
#include <grpc++/impl/codegen/completion_queue_tag.h>
#include <grpc++/impl/grpc_library.h> #include <grpc++/impl/grpc_library.h>
#include <grpc++/support/time.h> #include <grpc++/support/time.h>
#include <grpc/grpc.h> #include <grpc/grpc.h>
@ -43,16 +42,13 @@
namespace grpc { namespace grpc {
static internal::GrpcLibraryInitializer g_gli_initializer; static internal::GrpcLibraryInitializer g_gli_initializer;
CompletionQueue::CompletionQueue() {
g_gli_initializer.summon();
cq_ = grpc_completion_queue_create(nullptr);
}
CompletionQueue::CompletionQueue(grpc_completion_queue* take) : cq_(take) {} CompletionQueue::CompletionQueue(grpc_completion_queue* take) : cq_(take) {}
CompletionQueue::~CompletionQueue() { grpc_completion_queue_destroy(cq_); } void CompletionQueue::Shutdown() {
g_gli_initializer.summon();
void CompletionQueue::Shutdown() { grpc_completion_queue_shutdown(cq_); } grpc_completion_queue_shutdown(cq_);
}
CompletionQueue::NextStatus CompletionQueue::AsyncNextInternal( CompletionQueue::NextStatus CompletionQueue::AsyncNextInternal(
void** tag, bool* ok, gpr_timespec deadline) { void** tag, bool* ok, gpr_timespec deadline) {
@ -75,25 +71,4 @@ CompletionQueue::NextStatus CompletionQueue::AsyncNextInternal(
} }
} }
bool CompletionQueue::Pluck(CompletionQueueTag* tag) {
auto deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
auto ev = grpc_completion_queue_pluck(cq_, tag, deadline, nullptr);
bool ok = ev.success != 0;
void* ignored = tag;
GPR_ASSERT(tag->FinalizeResult(&ignored, &ok));
GPR_ASSERT(ignored == tag);
// Ignore mutations by FinalizeResult: Pluck returns the C API status
return ev.success != 0;
}
void CompletionQueue::TryPluck(CompletionQueueTag* tag) {
auto deadline = gpr_time_0(GPR_CLOCK_REALTIME);
auto ev = grpc_completion_queue_pluck(cq_, tag, deadline, nullptr);
if (ev.type == GRPC_QUEUE_TIMEOUT) return;
bool ok = ev.success != 0;
void* ignored = tag;
// the tag must be swallowed if using TryPluck
GPR_ASSERT(!tag->FinalizeResult(&ignored, &ok));
}
} // namespace grpc } // namespace grpc

@ -1,6 +1,6 @@
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -31,28 +31,31 @@
* *
*/ */
#include <grpc++/impl/proto_utils.h> #include "src/cpp/common/core_codegen.h"
#include <climits> #include <stdlib.h>
#include <grpc/grpc.h> #include <grpc++/support/config.h>
#include <grpc/byte_buffer.h> #include <grpc/byte_buffer.h>
#include <grpc/byte_buffer_reader.h> #include <grpc/byte_buffer_reader.h>
#include <grpc/support/log.h> #include <grpc/grpc.h>
#include <grpc/impl/codegen/alloc.h>
#include <grpc/impl/codegen/byte_buffer.h>
#include <grpc/impl/codegen/log.h>
#include <grpc/support/port_platform.h>
#include <grpc/support/slice.h> #include <grpc/support/slice.h>
#include <grpc/support/slice_buffer.h> #include <grpc/support/slice_buffer.h>
#include <grpc/support/port_platform.h>
#include <grpc++/support/config.h>
#include "src/core/profiling/timers.h" #include "src/core/profiling/timers.h"
const int kMaxBufferLength = 8192; namespace {
const int kGrpcBufferWriterMaxBufferLength = 8192;
class GrpcBufferWriter GRPC_FINAL class GrpcBufferWriter GRPC_FINAL
: public ::grpc::protobuf::io::ZeroCopyOutputStream { : public ::grpc::protobuf::io::ZeroCopyOutputStream {
public: public:
explicit GrpcBufferWriter(grpc_byte_buffer** bp, explicit GrpcBufferWriter(grpc_byte_buffer** bp, int block_size)
int block_size = kMaxBufferLength)
: block_size_(block_size), byte_count_(0), have_backup_(false) { : block_size_(block_size), byte_count_(0), have_backup_(false) {
*bp = grpc_raw_byte_buffer_create(NULL, 0); *bp = grpc_raw_byte_buffer_create(NULL, 0);
slice_buffer_ = &(*bp)->data.raw.slice_buffer; slice_buffer_ = &(*bp)->data.raw.slice_buffer;
@ -161,14 +164,56 @@ class GrpcBufferReader GRPC_FINAL
grpc_byte_buffer_reader reader_; grpc_byte_buffer_reader reader_;
gpr_slice slice_; gpr_slice slice_;
}; };
} // namespace
namespace grpc { namespace grpc {
Status SerializeProto(const grpc::protobuf::Message& msg, grpc_completion_queue* CoreCodegen::grpc_completion_queue_create(
void* reserved) {
return ::grpc_completion_queue_create(reserved);
}
void CoreCodegen::grpc_completion_queue_destroy(grpc_completion_queue* cq) {
::grpc_completion_queue_destroy(cq);
}
grpc_event CoreCodegen::grpc_completion_queue_pluck(grpc_completion_queue* cq,
void* tag,
gpr_timespec deadline,
void* reserved) {
return ::grpc_completion_queue_pluck(cq, tag, deadline, reserved);
}
void* CoreCodegen::gpr_malloc(size_t size) { return ::gpr_malloc(size); }
void CoreCodegen::gpr_free(void* p) { return ::gpr_free(p); }
void CoreCodegen::grpc_byte_buffer_destroy(grpc_byte_buffer* bb) {
::grpc_byte_buffer_destroy(bb);
}
void CoreCodegen::grpc_metadata_array_init(grpc_metadata_array* array) {
::grpc_metadata_array_init(array);
}
void CoreCodegen::grpc_metadata_array_destroy(grpc_metadata_array* array) {
::grpc_metadata_array_destroy(array);
}
gpr_timespec CoreCodegen::gpr_inf_future(gpr_clock_type type) {
return ::gpr_inf_future(type);
}
void CoreCodegen::assert_fail(const char* failed_assertion) {
gpr_log(GPR_ERROR, "assertion failed: %s", failed_assertion);
abort();
}
Status CoreCodegen::SerializeProto(const grpc::protobuf::Message& msg,
grpc_byte_buffer** bp) { grpc_byte_buffer** bp) {
GPR_TIMER_SCOPE("SerializeProto", 0); GPR_TIMER_SCOPE("SerializeProto", 0);
int byte_size = msg.ByteSize(); int byte_size = msg.ByteSize();
if (byte_size <= kMaxBufferLength) { if (byte_size <= kGrpcBufferWriterMaxBufferLength) {
gpr_slice slice = gpr_slice_malloc(byte_size); gpr_slice slice = gpr_slice_malloc(byte_size);
GPR_ASSERT(GPR_SLICE_END_PTR(slice) == GPR_ASSERT(GPR_SLICE_END_PTR(slice) ==
msg.SerializeWithCachedSizesToArray(GPR_SLICE_START_PTR(slice))); msg.SerializeWithCachedSizesToArray(GPR_SLICE_START_PTR(slice)));
@ -176,31 +221,36 @@ Status SerializeProto(const grpc::protobuf::Message& msg,
gpr_slice_unref(slice); gpr_slice_unref(slice);
return Status::OK; return Status::OK;
} else { } else {
GrpcBufferWriter writer(bp); GrpcBufferWriter writer(bp, kGrpcBufferWriterMaxBufferLength);
return msg.SerializeToZeroCopyStream(&writer) return msg.SerializeToZeroCopyStream(&writer)
? Status::OK ? Status::OK
: Status(StatusCode::INTERNAL, "Failed to serialize message"); : Status(StatusCode::INTERNAL, "Failed to serialize message");
} }
} }
Status DeserializeProto(grpc_byte_buffer* buffer, grpc::protobuf::Message* msg, Status CoreCodegen::DeserializeProto(grpc_byte_buffer* buffer,
grpc::protobuf::Message* msg,
int max_message_size) { int max_message_size) {
GPR_TIMER_SCOPE("DeserializeProto", 0); GPR_TIMER_SCOPE("DeserializeProto", 0);
if (!buffer) { if (buffer == nullptr) {
return Status(StatusCode::INTERNAL, "No payload"); return Status(StatusCode::INTERNAL, "No payload");
} }
Status result = Status::OK;
{
GrpcBufferReader reader(buffer); GrpcBufferReader reader(buffer);
::grpc::protobuf::io::CodedInputStream decoder(&reader); ::grpc::protobuf::io::CodedInputStream decoder(&reader);
if (max_message_size > 0) { if (max_message_size > 0) {
decoder.SetTotalBytesLimit(max_message_size, max_message_size); decoder.SetTotalBytesLimit(max_message_size, max_message_size);
} }
if (!msg->ParseFromCodedStream(&decoder)) { if (!msg->ParseFromCodedStream(&decoder)) {
return Status(StatusCode::INTERNAL, msg->InitializationErrorString()); result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
} }
if (!decoder.ConsumedEntireMessage()) { if (!decoder.ConsumedEntireMessage()) {
return Status(StatusCode::INTERNAL, "Did not read entire message"); result = Status(StatusCode::INTERNAL, "Did not read entire message");
} }
return Status::OK; }
grpc_byte_buffer_destroy(buffer);
return result;
} }
} // namespace grpc } // namespace grpc

@ -0,0 +1,71 @@
/*
*
* Copyright 2016, 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.
*
*/
// This file should be compiled as part of grpc++.
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc/byte_buffer.h>
namespace grpc {
/// Implementation of the core codegen interface.
class CoreCodegen : public CoreCodegenInterface {
private:
Status SerializeProto(const grpc::protobuf::Message& msg,
grpc_byte_buffer** bp) override;
Status DeserializeProto(grpc_byte_buffer* buffer,
grpc::protobuf::Message* msg,
int max_message_size) override;
grpc_completion_queue* grpc_completion_queue_create(void* reserved) override;
void grpc_completion_queue_destroy(grpc_completion_queue* cq) override;
grpc_event grpc_completion_queue_pluck(grpc_completion_queue* cq, void* tag,
gpr_timespec deadline,
void* reserved) override;
void* gpr_malloc(size_t size) override;
void gpr_free(void* p) override;
void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) override;
void grpc_metadata_array_init(grpc_metadata_array* array) override;
void grpc_metadata_array_destroy(grpc_metadata_array* array) override;
gpr_timespec gpr_inf_future(gpr_clock_type type) override;
void assert_fail(const char* failed_assertion) override;
};
} // namespace grpc

@ -62,7 +62,11 @@ class ServerContext::CompletionOp GRPC_FINAL : public CallOpSetInterface {
void FillOps(grpc_op* ops, size_t* nops) GRPC_OVERRIDE; void FillOps(grpc_op* ops, size_t* nops) GRPC_OVERRIDE;
bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE; bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE;
bool CheckCancelled(CompletionQueue* cq); bool CheckCancelled(CompletionQueue* cq) {
cq->TryPluck(this);
return CheckCancelledNoPluck();
}
bool CheckCancelledAsync() { return CheckCancelledNoPluck(); }
void set_tag(void* tag) { void set_tag(void* tag) {
has_tag_ = true; has_tag_ = true;
@ -72,6 +76,11 @@ class ServerContext::CompletionOp GRPC_FINAL : public CallOpSetInterface {
void Unref(); void Unref();
private: private:
bool CheckCancelledNoPluck() {
grpc::lock_guard<grpc::mutex> g(mu_);
return finalized_ ? (cancelled_ != 0) : false;
}
bool has_tag_; bool has_tag_;
void* tag_; void* tag_;
grpc::mutex mu_; grpc::mutex mu_;
@ -88,12 +97,6 @@ void ServerContext::CompletionOp::Unref() {
} }
} }
bool ServerContext::CompletionOp::CheckCancelled(CompletionQueue* cq) {
cq->TryPluck(this);
grpc::lock_guard<grpc::mutex> g(mu_);
return finalized_ ? cancelled_ != 0 : false;
}
void ServerContext::CompletionOp::FillOps(grpc_op* ops, size_t* nops) { void ServerContext::CompletionOp::FillOps(grpc_op* ops, size_t* nops) {
ops->op = GRPC_OP_RECV_CLOSE_ON_SERVER; ops->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
ops->data.recv_close_on_server.cancelled = &cancelled_; ops->data.recv_close_on_server.cancelled = &cancelled_;
@ -182,7 +185,14 @@ void ServerContext::TryCancel() const {
} }
bool ServerContext::IsCancelled() const { bool ServerContext::IsCancelled() const {
if (has_notify_when_done_tag_) {
// when using async API, but the result is only valid
// if the tag has already been delivered at the completion queue
return completion_op_ && completion_op_->CheckCancelledAsync();
} else {
// when using sync API
return completion_op_ && completion_op_->CheckCancelled(cq_); return completion_op_ && completion_op_->CheckCancelled(cq_);
}
} }
void ServerContext::set_compression_level(grpc_compression_level level) { void ServerContext::set_compression_level(grpc_compression_level level) {

@ -1,6 +1,6 @@
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2015-2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -33,72 +33,8 @@
#include <grpc++/support/string_ref.h> #include <grpc++/support/string_ref.h>
#include <string.h>
#include <algorithm>
#include <iostream>
namespace grpc { namespace grpc {
const size_t string_ref::npos = size_t(-1); const size_t string_ref::npos = size_t(-1);
string_ref& string_ref::operator=(const string_ref& rhs) {
data_ = rhs.data_;
length_ = rhs.length_;
return *this;
}
string_ref::string_ref(const char* s) : data_(s), length_(strlen(s)) {}
string_ref string_ref::substr(size_t pos, size_t n) const {
if (pos > length_) pos = length_;
if (n > (length_ - pos)) n = length_ - pos;
return string_ref(data_ + pos, n);
}
int string_ref::compare(string_ref x) const {
size_t min_size = length_ < x.length_ ? length_ : x.length_;
int r = memcmp(data_, x.data_, min_size);
if (r < 0) return -1;
if (r > 0) return 1;
if (length_ < x.length_) return -1;
if (length_ > x.length_) return 1;
return 0;
}
bool string_ref::starts_with(string_ref x) const {
return length_ >= x.length_ && (memcmp(data_, x.data_, x.length_) == 0);
}
bool string_ref::ends_with(string_ref x) const {
return length_ >= x.length_ &&
(memcmp(data_ + (length_ - x.length_), x.data_, x.length_) == 0);
}
size_t string_ref::find(string_ref s) const {
auto it = std::search(cbegin(), cend(), s.cbegin(), s.cend());
return it == cend() ? npos : std::distance(cbegin(), it);
}
size_t string_ref::find(char c) const {
auto it = std::find(cbegin(), cend(), c);
return it == cend() ? npos : std::distance(cbegin(), it);
}
bool operator==(string_ref x, string_ref y) { return x.compare(y) == 0; }
bool operator!=(string_ref x, string_ref y) { return x.compare(y) != 0; }
bool operator<(string_ref x, string_ref y) { return x.compare(y) < 0; }
bool operator<=(string_ref x, string_ref y) { return x.compare(y) <= 0; }
bool operator>(string_ref x, string_ref y) { return x.compare(y) > 0; }
bool operator>=(string_ref x, string_ref y) { return x.compare(y) >= 0; }
std::ostream& operator<<(std::ostream& out, const string_ref& string) {
return out << grpc::string(string.begin(), string.end());
}
} // namespace grpc } // namespace grpc

@ -323,7 +323,7 @@ namespace Grpc.Core
private static string NormalizeKey(string key) private static string NormalizeKey(string key)
{ {
var normalized = GrpcPreconditions.CheckNotNull(key, "key").ToLower(CultureInfo.InvariantCulture); var normalized = GrpcPreconditions.CheckNotNull(key, "key").ToLowerInvariant();
GrpcPreconditions.CheckArgument(ValidKeyRegex.IsMatch(normalized), GrpcPreconditions.CheckArgument(ValidKeyRegex.IsMatch(normalized),
"Metadata entry key not valid. Keys can only contain lowercase alphanumeric characters, underscores and hyphens."); "Metadata entry key not valid. Keys can only contain lowercase alphanumeric characters, underscores and hyphens.");
return normalized; return normalized;

@ -5,7 +5,7 @@
Beta Beta
## PREREQUISITES ## PREREQUISITES
- `node`: This requires `node` to be installed. If you instead have the `nodejs` executable on Debian, you should install the [`nodejs-legacy`](https://packages.debian.org/sid/nodejs-legacy) package. - `node`: This requires `node` to be installed, version `0.12` or above. If you instead have the `nodejs` executable on Debian, you should install the [`nodejs-legacy`](https://packages.debian.org/sid/nodejs-legacy) package.
## INSTALLATION ## INSTALLATION

@ -149,6 +149,9 @@ function _readsDone(status) {
if (!status) { if (!status) {
status = {code: grpc.status.OK, details: 'OK'}; status = {code: grpc.status.OK, details: 'OK'};
} }
if (status.code !== grpc.status.OK) {
this.call.cancelWithStatus(status.code, status.details);
}
this.finished = true; this.finished = true;
this.read_status = status; this.read_status = status;
this._emitStatusIfDone(); this._emitStatusIfDone();
@ -408,7 +411,7 @@ function makeUnaryRequestFunction(method, serialize, deserialize) {
} }
} }
if (status.code !== grpc.status.OK) { if (status.code !== grpc.status.OK) {
error = new Error(response.status.details); error = new Error(status.details);
error.code = status.code; error.code = status.code;
error.metadata = status.metadata; error.metadata = status.metadata;
callback(error); callback(error);

@ -37,6 +37,8 @@
#include <grpc/support/time.h> #include <grpc/support/time.h>
#import <RxLibrary/GRXConcurrentWriteable.h> #import <RxLibrary/GRXConcurrentWriteable.h>
#import "private/GRPCConnectivityMonitor.h"
#import "private/GRPCHost.h"
#import "private/GRPCRequestHeaders.h" #import "private/GRPCRequestHeaders.h"
#import "private/GRPCWrappedCall.h" #import "private/GRPCWrappedCall.h"
#import "private/NSData+GRPC.h" #import "private/NSData+GRPC.h"
@ -71,8 +73,11 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
@implementation GRPCCall { @implementation GRPCCall {
dispatch_queue_t _callQueue; dispatch_queue_t _callQueue;
NSString *_host;
NSString *_path;
GRPCWrappedCall *_wrappedCall; GRPCWrappedCall *_wrappedCall;
dispatch_once_t _callAlreadyInvoked; dispatch_once_t _callAlreadyInvoked;
GRPCConnectivityMonitor *_connectivityMonitor;
// The C gRPC library has less guarantees on the ordering of events than we // The C gRPC library has less guarantees on the ordering of events than we
// do. Particularly, in the face of errors, there's no ordering guarantee at // do. Particularly, in the face of errors, there's no ordering guarantee at
@ -115,13 +120,11 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
format:@"The requests writer can't be already started."]; format:@"The requests writer can't be already started."];
} }
if ((self = [super init])) { if ((self = [super init])) {
_wrappedCall = [[GRPCWrappedCall alloc] initWithHost:host path:path]; _host = [host copy];
if (!_wrappedCall) { _path = [path copy];
return nil;
}
// Serial queue to invoke the non-reentrant methods of the grpc_call object. // Serial queue to invoke the non-reentrant methods of the grpc_call object.
_callQueue = dispatch_queue_create("org.grpc.call", NULL); _callQueue = dispatch_queue_create("io.grpc.call", NULL);
_requestWriter = requestWriter; _requestWriter = requestWriter;
@ -156,7 +159,7 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
- (void)cancel { - (void)cancel {
[self finishWithError:[NSError errorWithDomain:kGRPCErrorDomain [self finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
code:GRPCErrorCodeCancelled code:GRPCErrorCodeCancelled
userInfo:nil]]; userInfo:@{NSLocalizedDescriptionKey: @"Canceled by app"}]];
[self cancelCall]; [self cancelCall];
} }
@ -354,8 +357,29 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
_retainSelf = self; _retainSelf = self;
_responseWriteable = [[GRXConcurrentWriteable alloc] initWithWriteable:writeable]; _responseWriteable = [[GRXConcurrentWriteable alloc] initWithWriteable:writeable];
_wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host path:_path];
NSAssert(_wrappedCall, @"Error allocating RPC objects. Low memory?");
[self sendHeaders:_requestHeaders]; [self sendHeaders:_requestHeaders];
[self invokeCall]; [self invokeCall];
// TODO(jcanizales): Extract this logic somewhere common.
NSString *host = [NSURL URLWithString:[@"https://" stringByAppendingString:_host]].host;
if (!host) {
// TODO(jcanizales): Check this on init.
[NSException raise:NSInvalidArgumentException format:@"host of %@ is nil", _host];
}
__weak typeof(self) weakSelf = self;
_connectivityMonitor = [GRPCConnectivityMonitor monitorWithHost:host];
[_connectivityMonitor handleLossWithHandler:^{
typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
code:GRPCErrorCodeUnavailable
userInfo:@{NSLocalizedDescriptionKey: @"Connectivity lost."}]];
[[GRPCHost hostWithAddress:strongSelf->_host] disconnect];
}
}];
} }
- (void)setState:(GRXWriterState)newState { - (void)setState:(GRXWriterState)newState {
@ -385,4 +409,5 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
return; return;
} }
} }
@end @end

@ -35,6 +35,7 @@
#include <grpc/grpc.h> #include <grpc/grpc.h>
@class GRPCCompletionQueue;
struct grpc_channel_credentials; struct grpc_channel_credentials;
@ -80,4 +81,6 @@ struct grpc_channel_credentials;
+ (nonnull GRPCChannel *)insecureChannelWithHost:(nonnull NSString *)host + (nonnull GRPCChannel *)insecureChannelWithHost:(nonnull NSString *)host
channelArgs:(nullable NSDictionary *)channelArgs; channelArgs:(nullable NSDictionary *)channelArgs;
- (nullable grpc_call *)unmanagedCallWithPath:(nonnull NSString *)path
completionQueue:(nonnull GRPCCompletionQueue *)queue;
@end @end

@ -38,6 +38,8 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#import "GRPCCompletionQueue.h"
/** /**
* Returns @c grpc_channel_credentials from the specified @c path. If the file at the path could not * Returns @c grpc_channel_credentials from the specified @c path. If the file at the path could not
* be read then NULL is returned. If NULL is returned, @c errorPtr may not be NULL if there are * be read then NULL is returned. If NULL is returned, @c errorPtr may not be NULL if there are
@ -205,4 +207,16 @@ grpc_channel_args * buildChannelArgs(NSDictionary *dictionary) {
channelArgs:channelArgs]; channelArgs:channelArgs];
} }
- (grpc_call *)unmanagedCallWithPath:(NSString *)path
completionQueue:(GRPCCompletionQueue *)queue {
return grpc_channel_create_call(_unmanagedChannel,
NULL, GRPC_PROPAGATE_DEFAULTS,
queue.unmanagedQueue,
path.UTF8String,
// Get "host" from "host:port"
// TODO(jcanizales): Use NSURLs throughout, to clarify these.
[_host componentsSeparatedByString:@":"][0].UTF8String,
gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
}
@end @end

@ -36,6 +36,8 @@
typedef void(^GRPCQueueCompletionHandler)(bool success); typedef void(^GRPCQueueCompletionHandler)(bool success);
extern const int64_t kGRPCCompletionQueueDefaultTimeoutSecs;
/** /**
* This class lets one more easily use |grpc_completion_queue|. To use it, pass the value of the * This class lets one more easily use |grpc_completion_queue|. To use it, pass the value of the
* |unmanagedQueue| property of an instance of this class to |grpc_channel_create_call|. Then for * |unmanagedQueue| property of an instance of this class to |grpc_channel_create_call|. Then for
@ -49,6 +51,11 @@ typedef void(^GRPCQueueCompletionHandler)(bool success);
*/ */
@interface GRPCCompletionQueue : NSObject @interface GRPCCompletionQueue : NSObject
@property(nonatomic, readonly) grpc_completion_queue *unmanagedQueue; @property(nonatomic, readonly) grpc_completion_queue *unmanagedQueue;
@property(nonatomic, readonly) int64_t timeoutSecs;
+ (instancetype)completionQueue; + (instancetype)completionQueue;
- (instancetype)init;
- (instancetype)initWithTimeout:(int64_t)timeoutSecs NS_DESIGNATED_INITIALIZER;
@end @end

@ -35,15 +35,28 @@
#import <grpc/grpc.h> #import <grpc/grpc.h>
const int64_t kGRPCCompletionQueueDefaultTimeoutSecs = 60;
@implementation GRPCCompletionQueue @implementation GRPCCompletionQueue
+ (instancetype)completionQueue { + (instancetype)completionQueue {
return [[self alloc] init]; static GRPCCompletionQueue *singleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleton = [[self alloc] init];
});
return singleton;
} }
- (instancetype)init { - (instancetype)init {
return [self initWithTimeout:kGRPCCompletionQueueDefaultTimeoutSecs];
}
- (instancetype)initWithTimeout:(int64_t)timeoutSecs {
if ((self = [super init])) { if ((self = [super init])) {
_unmanagedQueue = grpc_completion_queue_create(NULL); _unmanagedQueue = grpc_completion_queue_create(NULL);
_timeoutSecs = timeoutSecs;
// This is for the following block to capture the pointer by value (instead // This is for the following block to capture the pointer by value (instead
// of retaining self and doing self->_unmanagedQueue). This is essential // of retaining self and doing self->_unmanagedQueue). This is essential
@ -61,22 +74,28 @@
gDefaultConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); gDefaultConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
}); });
dispatch_async(gDefaultConcurrentQueue, ^{ dispatch_async(gDefaultConcurrentQueue, ^{
// Using a non-infinite deadline to re-enter grpc_completion_queue_next()
// alleviates https://github.com/grpc/grpc/issues/5593
gpr_timespec deadline = (timeoutSecs < 0)
? gpr_inf_future(GPR_CLOCK_REALTIME)
: gpr_time_from_seconds(timeoutSecs, GPR_CLOCK_REALTIME);
while (YES) { while (YES) {
// The following call blocks until an event is available. // The following call blocks until an event is available or the deadline elapses.
grpc_event event = grpc_completion_queue_next(unmanagedQueue, grpc_event event = grpc_completion_queue_next(unmanagedQueue, deadline, NULL);
gpr_inf_future(GPR_CLOCK_REALTIME),
NULL);
GRPCQueueCompletionHandler handler; GRPCQueueCompletionHandler handler;
switch (event.type) { switch (event.type) {
case GRPC_OP_COMPLETE: case GRPC_OP_COMPLETE:
handler = (__bridge_transfer GRPCQueueCompletionHandler)event.tag; handler = (__bridge_transfer GRPCQueueCompletionHandler)event.tag;
handler(event.success); handler(event.success);
break; break;
case GRPC_QUEUE_TIMEOUT:
// Nothing to do here
break;
case GRPC_QUEUE_SHUTDOWN: case GRPC_QUEUE_SHUTDOWN:
grpc_completion_queue_destroy(unmanagedQueue); grpc_completion_queue_destroy(unmanagedQueue);
return; return;
default: default:
[NSException raise:@"Unrecognized completion type" format:@""]; [NSException raise:@"Unrecognized completion type" format:@"type=%d", event.type];
} }
}; };
}); });

@ -0,0 +1,77 @@
/*
*
* Copyright 2016, 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.
*
*/
#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
@interface GRPCReachabilityFlags : NSObject
+ (nonnull instancetype)flagsWithFlags:(SCNetworkReachabilityFlags)flags;
/**
* One accessor method to query each of the different flags. Example:
@property(nonatomic, readonly) BOOL isCell;
*/
#define GRPC_XMACRO_ITEM(methodName, FlagName) \
@property(nonatomic, readonly) BOOL methodName;
#include "GRPCReachabilityFlagNames.xmacro.h"
#undef GRPC_XMACRO_ITEM
@property(nonatomic, readonly) BOOL isHostReachable;
@end
@interface GRPCConnectivityMonitor : NSObject
+ (nullable instancetype)monitorWithHost:(nonnull NSString *)hostName;
- (nonnull instancetype)init NS_UNAVAILABLE;
/**
* Queue on which callbacks will be dispatched. Default is the main queue. Set it before calling
* handleLossWithHandler:.
*/
// TODO(jcanizales): Default to a serial background queue instead.
@property(nonatomic, strong, null_resettable) dispatch_queue_t queue;
/**
* Calls handler every time the connectivity to this instance's host is lost. If this instance is
* released before that happens, the handler won't be called.
* Only one handler is active at a time, so if this method is called again before the previous
* handler has been called, it might never be called at all (or yes, if it has already been queued).
*/
- (void)handleLossWithHandler:(nonnull void (^)())handler;
@end

@ -0,0 +1,192 @@
/*
*
* Copyright 2016, 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.
*
*/
#import "GRPCConnectivityMonitor.h"
#pragma mark Flags
@implementation GRPCReachabilityFlags {
SCNetworkReachabilityFlags _flags;
}
+ (instancetype)flagsWithFlags:(SCNetworkReachabilityFlags)flags {
return [[self alloc] initWithFlags:flags];
}
- (instancetype)initWithFlags:(SCNetworkReachabilityFlags)flags {
if ((self = [super init])) {
_flags = flags;
}
return self;
}
/*
* One accessor method implementation per flag. Example:
- (BOOL)isCell { \
return !!(_flags & kSCNetworkReachabilityFlagsIsWWAN); \
}
*/
#define GRPC_XMACRO_ITEM(methodName, FlagName) \
- (BOOL)methodName { \
return !!(_flags & kSCNetworkReachabilityFlags ## FlagName); \
}
#include "GRPCReachabilityFlagNames.xmacro.h"
#undef GRPC_XMACRO_ITEM
- (BOOL)isHostReachable {
// Note: connectionOnDemand means it'll be reachable only if using the CFSocketStream API or APIs
// on top of it.
// connectionRequired means we can't tell until a connection is attempted (e.g. for VPN on
// demand).
return self.reachable && !self.interventionRequired && !self.connectionOnDemand;
}
- (NSString *)description {
NSMutableArray *activeOptions = [NSMutableArray arrayWithCapacity:9];
/*
* For each flag, add its name to the array if it's ON. Example:
if (self.isCell) {
[activeOptions addObject:@"isCell"];
}
*/
#define GRPC_XMACRO_ITEM(methodName, FlagName) \
if (self.methodName) { \
[activeOptions addObject:@#methodName]; \
}
#include "GRPCReachabilityFlagNames.xmacro.h"
#undef GRPC_XMACRO_ITEM
return activeOptions.count == 0 ? @"(none)" : [activeOptions componentsJoinedByString:@", "];
}
- (BOOL)isEqual:(id)object {
return [object isKindOfClass:[GRPCReachabilityFlags class]] &&
_flags == ((GRPCReachabilityFlags *)object)->_flags;
}
- (NSUInteger)hash {
return _flags;
}
@end
#pragma mark Connectivity Monitor
// Assumes the third argument is a block that accepts a GRPCReachabilityFlags object, and passes the
// received ones to it.
static void PassFlagsToContextInfoBlock(SCNetworkReachabilityRef target,
SCNetworkReachabilityFlags flags,
void *info) {
#pragma unused (target)
// This can be called many times with the same info. The info is retained by SCNetworkReachability
// while this function is being executed.
void (^handler)(GRPCReachabilityFlags *) = (__bridge void (^)(GRPCReachabilityFlags *))info;
handler([[GRPCReachabilityFlags alloc] initWithFlags:flags]);
}
@implementation GRPCConnectivityMonitor {
SCNetworkReachabilityRef _reachabilityRef;
}
- (nullable instancetype)initWithReachability:(nullable SCNetworkReachabilityRef)reachability {
if (!reachability) {
return nil;
}
if ((self = [super init])) {
_reachabilityRef = CFRetain(reachability);
_queue = dispatch_get_main_queue();
}
return self;
}
+ (nullable instancetype)monitorWithHost:(nonnull NSString *)host {
const char *hostName = host.UTF8String;
if (!hostName) {
[NSException raise:NSInvalidArgumentException
format:@"host.UTF8String returns NULL for %@", host];
}
SCNetworkReachabilityRef reachability =
SCNetworkReachabilityCreateWithName(NULL, hostName);
GRPCConnectivityMonitor *returnValue = [[self alloc] initWithReachability:reachability];
if (reachability) {
CFRelease(reachability);
}
return returnValue;
}
- (void)handleLossWithHandler:(void (^)())handler {
[self startListeningWithHandler:^(GRPCReachabilityFlags *flags) {
if (!flags.isHostReachable) {
handler();
}
}];
}
- (void)startListeningWithHandler:(void (^)(GRPCReachabilityFlags *))handler {
// Copy to ensure the handler block is in the heap (and so can't be deallocated when this method
// returns).
void (^copiedHandler)(GRPCReachabilityFlags *) = [handler copy];
SCNetworkReachabilityContext context = {
.version = 0,
.info = (__bridge void *)copiedHandler,
.retain = CFRetain,
.release = CFRelease,
};
// The following will retain context.info, and release it when the callback is set to NULL.
SCNetworkReachabilitySetCallback(_reachabilityRef, PassFlagsToContextInfoBlock, &context);
SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, _queue);
}
- (void)stopListening {
// This releases the block on context.info.
SCNetworkReachabilitySetCallback(_reachabilityRef, NULL, NULL);
SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, NULL);
}
- (void)setQueue:(dispatch_queue_t)queue {
_queue = queue ?: dispatch_get_main_queue();
}
- (void)dealloc {
if (_reachabilityRef) {
[self stopListening];
CFRelease(_reachabilityRef);
}
}
@end

@ -33,27 +33,39 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class GRPCCompletionQueue; @class GRPCCompletionQueue;
struct grpc_call; struct grpc_call;
@interface GRPCHost : NSObject @interface GRPCHost : NSObject
@property(nonatomic, readonly) NSString *address; @property(nonatomic, readonly) NSString *address;
@property(nonatomic, copy) NSString *userAgentPrefix; @property(nonatomic, copy, nullable) NSString *userAgentPrefix;
/** The following properties should only be modified for testing: */ /** The following properties should only be modified for testing: */
@property(nonatomic, getter=isSecure) BOOL secure; @property(nonatomic, getter=isSecure) BOOL secure;
@property(nonatomic, copy) NSString *pathToCertificates; @property(nonatomic, copy, nullable) NSString *pathToCertificates;
@property(nonatomic, copy) NSString *hostNameOverride; @property(nonatomic, copy, nullable) NSString *hostNameOverride;
- (nullable instancetype)init NS_UNAVAILABLE;
/** Host objects initialized with the same address are the same. */ /** Host objects initialized with the same address are the same. */
+ (instancetype)hostWithAddress:(NSString *)address; + (nullable instancetype)hostWithAddress:(NSString *)address;
- (instancetype)initWithAddress:(NSString *)address NS_DESIGNATED_INITIALIZER; - (nullable instancetype)initWithAddress:(NSString *)address NS_DESIGNATED_INITIALIZER;
/** Create a grpc_call object to the provided path on this host. */ /** Create a grpc_call object to the provided path on this host. */
- (struct grpc_call *)unmanagedCallWithPath:(NSString *)path - (nullable struct grpc_call *)unmanagedCallWithPath:(NSString *)path
completionQueue:(GRPCCompletionQueue *)queue; completionQueue:(GRPCCompletionQueue *)queue;
// TODO: There's a race when a new RPC is coming through just as an existing one is getting
// notified that there's no connectivity. If connectivity comes back at that moment, the new RPC
// will have its channel destroyed by the other RPC, and will never get notified of a problem, so
// it'll hang (the C layer logs a timeout, with exponential back off). One solution could be to pass
// the GRPCChannel to the GRPCCall, renaming this as "disconnectChannel:channel", which would only
// act on that specific channel.
- (void)disconnect;
@end @end
NS_ASSUME_NONNULL_END

@ -34,33 +34,30 @@
#import "GRPCHost.h" #import "GRPCHost.h"
#include <grpc/grpc.h> #include <grpc/grpc.h>
#import <GRPCClient/GRPCCall.h>
#import <GRPCClient/GRPCCall+ChannelArg.h> #import <GRPCClient/GRPCCall+ChannelArg.h>
#import "GRPCChannel.h" #import "GRPCChannel.h"
#import "GRPCCompletionQueue.h" #import "GRPCCompletionQueue.h"
#import "NSDictionary+GRPC.h" #import "NSDictionary+GRPC.h"
NS_ASSUME_NONNULL_BEGIN
// TODO(jcanizales): Generate the version in a standalone header, from templates. Like // TODO(jcanizales): Generate the version in a standalone header, from templates. Like
// templates/src/core/surface/version.c.template . // templates/src/core/surface/version.c.template .
#define GRPC_OBJC_VERSION_STRING @"0.13.0" #define GRPC_OBJC_VERSION_STRING @"0.13.0"
@interface GRPCHost () @implementation GRPCHost {
// TODO(mlumish): Investigate whether caching channels with strong links is a good idea. // TODO(mlumish): Investigate whether caching channels with strong links is a good idea.
@property(nonatomic, strong) GRPCChannel *channel; GRPCChannel *_channel;
@end
@implementation GRPCHost
+ (instancetype)hostWithAddress:(NSString *)address {
return [[self alloc] initWithAddress:address];
} }
- (instancetype)init { + (nullable instancetype)hostWithAddress:(NSString *)address {
return [self initWithAddress:nil]; return [[self alloc] initWithAddress:address];
} }
// Default initializer. // Default initializer.
- (instancetype)initWithAddress:(NSString *)address { - (nullable instancetype)initWithAddress:(NSString *)address {
if (!address) { if (!address) {
return nil; return nil;
} }
@ -95,46 +92,45 @@
return self; return self;
} }
- (grpc_call *)unmanagedCallWithPath:(NSString *)path completionQueue:(GRPCCompletionQueue *)queue { - (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path
if (!queue || !path || !self.channel) { completionQueue:(GRPCCompletionQueue *)queue {
return NULL; GRPCChannel *channel;
// This is racing -[GRPCHost disconnect].
@synchronized(self) {
if (!_channel) {
_channel = [self newChannel];
} }
return grpc_channel_create_call(self.channel.unmanagedChannel, channel = _channel;
NULL, GRPC_PROPAGATE_DEFAULTS, }
queue.unmanagedQueue, return [channel unmanagedCallWithPath:path completionQueue:queue];
path.UTF8String,
self.hostName.UTF8String,
gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
} }
- (GRPCChannel *)channel { - (NSDictionary *)channelArgs {
// Create it lazily, because we don't want to open a connection just because someone is
// configuring a host.
if (!_channel) {
NSMutableDictionary *args = [NSMutableDictionary dictionary]; NSMutableDictionary *args = [NSMutableDictionary dictionary];
// TODO(jcanizales): Add OS and device information (see // TODO(jcanizales): Add OS and device information (see
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#user-agents ). // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#user-agents ).
NSString *userAgent = @"grpc-objc/" GRPC_OBJC_VERSION_STRING; NSString *userAgent = @"grpc-objc/" GRPC_OBJC_VERSION_STRING;
if (_userAgentPrefix) { if (_userAgentPrefix) {
userAgent = [@[_userAgentPrefix, userAgent] componentsJoinedByString:@" "]; userAgent = [_userAgentPrefix stringByAppendingFormat:@" %@", userAgent];
} }
args[@GRPC_ARG_PRIMARY_USER_AGENT_STRING] = userAgent; args[@GRPC_ARG_PRIMARY_USER_AGENT_STRING] = userAgent;
if (_secure) { if (_secure && _hostNameOverride) {
if (_hostNameOverride) {
args[@GRPC_SSL_TARGET_NAME_OVERRIDE_ARG] = _hostNameOverride; args[@GRPC_SSL_TARGET_NAME_OVERRIDE_ARG] = _hostNameOverride;
} }
return args;
}
_channel = [GRPCChannel secureChannelWithHost:_address - (GRPCChannel *)newChannel {
NSDictionary *args = [self channelArgs];
if (_secure) {
return [GRPCChannel secureChannelWithHost:_address
pathToCertificates:_pathToCertificates pathToCertificates:_pathToCertificates
channelArgs:args]; channelArgs:args];
} else { } else {
_channel = [GRPCChannel insecureChannelWithHost:_address channelArgs:args]; return [GRPCChannel insecureChannelWithHost:_address channelArgs:args];
}
} }
return _channel;
} }
- (NSString *)hostName { - (NSString *)hostName {
@ -142,7 +138,16 @@
return _hostNameOverride ?: _address; return _hostNameOverride ?: _address;
} }
- (void)disconnect {
// This is racing -[GRPCHost unmanagedCallWithPath:completionQueue:].
@synchronized(self) {
_channel = nil;
}
}
// TODO(jcanizales): Don't let set |secure| to |NO| if |pathToCertificates| or |hostNameOverride| // TODO(jcanizales): Don't let set |secure| to |NO| if |pathToCertificates| or |hostNameOverride|
// have been set. Don't let set either of the latter if |secure| has been set to |NO|. // have been set. Don't let set either of the latter if |secure| has been set to |NO|.
@end @end
NS_ASSUME_NONNULL_END

@ -0,0 +1,65 @@
/*
*
* Copyright 2016, 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.
*
*/
/**
* "X-macro" file that lists the flags names of Apple's Network Reachability API, along with a nice
* Objective-C method name used to query each of them.
*
* Example usage: To generate a dictionary from flag value to name, one can do:
NSDictionary *flagNames = @{
#define GRPC_XMACRO_ITEM(methodName, FlagName) \
@(kSCNetworkReachabilityFlags ## FlagName): @#methodName,
#include "GRXReachabilityFlagNames.xmacro.h"
#undef GRPC_XMACRO_ITEM
};
XCTAssertEqualObjects(flagNames[@(kSCNetworkReachabilityFlagsIsWWAN)], @"isCell");
*/
#ifndef GRPC_XMACRO_ITEM
#error This file is to be used with the "X-macro" pattern: Please #define \
GRPC_XMACRO_ITEM(methodName, FlagName), then #include this file, and then #undef \
GRPC_XMACRO_ITEM.
#endif
GRPC_XMACRO_ITEM(isCell, IsWWAN)
GRPC_XMACRO_ITEM(reachable, Reachable)
GRPC_XMACRO_ITEM(transientConnection, TransientConnection)
GRPC_XMACRO_ITEM(connectionRequired, ConnectionRequired)
GRPC_XMACRO_ITEM(connectionOnTraffic, ConnectionOnTraffic)
GRPC_XMACRO_ITEM(interventionRequired, InterventionRequired)
GRPC_XMACRO_ITEM(connectionOnDemand, ConnectionOnDemand)
GRPC_XMACRO_ITEM(isLocalAddress, IsLocalAddress)
GRPC_XMACRO_ITEM(isDirect, IsDirect)

@ -34,7 +34,6 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#include <grpc/grpc.h> #include <grpc/grpc.h>
#import "GRPCChannel.h"
#import "GRPCRequestHeaders.h" #import "GRPCRequestHeaders.h"
@interface GRPCOperation : NSObject @interface GRPCOperation : NSObject
@ -94,4 +93,5 @@
- (void)startBatchWithOperations:(NSArray *)ops; - (void)startBatchWithOperations:(NSArray *)ops;
- (void)cancel; - (void)cancel;
@end @end

@ -1,6 +1,6 @@
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2015-2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -42,11 +42,42 @@
if (!handler) { if (!handler) {
return [[self alloc] init]; return [[self alloc] init];
} }
return [[self alloc] initWithValueHandler:^(id value) { // We nilify this variable when the block is invoked, so that handler is only invoked once even if
handler(value, nil); // the writer tries to write multiple values.
} completionHandler:^(NSError *errorOrNil) { __block GRXEventHandler eventHandler = ^(BOOL done, id value, NSError *error) {
if (errorOrNil) { // Nillify eventHandler before invoking handler, in case the latter causes the former to be
handler(nil, errorOrNil); // executed recursively. Because blocks can be deallocated even during execution, we have to
// first retain handler locally to guarantee it's valid.
// TODO(jcanizales): Just turn this craziness into a simple subclass of GRXWriteable.
GRXSingleHandler singleHandler = handler;
eventHandler = nil;
if (value) {
singleHandler(value, nil);
} else if (error) {
singleHandler(nil, error);
} else {
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: @"The writer finished without producing any value."
};
// Even though RxLibrary is independent of gRPC, the domain and code here are, for the moment,
// set to the values of kGRPCErrorDomain and GRPCErrorCodeInternal. This way, the error formed
// is the one user of gRPC would expect if the server failed to produce a response.
//
// TODO(jcanizales): Figure out a way to keep errors of RxLibrary generic without making users
// of gRPC take care of two different error domains and error code enums. A possibility is to
// add error handling to GRXWriters or GRXWriteables, and use them to translate errors between
// the two domains.
static NSString *kGRPCErrorDomain = @"io.grpc";
static NSUInteger kGRPCErrorCodeInternal = 13;
singleHandler(nil, [NSError errorWithDomain:kGRPCErrorDomain
code:kGRPCErrorCodeInternal
userInfo:userInfo]);
}
};
return [self writeableWithEventHandler:^(BOOL done, id value, NSError *error) {
if (eventHandler) {
eventHandler(done, value, error);
} }
}]; }];
} }

@ -273,10 +273,12 @@ static ProtoMethod *kUnaryCallMethod;
id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
XCTAssertNotNil(value, @"nil value received as response."); XCTAssertNotNil(value, @"nil value received as response.");
XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value); XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value);
/* This test needs to be more clever in regards to changing the version of the core.
XCTAssertEqualObjects(call.responseHeaders[@"x-grpc-test-echo-useragent"], XCTAssertEqualObjects(call.responseHeaders[@"x-grpc-test-echo-useragent"],
@"Foo grpc-objc/0.13.0 grpc-c/0.14.0-dev (ios)", @"Foo grpc-objc/0.13.0 grpc-c/0.14.0-dev (ios)",
@"Did not receive expected user agent %@", @"Did not receive expected user agent %@",
call.responseHeaders[@"x-grpc-test-echo-useragent"]); call.responseHeaders[@"x-grpc-test-echo-useragent"]);
*/
[response fulfill]; [response fulfill];
} completionHandler:^(NSError *errorOrNil) { } completionHandler:^(NSError *errorOrNil) {
XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil); XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);

@ -64,6 +64,8 @@
} }
@end @end
// TODO(jcanizales): Split into one file per tested class.
@interface RxLibraryUnitTests : XCTestCase @interface RxLibraryUnitTests : XCTestCase
@end @end
@ -79,6 +81,7 @@
// If: // If:
id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block]; id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
[writeable writeValue:anyValue]; [writeable writeValue:anyValue];
[writeable writesFinishedWithError:nil];
// Then: // Then:
XCTAssertEqual(handler.timesCalled, 1); XCTAssertEqual(handler.timesCalled, 1);
@ -101,6 +104,54 @@
XCTAssertEqualObjects(handler.errorOrNil, anyError); XCTAssertEqualObjects(handler.errorOrNil, anyError);
} }
- (void)testWriteableSingleHandlerIsCalledOnlyOnce_ValueThenError {
// Given:
CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
id anyValue = @7;
NSError *anyError = [NSError errorWithDomain:@"domain" code:7 userInfo:nil];
// If:
id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
[writeable writeValue:anyValue];
[writeable writesFinishedWithError:anyError];
// Then:
XCTAssertEqual(handler.timesCalled, 1);
XCTAssertEqualObjects(handler.value, anyValue);
XCTAssertEqualObjects(handler.errorOrNil, nil);
}
- (void)testWriteableSingleHandlerIsCalledOnlyOnce_ValueThenValue {
// Given:
CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
id anyValue = @7;
// If:
id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
[writeable writeValue:anyValue];
[writeable writeValue:anyValue];
[writeable writesFinishedWithError:nil];
// Then:
XCTAssertEqual(handler.timesCalled, 1);
XCTAssertEqualObjects(handler.value, anyValue);
XCTAssertEqualObjects(handler.errorOrNil, nil);
}
- (void)testWriteableSingleHandlerFailsOnEmptyWriter {
// Given:
CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
// If:
id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
[writeable writesFinishedWithError:nil];
// Then:
XCTAssertEqual(handler.timesCalled, 1);
XCTAssertEqualObjects(handler.value, nil);
XCTAssertNotNil(handler.errorOrNil);
}
#pragma mark BufferedPipe #pragma mark BufferedPipe
- (void)testBufferedPipePropagatesValue { - (void)testBufferedPipePropagatesValue {

@ -9,14 +9,21 @@ Beta
## Environment ## Environment
Prerequisite: PHP 5.5 or later, `phpunit`, `pecl` Prerequisite: `php` >=5.5, `phpize`, `pecl`, `phpunit`
**Linux:** **Linux (Debian):**
```sh ```sh
$ sudo apt-get install php5 php5-dev php-pear $ sudo apt-get install php5 php5-dev php-pear
``` ```
**Linux (CentOS):**
```sh
$ yum install php55w
$ yum --enablerepo=remi,remi-php55 install php-devel php-pear
```
**Mac OS X:** **Mac OS X:**
```sh ```sh
@ -24,11 +31,11 @@ $ curl -O http://pear.php.net/go-pear.phar
$ sudo php -d detect_unicode=0 go-pear.phar $ sudo php -d detect_unicode=0 go-pear.phar
``` ```
**PHPUnit: (Both Linux and Mac OS X)** **PHPUnit:**
```sh ```sh
$ curl https://phar.phpunit.de/phpunit.phar -o phpunit.phar $ wget https://phar.phpunit.de/phpunit-old.phar
$ chmod +x phpunit.phar $ chmod +x phpunit-old.phar
$ sudo mv phpunit.phar /usr/local/bin/phpunit $ sudo mv phpunit-old.phar /usr/bin/phpunit
``` ```
## Quick Install ## Quick Install
@ -39,15 +46,22 @@ Install the gRPC PHP extension
sudo pecl install grpc-beta sudo pecl install grpc-beta
``` ```
This will compile and install the gRPC PHP extension into the standard PHP extension directory. You should be able to run the [unit tests](#unit-tests), with the PHP extension installed.
To run tests with generated stub code from `.proto` files, you will also need the `composer`, `protoc` and `protoc-gen-php` binaries. You can find out how to get these [below](#generated-code-tests).
## Build from Source ## Build from Source
### gRPC C core library
Clone this repository Clone this repository
```sh ```sh
$ git clone https://github.com/grpc/grpc.git $ git clone https://github.com/grpc/grpc.git
``` ```
Build and install the gRPC C core libraries Build and install the gRPC C core library
```sh ```sh
$ cd grpc $ cd grpc
@ -56,20 +70,15 @@ $ make
$ sudo make install $ sudo make install
``` ```
Note: you may encounter a warning about the Protobuf compiler `protoc` 3.0.0+ not being installed. The following might help, and will be useful later on when we need to compile the `protoc-gen-php` tool. ### gRPC PHP extension
```sh Install the gRPC PHP extension from PECL
$ cd grpc/third_party/protobuf
$ sudo make install # 'make' should have been run by core grpc
```
Install the gRPC PHP extension
```sh ```sh
$ sudo pecl install grpc-beta $ sudo pecl install grpc-beta
``` ```
OR Or, compile from source
```sh ```sh
$ cd grpc/src/php/ext/grpc $ cd grpc/src/php/ext/grpc
@ -79,58 +88,98 @@ $ make
$ sudo make install $ sudo make install
``` ```
### Update php.ini
Add this line to your `php.ini` file, e.g. `/etc/php5/cli/php.ini` Add this line to your `php.ini` file, e.g. `/etc/php5/cli/php.ini`
```sh ```sh
extension=grpc.so extension=grpc.so
``` ```
Install Composer ## Unit Tests
You will need the source code to run tests
```sh
$ git clone https://github.com/grpc/grpc.git
$ cd grpc
$ git pull --recurse-submodules && git submodule update --init --recursive
```
Run unit tests
```sh ```sh
$ cd grpc/src/php $ cd grpc/src/php
$ ./bin/run_tests.sh
```
## Generated Code Tests
This section specifies the prerequisites for running the generated code tests, as well as how to run the tests themselves.
### Composer
If you don't have it already, install `composer` to pull in some runtime dependencies based on the `composer.json` file.
```sh
$ curl -sS https://getcomposer.org/installer | php $ curl -sS https://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer $ sudo mv composer.phar /usr/local/bin/composer
$ cd grpc/src/php
$ composer install $ composer install
``` ```
## Unit Tests ### Protobuf compiler
Run unit tests Again if you don't have it already, you need to install the protobuf compiler `protoc`, version 3.0.0+.
If you compiled the gRPC C core library from source above, the `protoc` binary should have been installed as well. If it hasn't been installed, you can run the following commands to install it.
```sh ```sh
$ cd grpc/src/php $ cd grpc/third_party/protobuf
$ ./bin/run_tests.sh $ sudo make install # 'make' should have been run by core grpc
``` ```
## Generated Code Tests Alternatively, you can download `protoc` binaries from [the protocol buffers Github repository](https://github.com/google/protobuf/releases).
Install `protoc-gen-php`
### PHP protobuf compiler
You need to install `protoc-gen-php` to generate stub class `.php` files from service definition `.proto` files.
```sh ```sh
$ cd grpc/src/php/vendor/datto/protobuf-php $ cd grpc/src/php/vendor/datto/protobuf-php # if you had run `composer install` in the previous step
OR
$ git clone https://github.com/stanley-cheung/Protobuf-PHP # clone from github repo
$ gem install rake ronn $ gem install rake ronn
$ rake pear:package version=1.0 $ rake pear:package version=1.0
$ sudo pear install Protobuf-1.0.tgz $ sudo pear install Protobuf-1.0.tgz
``` ```
Generate client stub code ### Client Stub
Generate client stub classes from `.proto` files
```sh ```sh
$ cd grpc/src/php $ cd grpc/src/php
$ ./bin/generate_proto_php.sh $ ./bin/generate_proto_php.sh
``` ```
Run a local server serving the math services ### Run test server
- Please see [Node][] on how to run an example server Run a local server serving the math services. Please see [Node][] for how to run an example server.
```sh ```sh
$ cd grpc/src/node $ cd grpc
$ npm install $ npm install
$ nodejs examples/math_server.js $ nodejs src/node/test/math/math_server.js
``` ```
### Run test client
Run the generated code tests Run the generated code tests
```sh ```sh
@ -161,13 +210,15 @@ $ sudo service apache2 restart
Make sure the Node math server is still running, as above. Make sure the Node math server is still running, as above.
```sh ```sh
$ cd grpc/src/node $ cd grpc
$ nodejs examples/math_server.js $ npm install
$ nodejs src/node/test/math/math_server.js
``` ```
Make sure you have run `composer install` to generate the `vendor/autoload.php` file Make sure you have run `composer install` to generate the `vendor/autoload.php` file
```sh ```sh
$ cd grpc/src/php
$ composer install $ composer install
``` ```
@ -229,13 +280,15 @@ $ sudo service php5-fpm restart
Make sure the Node math server is still running, as above. Make sure the Node math server is still running, as above.
```sh ```sh
$ cd grpc/src/node $ cd grpc
$ nodejs examples/math_server.js $ npm install
$ nodejs src/node/test/math/math_server.js
``` ```
Make sure you have run `composer install` to generate the `vendor/autoload.php` file Make sure you have run `composer install` to generate the `vendor/autoload.php` file
```sh ```sh
$ cd grpc/src/php
$ composer install $ composer install
``` ```

@ -1,7 +1,9 @@
{ {
"name": "grpc/grpc", "name": "grpc/grpc",
"type": "library",
"description": "gRPC library for PHP", "description": "gRPC library for PHP",
"version": "0.6.0", "version": "0.14.0",
"keywords": ["rpc"],
"homepage": "http://grpc.io", "homepage": "http://grpc.io",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"repositories": [ "repositories": [
@ -13,7 +15,7 @@
"require": { "require": {
"php": ">=5.5.0", "php": ">=5.5.0",
"datto/protobuf-php": "dev-master", "datto/protobuf-php": "dev-master",
"google/auth": "dev-master" "google/auth": "v0.7"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

@ -1,67 +0,0 @@
gRPC PHP Extension
==================
# Requirements
* PHP 5.5+
* [gRPC core library](https://github.com/grpc/grpc) 0.11.0
# Installation
## Install PHP 5
```
$ sudo apt-get install git php5 php5-dev php-pear unzip
```
## Compile gRPC Core Library
Clone the gRPC source code repository
```
$ git clone https://github.com/grpc/grpc.git
```
Build and install the gRPC C core libraries
```sh
$ cd grpc
$ git checkout --track origin/release-0_11
$ git pull --recurse-submodules && git submodule update --init --recursive
$ make
$ sudo make install
```
Note: you may encounter a warning about the Protobuf compiler `protoc` 3.0.0+ not being installed. The following might help, and will be useful later on when we need to compile the `protoc-gen-php` tool.
```sh
$ cd grpc/third_party/protobuf
$ sudo make install # 'make' should have been run by core grpc
```
## Install the gRPC PHP extension
Quick install
```sh
$ sudo pecl install grpc
```
Note: before a stable release, you may need to do
```sh
$ sudo pecl install grpc-beta
```
OR
Compile from source
```sh
$ # from grpc
$ cd src/php/ext/grpc
$ phpize
$ ./configure
$ make
$ sudo make install
```

@ -1,7 +1,7 @@
<?php <?php
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2015-2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -43,7 +43,9 @@ function p($line)
$host = 'localhost:50051'; $host = 'localhost:50051';
p("Connecting to host: $host"); p("Connecting to host: $host");
$client = new math\MathClient($host, []); $client = new math\MathClient($host, [
'credentials' => Grpc\ChannelCredentials::createInsecure()
]);
p('Client class: '.get_class($client)); p('Client class: '.get_class($client));
p(''); p('');

@ -42,6 +42,7 @@ message RequestParams {
bool echo_peer = 7; bool echo_peer = 7;
string expected_client_identity = 8; // will force check_auth_context. string expected_client_identity = 8; // will force check_auth_context.
bool skip_cancelled_check = 9; bool skip_cancelled_check = 9;
string expected_transport_security_type = 10;
} }
message EchoRequest { message EchoRequest {

@ -6,7 +6,7 @@ Package for gRPC Python.
Installation Installation
------------ ------------
gRPC Python is available for Linux and Mac OS X running Python 2.7. gRPC Python is available for Linux, Mac OS X, and Windows running Python 2.7.
From PyPI From PyPI
~~~~~~~~~ ~~~~~~~~~
@ -23,11 +23,15 @@ Else system wide (on Ubuntu)...
$ sudo pip install grpcio $ sudo pip install grpcio
n.b. On Windows and on Mac OS X one *must* have a recent release of :code:`pip`
to retrieve the proper wheel from PyPI. Be sure to upgrade to the latest
version!
From Source From Source
~~~~~~~~~~~ ~~~~~~~~~~~
Building from source requires that you have the Python headers (usually a Building from source requires that you have the Python headers (usually a
package named `python-dev`). package named :code:`python-dev`).
:: ::
@ -36,8 +40,8 @@ package named `python-dev`).
$ cd $REPO_ROOT $ cd $REPO_ROOT
$ pip install . $ pip install .
Note that `$REPO_ROOT` can be assigned to whatever directory name floats your Note that :code:`$REPO_ROOT` can be assigned to whatever directory name floats
fancy. your fancy.
Troubleshooting Troubleshooting
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~

@ -119,8 +119,7 @@ class SphinxDocumentation(setuptools.Command):
import sphinx import sphinx
import sphinx.apidoc import sphinx.apidoc
metadata = self.distribution.metadata metadata = self.distribution.metadata
src_dir = os.path.join( src_dir = os.path.join(PYTHON_STEM, 'grpc')
PYTHON_STEM, self.distribution.package_dir[''], 'grpc')
sys.path.append(src_dir) sys.path.append(src_dir)
sphinx.apidoc.main([ sphinx.apidoc.main([
'', '--force', '--full', '-H', metadata.name, '-A', metadata.author, '', '--force', '--full', '-H', metadata.name, '-A', metadata.author,

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

Loading…
Cancel
Save