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

pull/2131/head
Abhishek Kumar 10 years ago
commit 186e7b4d54
  1. 25
      BUILD
  2. 2
      INSTALL
  3. 1788
      Makefile
  4. 66
      build.json
  5. 1
      composer.json
  6. 14
      gRPC.podspec
  7. 12
      include/grpc++/channel_arguments.h
  8. 2
      include/grpc++/config.h
  9. 6
      include/grpc++/credentials.h
  10. 82
      include/grpc++/dynamic_thread_pool.h
  11. 2
      include/grpc++/impl/sync_no_cxx11.h
  12. 3
      include/grpc++/server_context.h
  13. 3
      include/grpc++/server_credentials.h
  14. 43
      include/grpc/census.h
  15. 41
      include/grpc/grpc.h
  16. 19
      include/grpc/grpc_security.h
  17. 6
      include/grpc/support/host_port.h
  18. 12
      include/grpc/support/port_platform.h
  19. 3
      include/grpc/support/time.h
  20. 18
      src/compiler/csharp_generator.cc
  21. 2
      src/compiler/python_generator.cc
  22. 2
      src/core/census/grpc_context.c
  23. 19
      src/core/census/initialize.c
  24. 21
      src/core/census/record_stat.c
  25. 34
      src/core/census/rpc_stat_id.h
  26. 5
      src/core/channel/channel_stack.c
  27. 5
      src/core/channel/channel_stack.h
  28. 198
      src/core/channel/client_channel.c
  29. 14
      src/core/channel/client_channel.h
  30. 15
      src/core/channel/compress_filter.c
  31. 6
      src/core/channel/connected_channel.c
  32. 77
      src/core/channel/http_client_filter.c
  33. 9
      src/core/channel/http_server_filter.c
  34. 1
      src/core/channel/noop_filter.c
  35. 4
      src/core/client_config/README.md
  36. 118
      src/core/client_config/lb_policies/pick_first.c
  37. 15
      src/core/client_config/lb_policy.c
  38. 12
      src/core/client_config/lb_policy.h
  39. 299
      src/core/client_config/resolvers/sockaddr_resolver.c
  40. 6
      src/core/client_config/resolvers/sockaddr_resolver.h
  41. 195
      src/core/client_config/resolvers/unix_resolver_posix.c
  42. 74
      src/core/client_config/subchannel.c
  43. 3
      src/core/client_config/subchannel.h
  44. 12
      src/core/iomgr/alarm.c
  45. 8
      src/core/iomgr/endpoint.c
  46. 6
      src/core/iomgr/endpoint.h
  47. 8
      src/core/iomgr/endpoint_pair_posix.c
  48. 6
      src/core/iomgr/endpoint_pair_windows.c
  49. 12
      src/core/iomgr/iomgr.c
  50. 4
      src/core/iomgr/pollset_posix.c
  51. 10
      src/core/iomgr/pollset_set_posix.c
  52. 2
      src/core/iomgr/pollset_windows.c
  53. 33
      src/core/iomgr/sockaddr_utils.c
  54. 2
      src/core/iomgr/sockaddr_utils.h
  55. 47
      src/core/iomgr/tcp_client_posix.c
  56. 7
      src/core/iomgr/tcp_client_windows.c
  57. 35
      src/core/iomgr/tcp_posix.c
  58. 3
      src/core/iomgr/tcp_posix.h
  59. 7
      src/core/iomgr/tcp_server_posix.c
  60. 51
      src/core/iomgr/tcp_server_windows.c
  61. 27
      src/core/iomgr/tcp_windows.c
  62. 2
      src/core/iomgr/tcp_windows.h
  63. 18
      src/core/security/client_auth_filter.c
  64. 31
      src/core/security/credentials.c
  65. 13
      src/core/security/credentials.h
  66. 3
      src/core/security/google_default_credentials.c
  67. 17
      src/core/security/secure_endpoint.c
  68. 7
      src/core/security/security_connector.c
  69. 1
      src/core/security/security_connector.h
  70. 8
      src/core/security/server_auth_filter.c
  71. 10
      src/core/support/host_port.c
  72. 35
      src/core/support/stack_lockfree.c
  73. 3
      src/core/support/sync_posix.c
  74. 4
      src/core/support/sync_win32.c
  75. 27
      src/core/support/time.c
  76. 2
      src/core/support/time_posix.c
  77. 2
      src/core/support/time_win32.c
  78. 20
      src/core/surface/call.c
  79. 7
      src/core/surface/call.h
  80. 8
      src/core/surface/call_log_batch.c
  81. 37
      src/core/surface/channel.c
  82. 2
      src/core/surface/channel.h
  83. 191
      src/core/surface/channel_connectivity.c
  84. 11
      src/core/surface/channel_create.c
  85. 4
      src/core/surface/completion_queue.c
  86. 14
      src/core/surface/init.c
  87. 18
      src/core/surface/lame_client.c
  88. 13
      src/core/surface/secure_channel_create.c
  89. 30
      src/core/surface/server.c
  90. 2
      src/core/transport/chttp2/frame_data.c
  91. 22
      src/core/transport/chttp2/internal.h
  92. 7
      src/core/transport/chttp2/parsing.c
  93. 13
      src/core/transport/chttp2/stream_encoder.c
  94. 68
      src/core/transport/chttp2/stream_lists.c
  95. 52
      src/core/transport/chttp2/writing.c
  96. 76
      src/core/transport/chttp2_transport.c
  97. 44
      src/core/transport/connectivity_state.c
  98. 13
      src/core/transport/connectivity_state.h
  99. 41
      src/core/transport/metadata.c
  100. 5
      src/core/transport/metadata.h
  101. Some files were not shown because too many files have changed in this diff Show More

25
BUILD

@ -168,7 +168,7 @@ cc_library(
"src/core/client_config/resolver_factory.h", "src/core/client_config/resolver_factory.h",
"src/core/client_config/resolver_registry.h", "src/core/client_config/resolver_registry.h",
"src/core/client_config/resolvers/dns_resolver.h", "src/core/client_config/resolvers/dns_resolver.h",
"src/core/client_config/resolvers/unix_resolver_posix.h", "src/core/client_config/resolvers/sockaddr_resolver.h",
"src/core/client_config/subchannel.h", "src/core/client_config/subchannel.h",
"src/core/client_config/subchannel_factory.h", "src/core/client_config/subchannel_factory.h",
"src/core/client_config/uri_parser.h", "src/core/client_config/uri_parser.h",
@ -246,6 +246,7 @@ cc_library(
"src/core/transport/transport.h", "src/core/transport/transport.h",
"src/core/transport/transport_impl.h", "src/core/transport/transport_impl.h",
"src/core/census/context.h", "src/core/census/context.h",
"src/core/census/rpc_stat_id.h",
"src/core/httpcli/format_request.c", "src/core/httpcli/format_request.c",
"src/core/httpcli/httpcli.c", "src/core/httpcli/httpcli.c",
"src/core/httpcli/httpcli_security_connector.c", "src/core/httpcli/httpcli_security_connector.c",
@ -287,7 +288,7 @@ cc_library(
"src/core/client_config/resolver_factory.c", "src/core/client_config/resolver_factory.c",
"src/core/client_config/resolver_registry.c", "src/core/client_config/resolver_registry.c",
"src/core/client_config/resolvers/dns_resolver.c", "src/core/client_config/resolvers/dns_resolver.c",
"src/core/client_config/resolvers/unix_resolver_posix.c", "src/core/client_config/resolvers/sockaddr_resolver.c",
"src/core/client_config/subchannel.c", "src/core/client_config/subchannel.c",
"src/core/client_config/subchannel_factory.c", "src/core/client_config/subchannel_factory.c",
"src/core/client_config/uri_parser.c", "src/core/client_config/uri_parser.c",
@ -342,6 +343,7 @@ cc_library(
"src/core/surface/call_details.c", "src/core/surface/call_details.c",
"src/core/surface/call_log_batch.c", "src/core/surface/call_log_batch.c",
"src/core/surface/channel.c", "src/core/surface/channel.c",
"src/core/surface/channel_connectivity.c",
"src/core/surface/channel_create.c", "src/core/surface/channel_create.c",
"src/core/surface/completion_queue.c", "src/core/surface/completion_queue.c",
"src/core/surface/event_string.c", "src/core/surface/event_string.c",
@ -381,6 +383,7 @@ cc_library(
"src/core/transport/transport_op_string.c", "src/core/transport/transport_op_string.c",
"src/core/census/context.c", "src/core/census/context.c",
"src/core/census/initialize.c", "src/core/census/initialize.c",
"src/core/census/record_stat.c",
], ],
hdrs = [ hdrs = [
"include/grpc/grpc_security.h", "include/grpc/grpc_security.h",
@ -424,7 +427,7 @@ cc_library(
"src/core/client_config/resolver_factory.h", "src/core/client_config/resolver_factory.h",
"src/core/client_config/resolver_registry.h", "src/core/client_config/resolver_registry.h",
"src/core/client_config/resolvers/dns_resolver.h", "src/core/client_config/resolvers/dns_resolver.h",
"src/core/client_config/resolvers/unix_resolver_posix.h", "src/core/client_config/resolvers/sockaddr_resolver.h",
"src/core/client_config/subchannel.h", "src/core/client_config/subchannel.h",
"src/core/client_config/subchannel_factory.h", "src/core/client_config/subchannel_factory.h",
"src/core/client_config/uri_parser.h", "src/core/client_config/uri_parser.h",
@ -502,6 +505,7 @@ cc_library(
"src/core/transport/transport.h", "src/core/transport/transport.h",
"src/core/transport/transport_impl.h", "src/core/transport/transport_impl.h",
"src/core/census/context.h", "src/core/census/context.h",
"src/core/census/rpc_stat_id.h",
"src/core/surface/init_unsecure.c", "src/core/surface/init_unsecure.c",
"src/core/census/grpc_context.c", "src/core/census/grpc_context.c",
"src/core/channel/channel_args.c", "src/core/channel/channel_args.c",
@ -520,7 +524,7 @@ cc_library(
"src/core/client_config/resolver_factory.c", "src/core/client_config/resolver_factory.c",
"src/core/client_config/resolver_registry.c", "src/core/client_config/resolver_registry.c",
"src/core/client_config/resolvers/dns_resolver.c", "src/core/client_config/resolvers/dns_resolver.c",
"src/core/client_config/resolvers/unix_resolver_posix.c", "src/core/client_config/resolvers/sockaddr_resolver.c",
"src/core/client_config/subchannel.c", "src/core/client_config/subchannel.c",
"src/core/client_config/subchannel_factory.c", "src/core/client_config/subchannel_factory.c",
"src/core/client_config/uri_parser.c", "src/core/client_config/uri_parser.c",
@ -575,6 +579,7 @@ cc_library(
"src/core/surface/call_details.c", "src/core/surface/call_details.c",
"src/core/surface/call_log_batch.c", "src/core/surface/call_log_batch.c",
"src/core/surface/channel.c", "src/core/surface/channel.c",
"src/core/surface/channel_connectivity.c",
"src/core/surface/channel_create.c", "src/core/surface/channel_create.c",
"src/core/surface/completion_queue.c", "src/core/surface/completion_queue.c",
"src/core/surface/event_string.c", "src/core/surface/event_string.c",
@ -614,6 +619,7 @@ cc_library(
"src/core/transport/transport_op_string.c", "src/core/transport/transport_op_string.c",
"src/core/census/context.c", "src/core/census/context.c",
"src/core/census/initialize.c", "src/core/census/initialize.c",
"src/core/census/record_stat.c",
], ],
hdrs = [ hdrs = [
"include/grpc/byte_buffer.h", "include/grpc/byte_buffer.h",
@ -661,6 +667,7 @@ cc_library(
"src/cpp/proto/proto_utils.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/fixed_size_thread_pool.cc", "src/cpp/server/fixed_size_thread_pool.cc",
"src/cpp/server/insecure_server_credentials.cc", "src/cpp/server/insecure_server_credentials.cc",
"src/cpp/server/server.cc", "src/cpp/server/server.cc",
@ -686,6 +693,7 @@ cc_library(
"include/grpc++/config_protobuf.h", "include/grpc++/config_protobuf.h",
"include/grpc++/create_channel.h", "include/grpc++/create_channel.h",
"include/grpc++/credentials.h", "include/grpc++/credentials.h",
"include/grpc++/dynamic_thread_pool.h",
"include/grpc++/fixed_size_thread_pool.h", "include/grpc++/fixed_size_thread_pool.h",
"include/grpc++/generic_stub.h", "include/grpc++/generic_stub.h",
"include/grpc++/impl/call.h", "include/grpc++/impl/call.h",
@ -746,6 +754,7 @@ cc_library(
"src/cpp/proto/proto_utils.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/fixed_size_thread_pool.cc", "src/cpp/server/fixed_size_thread_pool.cc",
"src/cpp/server/insecure_server_credentials.cc", "src/cpp/server/insecure_server_credentials.cc",
"src/cpp/server/server.cc", "src/cpp/server/server.cc",
@ -771,6 +780,7 @@ cc_library(
"include/grpc++/config_protobuf.h", "include/grpc++/config_protobuf.h",
"include/grpc++/create_channel.h", "include/grpc++/create_channel.h",
"include/grpc++/credentials.h", "include/grpc++/credentials.h",
"include/grpc++/dynamic_thread_pool.h",
"include/grpc++/fixed_size_thread_pool.h", "include/grpc++/fixed_size_thread_pool.h",
"include/grpc++/generic_stub.h", "include/grpc++/generic_stub.h",
"include/grpc++/impl/call.h", "include/grpc++/impl/call.h",
@ -998,7 +1008,7 @@ objc_library(
"src/core/client_config/resolver_factory.c", "src/core/client_config/resolver_factory.c",
"src/core/client_config/resolver_registry.c", "src/core/client_config/resolver_registry.c",
"src/core/client_config/resolvers/dns_resolver.c", "src/core/client_config/resolvers/dns_resolver.c",
"src/core/client_config/resolvers/unix_resolver_posix.c", "src/core/client_config/resolvers/sockaddr_resolver.c",
"src/core/client_config/subchannel.c", "src/core/client_config/subchannel.c",
"src/core/client_config/subchannel_factory.c", "src/core/client_config/subchannel_factory.c",
"src/core/client_config/uri_parser.c", "src/core/client_config/uri_parser.c",
@ -1053,6 +1063,7 @@ objc_library(
"src/core/surface/call_details.c", "src/core/surface/call_details.c",
"src/core/surface/call_log_batch.c", "src/core/surface/call_log_batch.c",
"src/core/surface/channel.c", "src/core/surface/channel.c",
"src/core/surface/channel_connectivity.c",
"src/core/surface/channel_create.c", "src/core/surface/channel_create.c",
"src/core/surface/completion_queue.c", "src/core/surface/completion_queue.c",
"src/core/surface/event_string.c", "src/core/surface/event_string.c",
@ -1092,6 +1103,7 @@ objc_library(
"src/core/transport/transport_op_string.c", "src/core/transport/transport_op_string.c",
"src/core/census/context.c", "src/core/census/context.c",
"src/core/census/initialize.c", "src/core/census/initialize.c",
"src/core/census/record_stat.c",
], ],
hdrs = [ hdrs = [
"include/grpc/grpc_security.h", "include/grpc/grpc_security.h",
@ -1137,7 +1149,7 @@ objc_library(
"src/core/client_config/resolver_factory.h", "src/core/client_config/resolver_factory.h",
"src/core/client_config/resolver_registry.h", "src/core/client_config/resolver_registry.h",
"src/core/client_config/resolvers/dns_resolver.h", "src/core/client_config/resolvers/dns_resolver.h",
"src/core/client_config/resolvers/unix_resolver_posix.h", "src/core/client_config/resolvers/sockaddr_resolver.h",
"src/core/client_config/subchannel.h", "src/core/client_config/subchannel.h",
"src/core/client_config/subchannel_factory.h", "src/core/client_config/subchannel_factory.h",
"src/core/client_config/uri_parser.h", "src/core/client_config/uri_parser.h",
@ -1215,6 +1227,7 @@ objc_library(
"src/core/transport/transport.h", "src/core/transport/transport.h",
"src/core/transport/transport_impl.h", "src/core/transport/transport_impl.h",
"src/core/census/context.h", "src/core/census/context.h",
"src/core/census/rpc_stat_id.h",
], ],
includes = [ includes = [
"include", "include",

@ -117,7 +117,7 @@ most Mac installations. Do the "git submodule" command listed above.
Then execute the following for all the needed build dependencies Then execute the following for all the needed build dependencies
$ sudo /opt/local/bin/port install autoconf automake libtool gflags cmake $ sudo /opt/local/bin/port install autoconf automake libtool gflags cmake
$ mkdir ~/gtest $ mkdir ~/gtest-svn
$ svn checkout http://googletest.googlecode.com/svn/trunk/ gtest-svn $ svn checkout http://googletest.googlecode.com/svn/trunk/ gtest-svn
$ mkdir mybuild $ mkdir mybuild
$ cd mybuild $ cd mybuild

1788
Makefile

File diff suppressed because one or more lines are too long

@ -18,11 +18,13 @@
"include/grpc/census.h" "include/grpc/census.h"
], ],
"headers": [ "headers": [
"src/core/census/context.h" "src/core/census/context.h",
"src/core/census/rpc_stat_id.h"
], ],
"src": [ "src": [
"src/core/census/context.c", "src/core/census/context.c",
"src/core/census/initialize.c" "src/core/census/initialize.c",
"src/core/census/record_stat.c"
] ]
}, },
{ {
@ -41,6 +43,7 @@
"include/grpc++/config_protobuf.h", "include/grpc++/config_protobuf.h",
"include/grpc++/create_channel.h", "include/grpc++/create_channel.h",
"include/grpc++/credentials.h", "include/grpc++/credentials.h",
"include/grpc++/dynamic_thread_pool.h",
"include/grpc++/fixed_size_thread_pool.h", "include/grpc++/fixed_size_thread_pool.h",
"include/grpc++/generic_stub.h", "include/grpc++/generic_stub.h",
"include/grpc++/impl/call.h", "include/grpc++/impl/call.h",
@ -88,6 +91,7 @@
"src/cpp/proto/proto_utils.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/fixed_size_thread_pool.cc", "src/cpp/server/fixed_size_thread_pool.cc",
"src/cpp/server/insecure_server_credentials.cc", "src/cpp/server/insecure_server_credentials.cc",
"src/cpp/server/server.cc", "src/cpp/server/server.cc",
@ -129,7 +133,7 @@
"src/core/client_config/resolver_factory.h", "src/core/client_config/resolver_factory.h",
"src/core/client_config/resolver_registry.h", "src/core/client_config/resolver_registry.h",
"src/core/client_config/resolvers/dns_resolver.h", "src/core/client_config/resolvers/dns_resolver.h",
"src/core/client_config/resolvers/unix_resolver_posix.h", "src/core/client_config/resolvers/sockaddr_resolver.h",
"src/core/client_config/subchannel.h", "src/core/client_config/subchannel.h",
"src/core/client_config/subchannel_factory.h", "src/core/client_config/subchannel_factory.h",
"src/core/client_config/uri_parser.h", "src/core/client_config/uri_parser.h",
@ -225,7 +229,7 @@
"src/core/client_config/resolver_factory.c", "src/core/client_config/resolver_factory.c",
"src/core/client_config/resolver_registry.c", "src/core/client_config/resolver_registry.c",
"src/core/client_config/resolvers/dns_resolver.c", "src/core/client_config/resolvers/dns_resolver.c",
"src/core/client_config/resolvers/unix_resolver_posix.c", "src/core/client_config/resolvers/sockaddr_resolver.c",
"src/core/client_config/subchannel.c", "src/core/client_config/subchannel.c",
"src/core/client_config/subchannel_factory.c", "src/core/client_config/subchannel_factory.c",
"src/core/client_config/uri_parser.c", "src/core/client_config/uri_parser.c",
@ -280,6 +284,7 @@
"src/core/surface/call_details.c", "src/core/surface/call_details.c",
"src/core/surface/call_log_batch.c", "src/core/surface/call_log_batch.c",
"src/core/surface/channel.c", "src/core/surface/channel.c",
"src/core/surface/channel_connectivity.c",
"src/core/surface/channel_create.c", "src/core/surface/channel_create.c",
"src/core/surface/completion_queue.c", "src/core/surface/completion_queue.c",
"src/core/surface/event_string.c", "src/core/surface/event_string.c",
@ -609,7 +614,6 @@
"headers": [ "headers": [
"test/cpp/util/cli_call.h", "test/cpp/util/cli_call.h",
"test/cpp/util/create_test_channel.h", "test/cpp/util/create_test_channel.h",
"test/cpp/util/fake_credentials.h",
"test/cpp/util/subprocess.h" "test/cpp/util/subprocess.h"
], ],
"src": [ "src": [
@ -618,7 +622,6 @@
"test/cpp/util/echo_duplicate.proto", "test/cpp/util/echo_duplicate.proto",
"test/cpp/util/cli_call.cc", "test/cpp/util/cli_call.cc",
"test/cpp/util/create_test_channel.cc", "test/cpp/util/create_test_channel.cc",
"test/cpp/util/fake_credentials.cc",
"test/cpp/util/subprocess.cc" "test/cpp/util/subprocess.cc"
], ],
"deps": [ "deps": [
@ -1892,6 +1895,9 @@
"grpc", "grpc",
"gpr_test_util", "gpr_test_util",
"gpr" "gpr"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -1909,6 +1915,9 @@
"grpc", "grpc",
"gpr_test_util", "gpr_test_util",
"gpr" "gpr"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -1967,6 +1976,9 @@
"grpc", "grpc",
"gpr_test_util", "gpr_test_util",
"gpr" "gpr"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -2044,6 +2056,21 @@
"gpr" "gpr"
] ]
}, },
{
"name": "dynamic_thread_pool_test",
"build": "test",
"language": "c++",
"src": [
"test/cpp/server/dynamic_thread_pool_test.cc"
],
"deps": [
"grpc_test_util",
"grpc++",
"grpc",
"gpr_test_util",
"gpr"
]
},
{ {
"name": "end2end_test", "name": "end2end_test",
"build": "test", "build": "test",
@ -2190,6 +2217,9 @@
"gpr_test_util", "gpr_test_util",
"gpr", "gpr",
"grpc++_test_config" "grpc++_test_config"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -2208,6 +2238,9 @@
"gpr_test_util", "gpr_test_util",
"gpr", "gpr",
"grpc++_test_config" "grpc++_test_config"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -2222,6 +2255,9 @@
"grpc", "grpc",
"gpr_test_util", "gpr_test_util",
"gpr" "gpr"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -2326,6 +2362,9 @@
"grpc", "grpc",
"gpr_test_util", "gpr_test_util",
"gpr" "gpr"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -2344,6 +2383,9 @@
"gpr_test_util", "gpr_test_util",
"gpr", "gpr",
"grpc++_test_config" "grpc++_test_config"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -2362,6 +2404,9 @@
"gpr_test_util", "gpr_test_util",
"gpr", "gpr",
"grpc++_test_config" "grpc++_test_config"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -2413,6 +2458,9 @@
"grpc", "grpc",
"gpr_test_util", "gpr_test_util",
"gpr" "gpr"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -2462,6 +2510,9 @@
"grpc", "grpc",
"gpr_test_util", "gpr_test_util",
"gpr" "gpr"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -2479,6 +2530,9 @@
"grpc", "grpc",
"gpr_test_util", "gpr_test_util",
"gpr" "gpr"
],
"platforms": [
"posix"
] ]
}, },
{ {

@ -2,6 +2,7 @@
"name": "grpc/grpc", "name": "grpc/grpc",
"type": "library", "type": "library",
"description": "gRPC library for PHP", "description": "gRPC library for PHP",
"version": "0.5.1",
"keywords": ["rpc"], "keywords": ["rpc"],
"homepage": "http://grpc.io", "homepage": "http://grpc.io",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",

@ -170,7 +170,7 @@ Pod::Spec.new do |s|
'src/core/client_config/resolver_factory.h', 'src/core/client_config/resolver_factory.h',
'src/core/client_config/resolver_registry.h', 'src/core/client_config/resolver_registry.h',
'src/core/client_config/resolvers/dns_resolver.h', 'src/core/client_config/resolvers/dns_resolver.h',
'src/core/client_config/resolvers/unix_resolver_posix.h', 'src/core/client_config/resolvers/sockaddr_resolver.h',
'src/core/client_config/subchannel.h', 'src/core/client_config/subchannel.h',
'src/core/client_config/subchannel_factory.h', 'src/core/client_config/subchannel_factory.h',
'src/core/client_config/uri_parser.h', 'src/core/client_config/uri_parser.h',
@ -248,6 +248,7 @@ Pod::Spec.new do |s|
'src/core/transport/transport.h', 'src/core/transport/transport.h',
'src/core/transport/transport_impl.h', 'src/core/transport/transport_impl.h',
'src/core/census/context.h', 'src/core/census/context.h',
'src/core/census/rpc_stat_id.h',
'grpc/grpc_security.h', 'grpc/grpc_security.h',
'grpc/byte_buffer.h', 'grpc/byte_buffer.h',
'grpc/byte_buffer_reader.h', 'grpc/byte_buffer_reader.h',
@ -296,7 +297,7 @@ Pod::Spec.new do |s|
'src/core/client_config/resolver_factory.c', 'src/core/client_config/resolver_factory.c',
'src/core/client_config/resolver_registry.c', 'src/core/client_config/resolver_registry.c',
'src/core/client_config/resolvers/dns_resolver.c', 'src/core/client_config/resolvers/dns_resolver.c',
'src/core/client_config/resolvers/unix_resolver_posix.c', 'src/core/client_config/resolvers/sockaddr_resolver.c',
'src/core/client_config/subchannel.c', 'src/core/client_config/subchannel.c',
'src/core/client_config/subchannel_factory.c', 'src/core/client_config/subchannel_factory.c',
'src/core/client_config/uri_parser.c', 'src/core/client_config/uri_parser.c',
@ -351,6 +352,7 @@ Pod::Spec.new do |s|
'src/core/surface/call_details.c', 'src/core/surface/call_details.c',
'src/core/surface/call_log_batch.c', 'src/core/surface/call_log_batch.c',
'src/core/surface/channel.c', 'src/core/surface/channel.c',
'src/core/surface/channel_connectivity.c',
'src/core/surface/channel_create.c', 'src/core/surface/channel_create.c',
'src/core/surface/completion_queue.c', 'src/core/surface/completion_queue.c',
'src/core/surface/event_string.c', 'src/core/surface/event_string.c',
@ -389,7 +391,8 @@ Pod::Spec.new do |s|
'src/core/transport/transport.c', 'src/core/transport/transport.c',
'src/core/transport/transport_op_string.c', 'src/core/transport/transport_op_string.c',
'src/core/census/context.c', 'src/core/census/context.c',
'src/core/census/initialize.c' 'src/core/census/initialize.c',
'src/core/census/record_stat.c'
ss.private_header_files = 'src/core/support/env.h', ss.private_header_files = 'src/core/support/env.h',
'src/core/support/file.h', 'src/core/support/file.h',
@ -434,7 +437,7 @@ Pod::Spec.new do |s|
'src/core/client_config/resolver_factory.h', 'src/core/client_config/resolver_factory.h',
'src/core/client_config/resolver_registry.h', 'src/core/client_config/resolver_registry.h',
'src/core/client_config/resolvers/dns_resolver.h', 'src/core/client_config/resolvers/dns_resolver.h',
'src/core/client_config/resolvers/unix_resolver_posix.h', 'src/core/client_config/resolvers/sockaddr_resolver.h',
'src/core/client_config/subchannel.h', 'src/core/client_config/subchannel.h',
'src/core/client_config/subchannel_factory.h', 'src/core/client_config/subchannel_factory.h',
'src/core/client_config/uri_parser.h', 'src/core/client_config/uri_parser.h',
@ -511,7 +514,8 @@ Pod::Spec.new do |s|
'src/core/transport/stream_op.h', 'src/core/transport/stream_op.h',
'src/core/transport/transport.h', 'src/core/transport/transport.h',
'src/core/transport/transport_impl.h', 'src/core/transport/transport_impl.h',
'src/core/census/context.h' 'src/core/census/context.h',
'src/core/census/rpc_stat_id.h'
ss.header_mappings_dir = '.' ss.header_mappings_dir = '.'

@ -54,6 +54,14 @@ class ChannelArguments {
ChannelArguments() {} ChannelArguments() {}
~ChannelArguments() {} ~ChannelArguments() {}
ChannelArguments(const ChannelArguments& other);
ChannelArguments& operator=(ChannelArguments other) {
Swap(other);
return *this;
}
void Swap(ChannelArguments& other);
// grpc specific channel argument setters // grpc specific channel argument setters
// Set target name override for SSL host name checking. // Set target name override for SSL host name checking.
void SetSslTargetNameOverride(const grpc::string& name); void SetSslTargetNameOverride(const grpc::string& name);
@ -73,10 +81,6 @@ class ChannelArguments {
friend class SecureCredentials; friend class SecureCredentials;
friend class testing::ChannelArgumentsTest; friend class testing::ChannelArgumentsTest;
// TODO(yangg) implement copy and assign
ChannelArguments(const ChannelArguments&);
ChannelArguments& operator=(const ChannelArguments&);
// Returns empty string when it is not set. // Returns empty string when it is not set.
grpc::string GetSslTargetNameOverride() const; grpc::string GetSslTargetNameOverride() const;

@ -79,6 +79,7 @@
#ifdef GRPC_CXX0X_NO_NULLPTR #ifdef GRPC_CXX0X_NO_NULLPTR
#include <memory> #include <memory>
namespace grpc {
const class { const class {
public: public:
template <class T> template <class T>
@ -98,6 +99,7 @@ const class {
private: private:
void operator&() const = delete; void operator&() const = delete;
} nullptr = {}; } nullptr = {};
}
#endif #endif
#ifndef GRPC_CUSTOM_STRING #ifndef GRPC_CUSTOM_STRING

@ -106,13 +106,13 @@ std::shared_ptr<Credentials> ServiceAccountCredentials(
const grpc::string& json_key, const grpc::string& scope, const grpc::string& json_key, const grpc::string& scope,
long token_lifetime_seconds); long token_lifetime_seconds);
// Builds JWT credentials. // Builds Service Account JWT Access credentials.
// json_key is the JSON key string containing the client's private key. // json_key is the JSON key string containing the client's private key.
// token_lifetime_seconds is the lifetime in seconds of each Json Web Token // token_lifetime_seconds is the lifetime in seconds of each Json Web Token
// (JWT) created with this credentials. It should not exceed // (JWT) created with this credentials. It should not exceed
// grpc_max_auth_token_lifetime or will be cropped to this value. // grpc_max_auth_token_lifetime or will be cropped to this value.
std::shared_ptr<Credentials> JWTCredentials(const grpc::string& json_key, std::shared_ptr<Credentials> ServiceAccountJWTAccessCredentials(
long token_lifetime_seconds); const grpc::string& json_key, long token_lifetime_seconds);
// Builds refresh token credentials. // Builds refresh token credentials.
// json_refresh_token is the JSON string containing the refresh token along // json_refresh_token is the JSON string containing the refresh token along

@ -0,0 +1,82 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPCXX_DYNAMIC_THREAD_POOL_H
#define GRPCXX_DYNAMIC_THREAD_POOL_H
#include <grpc++/config.h>
#include <grpc++/impl/sync.h>
#include <grpc++/impl/thd.h>
#include <grpc++/thread_pool_interface.h>
#include <list>
#include <memory>
#include <queue>
namespace grpc {
class DynamicThreadPool GRPC_FINAL : public ThreadPoolInterface {
public:
explicit DynamicThreadPool(int reserve_threads);
~DynamicThreadPool();
void Add(const std::function<void()>& callback) GRPC_OVERRIDE;
private:
class DynamicThread {
public:
DynamicThread(DynamicThreadPool *pool);
~DynamicThread();
private:
DynamicThreadPool *pool_;
std::unique_ptr<grpc::thread> thd_;
void ThreadFunc();
};
grpc::mutex mu_;
grpc::condition_variable cv_;
grpc::condition_variable shutdown_cv_;
bool shutdown_;
std::queue<std::function<void()>> callbacks_;
int reserve_threads_;
int nthreads_;
int threads_waiting_;
std::list<DynamicThread*> dead_threads_;
void ThreadFunc();
static void ReapThreads(std::list<DynamicThread*>* tlist);
};
} // namespace grpc
#endif // GRPCXX_DYNAMIC_THREAD_POOL_H

@ -87,7 +87,7 @@ class condition_variable {
~condition_variable() { gpr_cv_destroy(&cv_); } ~condition_variable() { gpr_cv_destroy(&cv_); }
void wait(lock_guard<mutex> &mu) { void wait(lock_guard<mutex> &mu) {
mu.locked = false; mu.locked = false;
gpr_cv_wait(&cv_, &mu.mu_.mu_, gpr_inf_future); gpr_cv_wait(&cv_, &mu.mu_.mu_, gpr_inf_future(GPR_CLOCK_REALTIME));
mu.locked = true; mu.locked = true;
} }
void notify_one() { gpr_cv_signal(&cv_); } void notify_one() { gpr_cv_signal(&cv_); }

@ -46,6 +46,7 @@
struct gpr_timespec; struct gpr_timespec;
struct grpc_metadata; struct grpc_metadata;
struct grpc_call; struct grpc_call;
struct census_context;
namespace grpc { namespace grpc {
@ -116,6 +117,8 @@ class ServerContext {
std::shared_ptr<const AuthContext> auth_context() const; std::shared_ptr<const AuthContext> auth_context() const;
const struct census_context* census_context() const;
private: private:
friend class ::grpc::testing::InteropContextInspector; friend class ::grpc::testing::InteropContextInspector;
friend class ::grpc::Server; friend class ::grpc::Server;

@ -58,12 +58,15 @@ class ServerCredentials {
// Options to create ServerCredentials with SSL // Options to create ServerCredentials with SSL
struct SslServerCredentialsOptions { struct SslServerCredentialsOptions {
SslServerCredentialsOptions() : force_client_auth(false) {}
struct PemKeyCertPair { struct PemKeyCertPair {
grpc::string private_key; grpc::string private_key;
grpc::string cert_chain; grpc::string cert_chain;
}; };
grpc::string pem_root_certs; grpc::string pem_root_certs;
std::vector<PemKeyCertPair> pem_key_cert_pairs; std::vector<PemKeyCertPair> pem_key_cert_pairs;
bool force_client_auth;
}; };
// Builds SSL ServerCredentials given SSL specific options // Builds SSL ServerCredentials given SSL specific options

@ -44,26 +44,30 @@
extern "C" { extern "C" {
#endif #endif
/* Identify census functionality that can be enabled via census_initialize(). */ /* Identify census features that can be enabled via census_initialize(). */
enum census_functions { enum census_features {
CENSUS_NONE = 0, /* Do not enable census. */ CENSUS_FEATURE_NONE = 0, /* Do not enable census. */
CENSUS_TRACING = 1, /* Enable census tracing. */ CENSUS_FEATURE_TRACING = 1, /* Enable census tracing. */
CENSUS_STATS = 2, /* Enable Census stats collection. */ CENSUS_FEATURE_STATS = 2, /* Enable Census stats collection. */
CENSUS_CPU = 4, /* Enable Census CPU usage collection. */ CENSUS_FEATURE_CPU = 4, /* Enable Census CPU usage collection. */
CENSUS_ALL = CENSUS_TRACING | CENSUS_STATS | CENSUS_CPU CENSUS_FEATURE_ALL =
CENSUS_FEATURE_TRACING | CENSUS_FEATURE_STATS | CENSUS_FEATURE_CPU
}; };
/* Shutdown and startup census subsystem. The 'functions' argument should be /** Shutdown and startup census subsystem. The 'features' argument should be
* the OR (|) of census_functions values. If census fails to initialize, then * the OR (|) of census_features values. If census fails to initialize, then
* census_initialize() will return a non-zero value. It is an error to call * census_initialize() will return a non-zero value. It is an error to call
* census_initialize() more than once (without an intervening * census_initialize() more than once (without an intervening
* census_shutdown()). */ * census_shutdown()). */
int census_initialize(int functions); int census_initialize(int features);
void census_shutdown(); void census_shutdown(void);
/* If any census feature has been initialized, this funtion will return a /** Return the features supported by the current census implementation (not all
* non-zero value. */ * features will be available on all platforms). */
int census_available(); int census_supported(void);
/** Return the census features currently enabled. */
int census_enabled(void);
/* Internally, Census relies on a context, which should be propagated across /* Internally, Census relies on a context, which should be propagated across
* RPC's. From the RPC subsystems viewpoint, this is an opaque data structure. * RPC's. From the RPC subsystems viewpoint, this is an opaque data structure.
@ -100,6 +104,17 @@ int census_context_deserialize(const char *buffer, census_context **context);
* future census calls will result in undefined behavior. */ * future census calls will result in undefined behavior. */
void census_context_destroy(census_context *context); void census_context_destroy(census_context *context);
/* A census statistic to be recorded comprises two parts: an ID for the
* particular statistic and the value to be recorded against it. */
typedef struct {
int id;
double value;
} census_stat;
/* Record new stats against the given context. */
void census_record_stat(census_context *context, census_stat *stats,
size_t nstats);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -126,6 +126,12 @@ typedef struct {
/** Initial sequence number for http2 transports */ /** Initial sequence number for http2 transports */
#define GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER \ #define GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER \
"grpc.http2.initial_sequence_number" "grpc.http2.initial_sequence_number"
/** Primary user agent: goes at the start of the user-agent metadata
sent on each request */
#define GRPC_ARG_PRIMARY_USER_AGENT_STRING "grpc.primary_user_agent"
/** Secondary user agent: goes at the end of the user-agent metadata
sent on each request */
#define GRPC_ARG_SECONDARY_USER_AGENT_STRING "grpc.secondary_user_agent"
/** Connectivity state of a channel. */ /** Connectivity state of a channel. */
typedef enum { typedef enum {
@ -396,6 +402,23 @@ void grpc_completion_queue_shutdown(grpc_completion_queue *cq);
drained and no threads are executing grpc_completion_queue_next */ drained and no threads are executing grpc_completion_queue_next */
void grpc_completion_queue_destroy(grpc_completion_queue *cq); void grpc_completion_queue_destroy(grpc_completion_queue *cq);
/** Check the connectivity state of a channel. */
grpc_connectivity_state grpc_channel_check_connectivity_state(
grpc_channel *channel, int try_to_connect);
/** Watch for a change in connectivity state.
Once the channel connectivity state is different from last_observed_state,
tag will be enqueued on cq with success=1.
If deadline expires BEFORE the state is changed, tag will be enqueued on cq
with success=0.
If optional_new_state is non-NULL, it will be set to the newly observed
connectivity state of the channel at the same point as tag is enqueued onto
the completion queue. */
void grpc_channel_watch_connectivity_state(
grpc_channel *channel, grpc_connectivity_state last_observed_state,
grpc_connectivity_state *optional_new_state, gpr_timespec deadline,
grpc_completion_queue *cq, void *tag);
/** Create a call given a grpc_channel, in order to call 'method'. All /** Create a call given a grpc_channel, in order to call 'method'. All
completions are sent to 'completion_queue'. 'method' and 'host' need only completions are sent to 'completion_queue'. 'method' and 'host' need only
live through the invocation of this function. */ live through the invocation of this function. */
@ -427,16 +450,30 @@ grpc_call *grpc_channel_create_registered_call(
grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops, grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
size_t nops, void *tag); size_t nops, void *tag);
/** Returns a newly allocated string representing the endpoint to which this
call is communicating with. The string is in the uri format accepted by
grpc_channel_create.
The returned string should be disposed of with gpr_free().
WARNING: this value is never authenticated or subject to any security
related code. It must not be used for any authentication related
functionality. Instead, use grpc_auth_context. */
char *grpc_call_get_peer(grpc_call *call);
/** Return a newly allocated string representing the target a channel was
created for. */
char *grpc_channel_get_target(grpc_channel *channel);
/** Create a client channel to 'target'. Additional channel level configuration /** Create a client channel to 'target'. Additional channel level configuration
MAY be provided by grpc_channel_args, though the expectation is that most MAY be provided by grpc_channel_args, though the expectation is that most
clients will want to simply pass NULL. See grpc_channel_args definition for clients will want to simply pass NULL. See grpc_channel_args definition for
more on this. The data in 'args' need only live through the invocation of more on this. The data in 'args' need only live through the invocation of
this function. */ this function. */
grpc_channel *grpc_channel_create(const char *target, grpc_channel *grpc_insecure_channel_create(const char *target,
const grpc_channel_args *args); const grpc_channel_args *args);
/** Create a lame client: this client fails every operation attempted on it. */ /** Create a lame client: this client fails every operation attempted on it. */
grpc_channel *grpc_lame_client_channel_create(void); grpc_channel *grpc_lame_client_channel_create(const char *target);
/** Close and destroy a grpc channel */ /** Close and destroy a grpc channel */
void grpc_channel_destroy(grpc_channel *channel); void grpc_channel_destroy(grpc_channel *channel);

@ -119,8 +119,8 @@ grpc_credentials *grpc_service_account_credentials_create(
- token_lifetime is the lifetime of each Json Web Token (JWT) created with - token_lifetime is the lifetime of each Json Web Token (JWT) created with
this credentials. It should not exceed grpc_max_auth_token_lifetime or this credentials. It should not exceed grpc_max_auth_token_lifetime or
will be cropped to this value. */ will be cropped to this value. */
grpc_credentials *grpc_jwt_credentials_create(const char *json_key, grpc_credentials *grpc_service_account_jwt_access_credentials_create(
gpr_timespec token_lifetime); const char *json_key, gpr_timespec token_lifetime);
/* Creates an Oauth2 Refresh Token credentials object. May return NULL if the /* Creates an Oauth2 Refresh Token credentials object. May return NULL if the
input is invalid. input is invalid.
@ -140,9 +140,6 @@ grpc_credentials *grpc_access_token_credentials_create(
grpc_credentials *grpc_iam_credentials_create(const char *authorization_token, grpc_credentials *grpc_iam_credentials_create(const char *authorization_token,
const char *authority_selector); const char *authority_selector);
/* Creates a fake transport security credentials object for testing. */
grpc_credentials *grpc_fake_transport_security_credentials_create(void);
/* --- Secure channel creation. --- */ /* --- Secure channel creation. --- */
/* The caller of the secure_channel_create functions may override the target /* The caller of the secure_channel_create functions may override the target
@ -177,14 +174,13 @@ void grpc_server_credentials_release(grpc_server_credentials *creds);
- pem_key_cert_pairs is an array private key / certificate chains of the - pem_key_cert_pairs is an array private key / certificate chains of the
server. This parameter cannot be NULL. server. This parameter cannot be NULL.
- num_key_cert_pairs indicates the number of items in the private_key_files - num_key_cert_pairs indicates the number of items in the private_key_files
and cert_chain_files parameters. It should be at least 1. */ and cert_chain_files parameters. It should be at least 1.
- force_client_auth, if set to non-zero will force the client to authenticate
with an SSL cert. Note that this option is ignored if pem_root_certs is
NULL. */
grpc_server_credentials *grpc_ssl_server_credentials_create( grpc_server_credentials *grpc_ssl_server_credentials_create(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
size_t num_key_cert_pairs); size_t num_key_cert_pairs, int force_client_auth);
/* Creates a fake server transport security credentials object for testing. */
grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
void);
/* --- Server-side secure ports. --- */ /* --- Server-side secure ports. --- */
@ -206,7 +202,6 @@ grpc_call_error grpc_call_set_credentials(grpc_call *call,
/* TODO(jboeuf): Define some well-known property names. */ /* TODO(jboeuf): Define some well-known property names. */
#define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME "transport_security_type" #define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME "transport_security_type"
#define GRPC_FAKE_TRANSPORT_SECURITY_TYPE "fake"
#define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl" #define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl"
#define GRPC_X509_CN_PROPERTY_NAME "x509_common_name" #define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"

@ -52,8 +52,10 @@ int gpr_join_host_port(char **out, const char *host, int port);
/* Given a name in the form "host:port" or "[ho:st]:port", split into hostname /* Given a name in the form "host:port" or "[ho:st]:port", split into hostname
and port number, into newly allocated strings, which must later be and port number, into newly allocated strings, which must later be
destroyed using gpr_free(). */ destroyed using gpr_free().
void gpr_split_host_port(const char *name, char **host, char **port); Return 1 on success, 0 on failure. Guarantees *host and *port == NULL on
failure. */
int gpr_split_host_port(const char *name, char **host, char **port);
#ifdef __cplusplus #ifdef __cplusplus
} }

@ -71,6 +71,7 @@
#if !defined(GPR_NO_AUTODETECT_PLATFORM) #if !defined(GPR_NO_AUTODETECT_PLATFORM)
#if defined(_WIN64) || defined(WIN64) #if defined(_WIN64) || defined(WIN64)
#define GPR_PLATFORM_STRING "windows"
#define GPR_WIN32 1 #define GPR_WIN32 1
#define GPR_ARCH_64 1 #define GPR_ARCH_64 1
#define GPR_GETPID_IN_PROCESS_H 1 #define GPR_GETPID_IN_PROCESS_H 1
@ -84,6 +85,7 @@
#endif #endif
#define GPR_WINDOWS_CRASH_HANDLER 1 #define GPR_WINDOWS_CRASH_HANDLER 1
#elif defined(_WIN32) || defined(WIN32) #elif defined(_WIN32) || defined(WIN32)
#define GPR_PLATFORM_STRING "windows"
#define GPR_ARCH_32 1 #define GPR_ARCH_32 1
#define GPR_WIN32 1 #define GPR_WIN32 1
#define GPR_GETPID_IN_PROCESS_H 1 #define GPR_GETPID_IN_PROCESS_H 1
@ -97,6 +99,7 @@
#endif #endif
#define GPR_WINDOWS_CRASH_HANDLER 1 #define GPR_WINDOWS_CRASH_HANDLER 1
#elif defined(ANDROID) || defined(__ANDROID__) #elif defined(ANDROID) || defined(__ANDROID__)
#define GPR_PLATFORM_STRING "android"
#define GPR_ANDROID 1 #define GPR_ANDROID 1
#define GPR_ARCH_32 1 #define GPR_ARCH_32 1
#define GPR_CPU_LINUX 1 #define GPR_CPU_LINUX 1
@ -117,6 +120,7 @@
#define GPR_GETPID_IN_UNISTD_H 1 #define GPR_GETPID_IN_UNISTD_H 1
#define GPR_HAVE_MSG_NOSIGNAL 1 #define GPR_HAVE_MSG_NOSIGNAL 1
#elif defined(__linux__) #elif defined(__linux__)
#define GPR_PLATFORM_STRING "linux"
#ifndef _BSD_SOURCE #ifndef _BSD_SOURCE
#define _BSD_SOURCE #define _BSD_SOURCE
#endif #endif
@ -173,9 +177,11 @@
#define _BSD_SOURCE #define _BSD_SOURCE
#endif #endif
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
#define GPR_PLATFORM_STRING "ios"
#define GPR_CPU_IPHONE 1 #define GPR_CPU_IPHONE 1
#define GPR_PTHREAD_TLS 1 #define GPR_PTHREAD_TLS 1
#else /* TARGET_OS_IPHONE */ #else /* TARGET_OS_IPHONE */
#define GPR_PLATFORM_STRING "osx"
#define GPR_CPU_POSIX 1 #define GPR_CPU_POSIX 1
#define GPR_GCC_TLS 1 #define GPR_GCC_TLS 1
#endif #endif
@ -201,6 +207,7 @@
#define GPR_ARCH_32 1 #define GPR_ARCH_32 1
#endif /* _LP64 */ #endif /* _LP64 */
#elif defined(__FreeBSD__) #elif defined(__FreeBSD__)
#define GPR_PLATFORM_STRING "freebsd"
#ifndef _BSD_SOURCE #ifndef _BSD_SOURCE
#define _BSD_SOURCE #define _BSD_SOURCE
#endif #endif
@ -232,6 +239,11 @@
#endif #endif
#endif /* GPR_NO_AUTODETECT_PLATFORM */ #endif /* GPR_NO_AUTODETECT_PLATFORM */
#ifndef GPR_PLATFORM_STRING
#warning "GPR_PLATFORM_STRING not auto-detected"
#define GPR_PLATFORM_STRING "unknown"
#endif
/* For a common case, assume that the platform has a C99-like stdint.h */ /* For a common case, assume that the platform has a C99-like stdint.h */
#include <stdint.h> #include <stdint.h>

@ -83,6 +83,9 @@ void gpr_time_init(void);
/* Return the current time measured from the given clocks epoch. */ /* Return the current time measured from the given clocks epoch. */
gpr_timespec gpr_now(gpr_clock_type clock); gpr_timespec gpr_now(gpr_clock_type clock);
/* Convert a timespec from one clock to another */
gpr_timespec gpr_convert_clock_type(gpr_timespec t, gpr_clock_type target_clock);
/* Return -ve, 0, or +ve according to whether a < b, a == b, or a > b /* Return -ve, 0, or +ve according to whether a < b, a == b, or a > b
respectively. */ respectively. */
int gpr_time_cmp(gpr_timespec a, gpr_timespec b); int gpr_time_cmp(gpr_timespec a, gpr_timespec b);

@ -149,7 +149,7 @@ std::string GetMethodRequestParamMaybe(const MethodDescriptor *method) {
std::string GetMethodReturnTypeClient(const MethodDescriptor *method) { std::string GetMethodReturnTypeClient(const MethodDescriptor *method) {
switch (GetMethodType(method)) { switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING: case METHODTYPE_NO_STREAMING:
return "Task<" + GetClassName(method->output_type()) + ">"; return "AsyncUnaryCall<" + GetClassName(method->output_type()) + ">";
case METHODTYPE_CLIENT_STREAMING: case METHODTYPE_CLIENT_STREAMING:
return "AsyncClientStreamingCall<" + GetClassName(method->input_type()) return "AsyncClientStreamingCall<" + GetClassName(method->input_type())
+ ", " + GetClassName(method->output_type()) + ">"; + ", " + GetClassName(method->output_type()) + ">";
@ -269,7 +269,7 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
if (method_type == METHODTYPE_NO_STREAMING) { if (method_type == METHODTYPE_NO_STREAMING) {
// unary calls have an extra synchronous stub method // unary calls have an extra synchronous stub method
out->Print( out->Print(
"$response$ $methodname$($request$ request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));\n", "$response$ $methodname$($request$ request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));\n",
"methodname", method->name(), "request", "methodname", method->name(), "request",
GetClassName(method->input_type()), "response", GetClassName(method->input_type()), "response",
GetClassName(method->output_type())); GetClassName(method->output_type()));
@ -280,7 +280,7 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
method_name += "Async"; // prevent name clash with synchronous method. method_name += "Async"; // prevent name clash with synchronous method.
} }
out->Print( out->Print(
"$returntype$ $methodname$($request_maybe$Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));\n", "$returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));\n",
"methodname", method_name, "request_maybe", "methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype", GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method)); GetMethodReturnTypeClient(method));
@ -298,7 +298,9 @@ void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) {
out->Indent(); out->Indent();
for (int i = 0; i < service->method_count(); i++) { for (int i = 0; i < service->method_count(); i++) {
const MethodDescriptor *method = service->method(i); const MethodDescriptor *method = service->method(i);
out->Print("$returntype$ $methodname$(ServerCallContext context, $request$$response_stream_maybe$);\n", out->Print(
"$returntype$ $methodname$($request$$response_stream_maybe$, "
"ServerCallContext context);\n",
"methodname", method->name(), "returntype", "methodname", method->name(), "returntype",
GetMethodReturnTypeServer(method), "request", GetMethodReturnTypeServer(method), "request",
GetMethodRequestParamServer(method), "response_stream_maybe", GetMethodRequestParamServer(method), "response_stream_maybe",
@ -332,13 +334,13 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
if (method_type == METHODTYPE_NO_STREAMING) { if (method_type == METHODTYPE_NO_STREAMING) {
// unary calls have an extra synchronous stub method // unary calls have an extra synchronous stub method
out->Print( out->Print(
"public $response$ $methodname$($request$ request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))\n", "public $response$ $methodname$($request$ request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
"methodname", method->name(), "request", "methodname", method->name(), "request",
GetClassName(method->input_type()), "response", GetClassName(method->input_type()), "response",
GetClassName(method->output_type())); GetClassName(method->output_type()));
out->Print("{\n"); out->Print("{\n");
out->Indent(); out->Indent();
out->Print("var call = CreateCall($servicenamefield$, $methodfield$, headers);\n", out->Print("var call = CreateCall($servicenamefield$, $methodfield$, headers, deadline);\n",
"servicenamefield", GetServiceNameFieldName(), "methodfield", "servicenamefield", GetServiceNameFieldName(), "methodfield",
GetMethodFieldName(method)); GetMethodFieldName(method));
out->Print("return Calls.BlockingUnaryCall(call, request, cancellationToken);\n"); out->Print("return Calls.BlockingUnaryCall(call, request, cancellationToken);\n");
@ -351,13 +353,13 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
method_name += "Async"; // prevent name clash with synchronous method. method_name += "Async"; // prevent name clash with synchronous method.
} }
out->Print( out->Print(
"public $returntype$ $methodname$($request_maybe$Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))\n", "public $returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
"methodname", method_name, "request_maybe", "methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype", GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method)); GetMethodReturnTypeClient(method));
out->Print("{\n"); out->Print("{\n");
out->Indent(); out->Indent();
out->Print("var call = CreateCall($servicenamefield$, $methodfield$, headers);\n", out->Print("var call = CreateCall($servicenamefield$, $methodfield$, headers, deadline);\n",
"servicenamefield", GetServiceNameFieldName(), "methodfield", "servicenamefield", GetServiceNameFieldName(), "methodfield",
GetMethodFieldName(method)); GetMethodFieldName(method));
switch (GetMethodType(method)) { switch (GetMethodType(method)) {

@ -249,7 +249,7 @@ bool GetModuleAndMessagePath(const Descriptor* type,
do { do {
message_path.push_back(path_elem_type); message_path.push_back(path_elem_type);
path_elem_type = path_elem_type->containing_type(); path_elem_type = path_elem_type->containing_type();
} while (path_elem_type != nullptr); } while (path_elem_type); // implicit nullptr comparison; don't be explicit
grpc::string file_name = type->file()->name(); grpc::string file_name = type->file()->name();
static const int proto_suffix_length = strlen(".proto"); static const int proto_suffix_length = strlen(".proto");
if (!(file_name.size() > static_cast<size_t>(proto_suffix_length) && if (!(file_name.size() > static_cast<size_t>(proto_suffix_length) &&

@ -39,7 +39,7 @@ static void grpc_census_context_destroy(void *context) {
} }
void grpc_census_call_set_context(grpc_call *call, census_context *context) { void grpc_census_call_set_context(grpc_call *call, census_context *context) {
if (!census_available()) { if (census_enabled() == CENSUS_FEATURE_NONE) {
return; return;
} }
if (context == NULL) { if (context == NULL) {

@ -33,20 +33,25 @@
#include <grpc/census.h> #include <grpc/census.h>
static int census_fns_enabled = CENSUS_NONE; static int features_enabled = CENSUS_FEATURE_NONE;
int census_initialize(int functions) { int census_initialize(int features) {
if (census_fns_enabled != CENSUS_NONE) { if (features_enabled != CENSUS_FEATURE_NONE) {
return 1; return 1;
} }
if (functions != CENSUS_NONE) { if (features != CENSUS_FEATURE_NONE) {
return 1; return 1;
} else { } else {
census_fns_enabled = functions; features_enabled = features;
return 0; return 0;
} }
} }
void census_shutdown() { census_fns_enabled = CENSUS_NONE; } void census_shutdown(void) { features_enabled = CENSUS_FEATURE_NONE; }
int census_available() { return (census_fns_enabled != CENSUS_NONE); } int census_supported(void) {
/* TODO(aveitch): improve this as we implement features... */
return CENSUS_FEATURE_NONE;
}
int census_enabled(void) { return features_enabled; }

@ -31,21 +31,8 @@
* *
*/ */
#ifndef GRPC_TEST_CPP_UTIL_FAKE_CREDENTIALS_H #include <grpc/census.h>
#define GRPC_TEST_CPP_UTIL_FAKE_CREDENTIALS_H #include "src/core/census/rpc_stat_id.h"
#include <memory> void census_record_stat(census_context *context, census_stat *stats,
size_t nstats) {}
namespace grpc {
class Credentials;
class ServerCredentials;
namespace testing {
std::shared_ptr<Credentials> FakeTransportSecurityCredentials();
std::shared_ptr<ServerCredentials> FakeTransportSecurityServerCredentials();
} // namespace testing
} // namespace grpc
#endif // GRPC_TEST_CPP_UTIL_FAKE_CREDENTIALS_H

@ -31,28 +31,16 @@
* *
*/ */
#include <grpc/grpc_security.h> #ifndef CENSUS_RPC_STAT_ID_H
#include <grpc++/channel_arguments.h> #define CENSUS_RPC_STAT_ID_H
#include <grpc++/credentials.h>
#include <grpc++/server_credentials.h>
#include "src/cpp/client/channel.h"
#include "src/cpp/client/secure_credentials.h"
#include "src/cpp/server/secure_server_credentials.h"
namespace grpc { /* Stats ID's used for RPC measurements. */
namespace testing { #define CENSUS_INVALID_STAT_ID 0 /* ID 0 is always invalid */
#define CENSUS_RPC_CLIENT_REQUESTS 1 /* Count of client requests sent. */
#define CENSUS_RPC_SERVER_REQUESTS 2 /* Count of server requests sent. */
#define CENSUS_RPC_CLIENT_ERRORS 3 /* Client error counts. */
#define CENSUS_RPC_SERVER_ERRORS 4 /* Server error counts. */
#define CENSUS_RPC_CLIENT_LATENCY 5 /* Client side request latency. */
#define CENSUS_RPC_SERVER_LATENCY 6 /* Server side request latency. */
std::shared_ptr<Credentials> FakeTransportSecurityCredentials() { #endif /* CENSUS_RPC_STAT_ID_H */
grpc_credentials* c_creds = grpc_fake_transport_security_credentials_create();
return std::shared_ptr<Credentials>(new SecureCredentials(c_creds));
}
std::shared_ptr<ServerCredentials> FakeTransportSecurityServerCredentials() {
grpc_server_credentials* c_creds =
grpc_fake_transport_security_server_credentials_create();
return std::shared_ptr<ServerCredentials>(
new SecureServerCredentials(c_creds));
}
} // namespace testing
} // namespace grpc

@ -191,6 +191,11 @@ void grpc_call_next_op(grpc_call_element *elem, grpc_transport_stream_op *op) {
next_elem->filter->start_transport_stream_op(next_elem, op); next_elem->filter->start_transport_stream_op(next_elem, op);
} }
char *grpc_call_next_get_peer(grpc_call_element *elem) {
grpc_call_element *next_elem = elem + 1;
return next_elem->filter->get_peer(next_elem);
}
void grpc_channel_next_op(grpc_channel_element *elem, grpc_transport_op *op) { void grpc_channel_next_op(grpc_channel_element *elem, grpc_transport_op *op) {
grpc_channel_element *next_elem = elem + 1; grpc_channel_element *next_elem = elem + 1;
next_elem->filter->start_transport_op(next_elem, op); next_elem->filter->start_transport_op(next_elem, op);

@ -104,6 +104,9 @@ typedef struct {
The filter does not need to do any chaining */ The filter does not need to do any chaining */
void (*destroy_channel_elem)(grpc_channel_element *elem); void (*destroy_channel_elem)(grpc_channel_element *elem);
/* Implement grpc_call_get_peer() */
char *(*get_peer)(grpc_call_element *elem);
/* The name of this filter */ /* The name of this filter */
const char *name; const char *name;
} grpc_channel_filter; } grpc_channel_filter;
@ -173,6 +176,8 @@ void grpc_call_next_op(grpc_call_element *elem, grpc_transport_stream_op *op);
/* Call the next operation (depending on call directionality) in a channel /* Call the next operation (depending on call directionality) in a channel
stack */ stack */
void grpc_channel_next_op(grpc_channel_element *elem, grpc_transport_op *op); void grpc_channel_next_op(grpc_channel_element *elem, grpc_transport_op *op);
/* Pass through a request to get_peer to the next child element */
char *grpc_call_next_get_peer(grpc_call_element *elem);
/* Given the top element of a channel stack, get the channel stack itself */ /* Given the top element of a channel stack, get the channel stack itself */
grpc_channel_stack *grpc_channel_stack_from_top_element( grpc_channel_stack *grpc_channel_stack_from_top_element(

@ -40,7 +40,6 @@
#include "src/core/channel/connected_channel.h" #include "src/core/channel/connected_channel.h"
#include "src/core/surface/channel.h" #include "src/core/surface/channel.h"
#include "src/core/iomgr/iomgr.h" #include "src/core/iomgr/iomgr.h"
#include "src/core/iomgr/pollset_set.h"
#include "src/core/support/string.h" #include "src/core/support/string.h"
#include "src/core/transport/connectivity_state.h" #include "src/core/transport/connectivity_state.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
@ -77,8 +76,22 @@ typedef struct {
grpc_iomgr_closure on_config_changed; grpc_iomgr_closure on_config_changed;
/** connectivity state being tracked */ /** connectivity state being tracked */
grpc_connectivity_state_tracker state_tracker; grpc_connectivity_state_tracker state_tracker;
/** when an lb_policy arrives, should we try to exit idle */
int exit_idle_when_lb_policy_arrives;
/** pollset_set of interested parties in a new connection */
grpc_pollset_set pollset_set;
} channel_data; } channel_data;
/** We create one watcher for each new lb_policy that is returned from a resolver,
to watch for state changes from the lb_policy. When a state change is seen, we
update the channel, and create a new watcher */
typedef struct {
channel_data *chand;
grpc_iomgr_closure on_changed;
grpc_connectivity_state state;
grpc_lb_policy *lb_policy;
} lb_policy_connectivity_watcher;
typedef enum { typedef enum {
CALL_CREATED, CALL_CREATED,
CALL_WAITING_FOR_SEND, CALL_WAITING_FOR_SEND,
@ -236,21 +249,6 @@ static void picked_target(void *arg, int iomgr_success) {
} }
} }
static void pick_target(grpc_lb_policy *lb_policy, call_data *calld) {
grpc_metadata_batch *initial_metadata;
grpc_transport_stream_op *op = &calld->waiting_op;
GPR_ASSERT(op->bind_pollset);
GPR_ASSERT(op->send_ops);
GPR_ASSERT(op->send_ops->nops >= 1);
GPR_ASSERT(op->send_ops->ops[0].type == GRPC_OP_METADATA);
initial_metadata = &op->send_ops->ops[0].data.metadata;
grpc_iomgr_closure_init(&calld->async_setup_task, picked_target, calld);
grpc_lb_policy_pick(lb_policy, op->bind_pollset, initial_metadata,
&calld->picked_channel, &calld->async_setup_task);
}
static grpc_iomgr_closure *merge_into_waiting_op( static grpc_iomgr_closure *merge_into_waiting_op(
grpc_call_element *elem, grpc_transport_stream_op *new_op) { grpc_call_element *elem, grpc_transport_stream_op *new_op) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
@ -280,6 +278,26 @@ static grpc_iomgr_closure *merge_into_waiting_op(
return consumed_op; return consumed_op;
} }
static char *cc_get_peer(grpc_call_element *elem) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
grpc_subchannel_call *subchannel_call;
char *result;
gpr_mu_lock(&calld->mu_state);
if (calld->state == CALL_ACTIVE) {
subchannel_call = calld->subchannel_call;
GRPC_SUBCHANNEL_CALL_REF(subchannel_call, "get_peer");
gpr_mu_unlock(&calld->mu_state);
result = grpc_subchannel_call_get_peer(subchannel_call);
GRPC_SUBCHANNEL_CALL_UNREF(subchannel_call, "get_peer");
return result;
} else {
gpr_mu_unlock(&calld->mu_state);
return grpc_channel_get_target(chand->master);
}
}
static void perform_transport_stream_op(grpc_call_element *elem, static void perform_transport_stream_op(grpc_call_element *elem,
grpc_transport_stream_op *op, grpc_transport_stream_op *op,
int continuation) { int continuation) {
@ -358,12 +376,23 @@ static void perform_transport_stream_op(grpc_call_element *elem,
gpr_mu_lock(&chand->mu_config); gpr_mu_lock(&chand->mu_config);
lb_policy = chand->lb_policy; lb_policy = chand->lb_policy;
if (lb_policy) { if (lb_policy) {
grpc_transport_stream_op *op = &calld->waiting_op;
grpc_pollset *bind_pollset = op->bind_pollset;
grpc_metadata_batch *initial_metadata = &op->send_ops->ops[0].data.metadata;
GRPC_LB_POLICY_REF(lb_policy, "pick"); GRPC_LB_POLICY_REF(lb_policy, "pick");
gpr_mu_unlock(&chand->mu_config); gpr_mu_unlock(&chand->mu_config);
calld->state = CALL_WAITING_FOR_PICK; calld->state = CALL_WAITING_FOR_PICK;
GPR_ASSERT(op->bind_pollset);
GPR_ASSERT(op->send_ops);
GPR_ASSERT(op->send_ops->nops >= 1);
GPR_ASSERT(
op->send_ops->ops[0].type == GRPC_OP_METADATA);
gpr_mu_unlock(&calld->mu_state); gpr_mu_unlock(&calld->mu_state);
pick_target(lb_policy, calld); grpc_iomgr_closure_init(&calld->async_setup_task, picked_target, calld);
grpc_lb_policy_pick(lb_policy, bind_pollset, initial_metadata,
&calld->picked_channel, &calld->async_setup_task);
GRPC_LB_POLICY_UNREF(lb_policy, "pick"); GRPC_LB_POLICY_UNREF(lb_policy, "pick");
} else if (chand->resolver != NULL) { } else if (chand->resolver != NULL) {
@ -392,16 +421,53 @@ static void cc_start_transport_stream_op(grpc_call_element *elem,
perform_transport_stream_op(elem, op, 0); perform_transport_stream_op(elem, op, 0);
} }
static void watch_lb_policy(channel_data *chand, grpc_lb_policy *lb_policy, grpc_connectivity_state current_state);
static void on_lb_policy_state_changed(void *arg, int iomgr_success) {
lb_policy_connectivity_watcher *w = arg;
gpr_mu_lock(&w->chand->mu_config);
/* check if the notification is for a stale policy */
if (w->lb_policy == w->chand->lb_policy) {
grpc_connectivity_state_set(&w->chand->state_tracker, w->state,
"lb_changed");
if (w->state != GRPC_CHANNEL_FATAL_FAILURE) {
watch_lb_policy(w->chand, w->lb_policy, w->state);
}
}
gpr_mu_unlock(&w->chand->mu_config);
GRPC_CHANNEL_INTERNAL_UNREF(w->chand->master, "watch_lb_policy");
gpr_free(w);
}
static void watch_lb_policy(channel_data *chand, grpc_lb_policy *lb_policy, grpc_connectivity_state current_state) {
lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
GRPC_CHANNEL_INTERNAL_REF(chand->master, "watch_lb_policy");
w->chand = chand;
grpc_iomgr_closure_init(&w->on_changed, on_lb_policy_state_changed, w);
w->state = current_state;
w->lb_policy = lb_policy;
grpc_lb_policy_notify_on_state_change(lb_policy, &w->state, &w->on_changed);
}
static void cc_on_config_changed(void *arg, int iomgr_success) { static void cc_on_config_changed(void *arg, int iomgr_success) {
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_resolver *old_resolver;
grpc_iomgr_closure *wakeup_closures = NULL; grpc_iomgr_closure *wakeup_closures = NULL;
grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
int exit_idle = 0;
if (chand->incoming_configuration != NULL) { if (chand->incoming_configuration != NULL) {
lb_policy = grpc_client_config_get_lb_policy(chand->incoming_configuration); lb_policy = grpc_client_config_get_lb_policy(chand->incoming_configuration);
if (lb_policy != NULL) {
GRPC_LB_POLICY_REF(lb_policy, "channel"); GRPC_LB_POLICY_REF(lb_policy, "channel");
GRPC_LB_POLICY_REF(lb_policy, "config_change");
state = grpc_lb_policy_check_connectivity(lb_policy);
}
grpc_client_config_unref(chand->incoming_configuration); grpc_client_config_unref(chand->incoming_configuration);
} }
@ -415,13 +481,12 @@ static void cc_on_config_changed(void *arg, int iomgr_success) {
wakeup_closures = chand->waiting_for_config_closures; wakeup_closures = chand->waiting_for_config_closures;
chand->waiting_for_config_closures = NULL; chand->waiting_for_config_closures = NULL;
} }
gpr_mu_unlock(&chand->mu_config); if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
if (old_lb_policy) { exit_idle = 1;
GRPC_LB_POLICY_UNREF(old_lb_policy, "channel"); chand->exit_idle_when_lb_policy_arrives = 0;
} }
gpr_mu_lock(&chand->mu_config);
if (iomgr_success && chand->resolver) { if (iomgr_success && chand->resolver) {
grpc_resolver *resolver = chand->resolver; grpc_resolver *resolver = chand->resolver;
GRPC_RESOLVER_REF(resolver, "channel-next"); GRPC_RESOLVER_REF(resolver, "channel-next");
@ -430,11 +495,16 @@ static void cc_on_config_changed(void *arg, int iomgr_success) {
grpc_resolver_next(resolver, &chand->incoming_configuration, grpc_resolver_next(resolver, &chand->incoming_configuration,
&chand->on_config_changed); &chand->on_config_changed);
GRPC_RESOLVER_UNREF(resolver, "channel-next"); GRPC_RESOLVER_UNREF(resolver, "channel-next");
grpc_connectivity_state_set(&chand->state_tracker, state,
"new_lb+resolver");
if (lb_policy != NULL) {
watch_lb_policy(chand, lb_policy, state);
}
} else { } else {
old_resolver = chand->resolver; old_resolver = chand->resolver;
chand->resolver = NULL; chand->resolver = NULL;
grpc_connectivity_state_set(&chand->state_tracker, grpc_connectivity_state_set(&chand->state_tracker,
GRPC_CHANNEL_FATAL_FAILURE); GRPC_CHANNEL_FATAL_FAILURE, "resolver_gone");
gpr_mu_unlock(&chand->mu_config); gpr_mu_unlock(&chand->mu_config);
if (old_resolver != NULL) { if (old_resolver != NULL) {
grpc_resolver_shutdown(old_resolver); grpc_resolver_shutdown(old_resolver);
@ -442,12 +512,24 @@ static void cc_on_config_changed(void *arg, int iomgr_success) {
} }
} }
if (exit_idle) {
grpc_lb_policy_exit_idle(lb_policy);
GRPC_LB_POLICY_UNREF(lb_policy, "exit_idle");
}
if (old_lb_policy != NULL) {
GRPC_LB_POLICY_UNREF(old_lb_policy, "channel");
}
while (wakeup_closures) { while (wakeup_closures) {
grpc_iomgr_closure *next = wakeup_closures->next; grpc_iomgr_closure *next = wakeup_closures->next;
grpc_iomgr_add_callback(wakeup_closures); wakeup_closures->cb(wakeup_closures->cb_arg, 1);
wakeup_closures = next; wakeup_closures = next;
} }
if (lb_policy != NULL) {
GRPC_LB_POLICY_UNREF(lb_policy, "config_change");
}
GRPC_CHANNEL_INTERNAL_UNREF(chand->master, "resolver"); GRPC_CHANNEL_INTERNAL_UNREF(chand->master, "resolver");
} }
@ -471,20 +553,22 @@ static void cc_start_transport_op(grpc_channel_element *elem,
op->connectivity_state = NULL; op->connectivity_state = NULL;
} }
if (!is_empty(op, sizeof(*op))) {
lb_policy = chand->lb_policy;
if (lb_policy) {
GRPC_LB_POLICY_REF(lb_policy, "broadcast");
}
}
if (op->disconnect && chand->resolver != NULL) { if (op->disconnect && chand->resolver != NULL) {
grpc_connectivity_state_set(&chand->state_tracker, grpc_connectivity_state_set(&chand->state_tracker,
GRPC_CHANNEL_FATAL_FAILURE); GRPC_CHANNEL_FATAL_FAILURE, "disconnect");
destroy_resolver = chand->resolver; destroy_resolver = chand->resolver;
chand->resolver = NULL; chand->resolver = NULL;
if (chand->lb_policy != NULL) { if (chand->lb_policy != NULL) {
grpc_lb_policy_shutdown(chand->lb_policy); grpc_lb_policy_shutdown(chand->lb_policy);
} GRPC_LB_POLICY_UNREF(chand->lb_policy, "channel");
} chand->lb_policy = NULL;
if (!is_empty(op, sizeof(*op))) {
lb_policy = chand->lb_policy;
if (lb_policy) {
GRPC_LB_POLICY_REF(lb_policy, "broadcast");
} }
} }
gpr_mu_unlock(&chand->mu_config); gpr_mu_unlock(&chand->mu_config);
@ -565,10 +649,11 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
gpr_mu_init(&chand->mu_config); gpr_mu_init(&chand->mu_config);
chand->mdctx = metadata_context; chand->mdctx = metadata_context;
chand->master = master; chand->master = master;
grpc_pollset_set_init(&chand->pollset_set);
grpc_iomgr_closure_init(&chand->on_config_changed, cc_on_config_changed, grpc_iomgr_closure_init(&chand->on_config_changed, cc_on_config_changed,
chand); chand);
grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE); grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE, "client_channel");
} }
/* Destructor for channel_data */ /* Destructor for channel_data */
@ -582,6 +667,8 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
if (chand->lb_policy != NULL) { if (chand->lb_policy != NULL) {
GRPC_LB_POLICY_UNREF(chand->lb_policy, "channel"); GRPC_LB_POLICY_UNREF(chand->lb_policy, "channel");
} }
grpc_connectivity_state_destroy(&chand->state_tracker);
grpc_pollset_set_destroy(&chand->pollset_set);
gpr_mu_destroy(&chand->mu_config); gpr_mu_destroy(&chand->mu_config);
} }
@ -594,6 +681,7 @@ const grpc_channel_filter grpc_client_channel_filter = {
sizeof(channel_data), sizeof(channel_data),
init_channel_elem, init_channel_elem,
destroy_channel_elem, destroy_channel_elem,
cc_get_peer,
"client-channel", "client-channel",
}; };
@ -609,3 +697,47 @@ void grpc_client_channel_set_resolver(grpc_channel_stack *channel_stack,
grpc_resolver_next(resolver, &chand->incoming_configuration, grpc_resolver_next(resolver, &chand->incoming_configuration,
&chand->on_config_changed); &chand->on_config_changed);
} }
grpc_connectivity_state grpc_client_channel_check_connectivity_state(
grpc_channel_element *elem, int try_to_connect) {
channel_data *chand = elem->channel_data;
grpc_connectivity_state out;
gpr_mu_lock(&chand->mu_config);
out = grpc_connectivity_state_check(&chand->state_tracker);
if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
if (chand->lb_policy != NULL) {
grpc_lb_policy_exit_idle(chand->lb_policy);
} else {
chand->exit_idle_when_lb_policy_arrives = 1;
}
}
gpr_mu_unlock(&chand->mu_config);
return out;
}
void grpc_client_channel_watch_connectivity_state(
grpc_channel_element *elem, grpc_connectivity_state *state,
grpc_iomgr_closure *on_complete) {
channel_data *chand = elem->channel_data;
gpr_mu_lock(&chand->mu_config);
grpc_connectivity_state_notify_on_state_change(&chand->state_tracker, state,
on_complete);
gpr_mu_unlock(&chand->mu_config);
}
grpc_pollset_set *grpc_client_channel_get_connecting_pollset_set(grpc_channel_element *elem) {
channel_data *chand = elem->channel_data;
return &chand->pollset_set;
}
void grpc_client_channel_add_interested_party(grpc_channel_element *elem,
grpc_pollset *pollset) {
channel_data *chand = elem->channel_data;
grpc_pollset_set_add_pollset(&chand->pollset_set, pollset);
}
void grpc_client_channel_del_interested_party(grpc_channel_element *elem,
grpc_pollset *pollset) {
channel_data *chand = elem->channel_data;
grpc_pollset_set_del_pollset(&chand->pollset_set, pollset);
}

@ -52,4 +52,18 @@ extern const grpc_channel_filter grpc_client_channel_filter;
void grpc_client_channel_set_resolver(grpc_channel_stack *channel_stack, void grpc_client_channel_set_resolver(grpc_channel_stack *channel_stack,
grpc_resolver *resolver); grpc_resolver *resolver);
grpc_connectivity_state grpc_client_channel_check_connectivity_state(
grpc_channel_element *elem, int try_to_connect);
void grpc_client_channel_watch_connectivity_state(
grpc_channel_element *elem, grpc_connectivity_state *state,
grpc_iomgr_closure *on_complete);
grpc_pollset_set *grpc_client_channel_get_connecting_pollset_set(grpc_channel_element *elem);
void grpc_client_channel_add_interested_party(grpc_channel_element *channel,
grpc_pollset *pollset);
void grpc_client_channel_del_interested_party(grpc_channel_element *channel,
grpc_pollset *pollset);
#endif /* GRPC_INTERNAL_CORE_CHANNEL_CLIENT_CHANNEL_H */ #endif /* GRPC_INTERNAL_CORE_CHANNEL_CLIENT_CHANNEL_H */

@ -174,6 +174,8 @@ static void process_send_ops(grpc_call_element *elem,
size_t i; size_t i;
int did_compress = 0; int did_compress = 0;
/* In streaming calls, we need to reset the previously accumulated slices */
gpr_slice_buffer_reset_and_unref(&calld->slices);
for (i = 0; i < send_ops->nops; ++i) { for (i = 0; i < send_ops->nops; ++i) {
grpc_stream_op *sop = &send_ops->ops[i]; grpc_stream_op *sop = &send_ops->ops[i];
switch (sop->type) { switch (sop->type) {
@ -200,7 +202,7 @@ static void process_send_ops(grpc_call_element *elem,
channeld->default_compression_algorithm; channeld->default_compression_algorithm;
calld->has_compression_algorithm = 1; /* GPR_TRUE */ calld->has_compression_algorithm = 1; /* GPR_TRUE */
} }
grpc_metadata_batch_add_head( grpc_metadata_batch_add_tail(
&(sop->data.metadata), &calld->compression_algorithm_storage, &(sop->data.metadata), &calld->compression_algorithm_storage,
grpc_mdelem_ref(channeld->mdelem_compression_algorithms grpc_mdelem_ref(channeld->mdelem_compression_algorithms
[calld->compression_algorithm])); [calld->compression_algorithm]));
@ -282,19 +284,19 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
grpc_channel_args_get_compression_algorithm(args); grpc_channel_args_get_compression_algorithm(args);
channeld->mdstr_request_compression_algorithm_key = channeld->mdstr_request_compression_algorithm_key =
grpc_mdstr_from_string(mdctx, GRPC_COMPRESS_REQUEST_ALGORITHM_KEY); grpc_mdstr_from_string(mdctx, GRPC_COMPRESS_REQUEST_ALGORITHM_KEY, 0);
channeld->mdstr_outgoing_compression_algorithm_key = channeld->mdstr_outgoing_compression_algorithm_key =
grpc_mdstr_from_string(mdctx, "grpc-encoding"); grpc_mdstr_from_string(mdctx, "grpc-encoding", 0);
for (algo_idx = 0; algo_idx < GRPC_COMPRESS_ALGORITHMS_COUNT; ++algo_idx) { for (algo_idx = 0; algo_idx < GRPC_COMPRESS_ALGORITHMS_COUNT; ++algo_idx) {
char *algorith_name; char *algorithm_name;
GPR_ASSERT(grpc_compression_algorithm_name(algo_idx, &algorith_name) != 0); GPR_ASSERT(grpc_compression_algorithm_name(algo_idx, &algorithm_name) != 0);
channeld->mdelem_compression_algorithms[algo_idx] = channeld->mdelem_compression_algorithms[algo_idx] =
grpc_mdelem_from_metadata_strings( grpc_mdelem_from_metadata_strings(
mdctx, mdctx,
grpc_mdstr_ref(channeld->mdstr_outgoing_compression_algorithm_key), grpc_mdstr_ref(channeld->mdstr_outgoing_compression_algorithm_key),
grpc_mdstr_from_string(mdctx, algorith_name)); grpc_mdstr_from_string(mdctx, algorithm_name, 0));
} }
GPR_ASSERT(!is_last); GPR_ASSERT(!is_last);
@ -322,4 +324,5 @@ const grpc_channel_filter grpc_compress_filter = {
sizeof(channel_data), sizeof(channel_data),
init_channel_elem, init_channel_elem,
destroy_channel_elem, destroy_channel_elem,
grpc_call_next_get_peer,
"compress"}; "compress"};

@ -119,6 +119,11 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
grpc_transport_destroy(cd->transport); grpc_transport_destroy(cd->transport);
} }
static char *con_get_peer(grpc_call_element *elem) {
channel_data *chand = elem->channel_data;
return grpc_transport_get_peer(chand->transport);
}
const grpc_channel_filter grpc_connected_channel_filter = { const grpc_channel_filter grpc_connected_channel_filter = {
con_start_transport_stream_op, con_start_transport_stream_op,
con_start_transport_op, con_start_transport_op,
@ -128,6 +133,7 @@ const grpc_channel_filter grpc_connected_channel_filter = {
sizeof(channel_data), sizeof(channel_data),
init_channel_elem, init_channel_elem,
destroy_channel_elem, destroy_channel_elem,
con_get_peer,
"connected", "connected",
}; };

@ -32,13 +32,17 @@
#include "src/core/channel/http_client_filter.h" #include "src/core/channel/http_client_filter.h"
#include <string.h> #include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/support/string.h"
typedef struct call_data { typedef struct call_data {
grpc_linked_mdelem method; grpc_linked_mdelem method;
grpc_linked_mdelem scheme; grpc_linked_mdelem scheme;
grpc_linked_mdelem te_trailers; grpc_linked_mdelem te_trailers;
grpc_linked_mdelem content_type; grpc_linked_mdelem content_type;
grpc_linked_mdelem user_agent;
int sent_initial_metadata; int sent_initial_metadata;
int got_initial_metadata; int got_initial_metadata;
@ -58,6 +62,8 @@ typedef struct channel_data {
grpc_mdelem *scheme; grpc_mdelem *scheme;
grpc_mdelem *content_type; grpc_mdelem *content_type;
grpc_mdelem *status; grpc_mdelem *status;
/** complete user agent mdelem */
grpc_mdelem *user_agent;
} channel_data; } channel_data;
/* used to silence 'variable not used' warnings */ /* used to silence 'variable not used' warnings */
@ -92,6 +98,18 @@ static void hc_on_recv(void *user_data, int success) {
calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success); calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
} }
static grpc_mdelem *client_strip_filter(void *user_data, grpc_mdelem *md) {
grpc_call_element *elem = user_data;
channel_data *channeld = elem->channel_data;
/* eat the things we'd like to set ourselves */
if (md->key == channeld->method->key) return NULL;
if (md->key == channeld->scheme->key) return NULL;
if (md->key == channeld->te_trailers->key) return NULL;
if (md->key == channeld->content_type->key) return NULL;
if (md->key == channeld->user_agent->key) return NULL;
return md;
}
static void hc_mutate_op(grpc_call_element *elem, static void hc_mutate_op(grpc_call_element *elem,
grpc_transport_stream_op *op) { grpc_transport_stream_op *op) {
/* grab pointers to our data from the call element */ /* grab pointers to our data from the call element */
@ -105,6 +123,7 @@ static void hc_mutate_op(grpc_call_element *elem,
grpc_stream_op *op = &ops[i]; grpc_stream_op *op = &ops[i];
if (op->type != GRPC_OP_METADATA) continue; if (op->type != GRPC_OP_METADATA) continue;
calld->sent_initial_metadata = 1; calld->sent_initial_metadata = 1;
grpc_metadata_batch_filter(&op->data.metadata, client_strip_filter, elem);
/* Send : prefixed headers, which have to be before any application /* Send : prefixed headers, which have to be before any application
layer headers. */ layer headers. */
grpc_metadata_batch_add_head(&op->data.metadata, &calld->method, grpc_metadata_batch_add_head(&op->data.metadata, &calld->method,
@ -115,6 +134,8 @@ static void hc_mutate_op(grpc_call_element *elem,
GRPC_MDELEM_REF(channeld->te_trailers)); GRPC_MDELEM_REF(channeld->te_trailers));
grpc_metadata_batch_add_tail(&op->data.metadata, &calld->content_type, grpc_metadata_batch_add_tail(&op->data.metadata, &calld->content_type,
GRPC_MDELEM_REF(channeld->content_type)); GRPC_MDELEM_REF(channeld->content_type));
grpc_metadata_batch_add_tail(&op->data.metadata, &calld->user_agent,
GRPC_MDELEM_REF(channeld->user_agent));
break; break;
} }
} }
@ -169,6 +190,55 @@ static const char *scheme_from_args(const grpc_channel_args *args) {
return "http"; return "http";
} }
static grpc_mdstr *user_agent_from_args(grpc_mdctx *mdctx,
const grpc_channel_args *args) {
gpr_strvec v;
size_t i;
int is_first = 1;
char *tmp;
grpc_mdstr *result;
gpr_strvec_init(&v);
for (i = 0; args && i < args->num_args; i++) {
if (0 == strcmp(args->args[i].key, GRPC_ARG_PRIMARY_USER_AGENT_STRING)) {
if (args->args[i].type != GRPC_ARG_STRING) {
gpr_log(GPR_ERROR, "Channel argument '%s' should be a string",
GRPC_ARG_PRIMARY_USER_AGENT_STRING);
} else {
if (!is_first) gpr_strvec_add(&v, gpr_strdup(" "));
is_first = 0;
gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string));
}
}
}
gpr_asprintf(&tmp, "%sgrpc-c/%s (%s)", is_first ? "" : " ",
grpc_version_string(), GPR_PLATFORM_STRING);
is_first = 0;
gpr_strvec_add(&v, tmp);
for (i = 0; args && i < args->num_args; i++) {
if (0 == strcmp(args->args[i].key, GRPC_ARG_SECONDARY_USER_AGENT_STRING)) {
if (args->args[i].type != GRPC_ARG_STRING) {
gpr_log(GPR_ERROR, "Channel argument '%s' should be a string",
GRPC_ARG_SECONDARY_USER_AGENT_STRING);
} else {
if (!is_first) gpr_strvec_add(&v, gpr_strdup(" "));
is_first = 0;
gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string));
}
}
}
tmp = gpr_strvec_flatten(&v, NULL);
gpr_strvec_destroy(&v);
result = grpc_mdstr_from_string(mdctx, tmp, 0);
gpr_free(tmp);
return result;
}
/* Constructor for channel_data */ /* Constructor for channel_data */
static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master, static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args, grpc_mdctx *mdctx, const grpc_channel_args *args, grpc_mdctx *mdctx,
@ -189,6 +259,9 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
channeld->content_type = channeld->content_type =
grpc_mdelem_from_strings(mdctx, "content-type", "application/grpc"); grpc_mdelem_from_strings(mdctx, "content-type", "application/grpc");
channeld->status = grpc_mdelem_from_strings(mdctx, ":status", "200"); channeld->status = grpc_mdelem_from_strings(mdctx, ":status", "200");
channeld->user_agent = grpc_mdelem_from_metadata_strings(
mdctx, grpc_mdstr_from_string(mdctx, "user-agent", 0),
user_agent_from_args(mdctx, args));
} }
/* Destructor for channel data */ /* Destructor for channel data */
@ -201,9 +274,11 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
GRPC_MDELEM_UNREF(channeld->scheme); GRPC_MDELEM_UNREF(channeld->scheme);
GRPC_MDELEM_UNREF(channeld->content_type); GRPC_MDELEM_UNREF(channeld->content_type);
GRPC_MDELEM_UNREF(channeld->status); GRPC_MDELEM_UNREF(channeld->status);
GRPC_MDELEM_UNREF(channeld->user_agent);
} }
const grpc_channel_filter grpc_http_client_filter = { const grpc_channel_filter grpc_http_client_filter = {
hc_start_transport_op, grpc_channel_next_op, sizeof(call_data), hc_start_transport_op, grpc_channel_next_op, sizeof(call_data),
init_call_elem, destroy_call_elem, sizeof(channel_data), init_call_elem, destroy_call_elem, sizeof(channel_data),
init_channel_elem, destroy_channel_elem, "http-client"}; init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer,
"http-client"};

@ -250,9 +250,9 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
channeld->http_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "http"); channeld->http_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "http");
channeld->https_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "https"); channeld->https_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "https");
channeld->grpc_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "grpc"); channeld->grpc_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "grpc");
channeld->path_key = grpc_mdstr_from_string(mdctx, ":path"); channeld->path_key = grpc_mdstr_from_string(mdctx, ":path", 0);
channeld->authority_key = grpc_mdstr_from_string(mdctx, ":authority"); channeld->authority_key = grpc_mdstr_from_string(mdctx, ":authority", 0);
channeld->host_key = grpc_mdstr_from_string(mdctx, "host"); channeld->host_key = grpc_mdstr_from_string(mdctx, "host", 0);
channeld->content_type = channeld->content_type =
grpc_mdelem_from_strings(mdctx, "content-type", "application/grpc"); grpc_mdelem_from_strings(mdctx, "content-type", "application/grpc");
@ -280,4 +280,5 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
const grpc_channel_filter grpc_http_server_filter = { const grpc_channel_filter grpc_http_server_filter = {
hs_start_transport_op, grpc_channel_next_op, sizeof(call_data), hs_start_transport_op, grpc_channel_next_op, sizeof(call_data),
init_call_elem, destroy_call_elem, sizeof(channel_data), init_call_elem, destroy_call_elem, sizeof(channel_data),
init_channel_elem, destroy_channel_elem, "http-server"}; init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer,
"http-server"};

@ -127,4 +127,5 @@ const grpc_channel_filter grpc_no_op_filter = {noop_start_transport_stream_op,
sizeof(channel_data), sizeof(channel_data),
init_channel_elem, init_channel_elem,
destroy_channel_elem, destroy_channel_elem,
grpc_call_next_get_peer,
"no-op"}; "no-op"};

@ -60,3 +60,7 @@ unix:path - the unix scheme is used to create and connect to unix domain
sockets - the authority must be empty, and the path sockets - the authority must be empty, and the path
represents the absolute or relative path to the desired represents the absolute or relative path to the desired
socket socket
ipv4:host:port - a pre-resolved ipv4 dotted decimal address/port combination
ipv6:[host]:port - a pre-resolved ipv6 address/port combination

@ -62,6 +62,8 @@ typedef struct {
grpc_subchannel *selected; grpc_subchannel *selected;
/** have we started picking? */ /** have we started picking? */
int started_picking; int started_picking;
/** are we shut down? */
int shutdown;
/** which subchannel are we watching? */ /** which subchannel are we watching? */
size_t checking_subchannel; size_t checking_subchannel;
/** what is the connectivity of that channel? */ /** what is the connectivity of that channel? */
@ -73,12 +75,30 @@ typedef struct {
grpc_connectivity_state_tracker state_tracker; grpc_connectivity_state_tracker state_tracker;
} pick_first_lb_policy; } pick_first_lb_policy;
static void del_interested_parties_locked(pick_first_lb_policy *p) {
pending_pick *pp;
for (pp = p->pending_picks; pp; pp = pp->next) {
grpc_subchannel_del_interested_party(p->subchannels[p->checking_subchannel],
pp->pollset);
}
}
static void add_interested_parties_locked(pick_first_lb_policy *p) {
pending_pick *pp;
for (pp = p->pending_picks; pp; pp = pp->next) {
grpc_subchannel_add_interested_party(p->subchannels[p->checking_subchannel],
pp->pollset);
}
}
void pf_destroy(grpc_lb_policy *pol) { void pf_destroy(grpc_lb_policy *pol) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol; pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
size_t i; size_t i;
del_interested_parties_locked(p);
for (i = 0; i < p->num_subchannels; i++) { for (i = 0; i < p->num_subchannels; i++) {
GRPC_SUBCHANNEL_UNREF(p->subchannels[i], "pick_first"); GRPC_SUBCHANNEL_UNREF(p->subchannels[i], "pick_first");
} }
grpc_connectivity_state_destroy(&p->state_tracker);
gpr_free(p->subchannels); gpr_free(p->subchannels);
gpr_mu_destroy(&p->mu); gpr_mu_destroy(&p->mu);
gpr_free(p); gpr_free(p);
@ -88,12 +108,35 @@ void pf_shutdown(grpc_lb_policy *pol) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol; pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
pending_pick *pp; pending_pick *pp;
gpr_mu_lock(&p->mu); gpr_mu_lock(&p->mu);
del_interested_parties_locked(p);
p->shutdown = 1;
while ((pp = p->pending_picks)) { while ((pp = p->pending_picks)) {
p->pending_picks = pp->next; p->pending_picks = pp->next;
*pp->target = NULL; *pp->target = NULL;
grpc_iomgr_add_delayed_callback(pp->on_complete, 0); grpc_iomgr_add_delayed_callback(pp->on_complete, 0);
gpr_free(pp); gpr_free(pp);
} }
grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_FATAL_FAILURE,
"shutdown");
gpr_mu_unlock(&p->mu);
}
static void start_picking(pick_first_lb_policy *p) {
p->started_picking = 1;
p->checking_subchannel = 0;
p->checking_connectivity = GRPC_CHANNEL_IDLE;
GRPC_LB_POLICY_REF(&p->base, "pick_first_connectivity");
grpc_subchannel_notify_on_state_change(p->subchannels[p->checking_subchannel],
&p->checking_connectivity,
&p->connectivity_changed);
}
void pf_exit_idle(grpc_lb_policy *pol) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
gpr_mu_lock(&p->mu);
if (!p->started_picking) {
start_picking(p);
}
gpr_mu_unlock(&p->mu); gpr_mu_unlock(&p->mu);
} }
@ -109,13 +152,7 @@ void pf_pick(grpc_lb_policy *pol, grpc_pollset *pollset,
on_complete->cb(on_complete->cb_arg, 1); on_complete->cb(on_complete->cb_arg, 1);
} else { } else {
if (!p->started_picking) { if (!p->started_picking) {
p->started_picking = 1; start_picking(p);
p->checking_subchannel = 0;
p->checking_connectivity = GRPC_CHANNEL_IDLE;
GRPC_LB_POLICY_REF(pol, "pick_first_connectivity");
grpc_subchannel_notify_on_state_change(
p->subchannels[p->checking_subchannel], &p->checking_connectivity,
&p->connectivity_changed);
} }
grpc_subchannel_add_interested_party(p->subchannels[p->checking_subchannel], grpc_subchannel_add_interested_party(p->subchannels[p->checking_subchannel],
pollset); pollset);
@ -129,31 +166,30 @@ void pf_pick(grpc_lb_policy *pol, grpc_pollset *pollset,
} }
} }
static void del_interested_parties_locked(pick_first_lb_policy *p) {
pending_pick *pp;
for (pp = p->pending_picks; pp; pp = pp->next) {
grpc_subchannel_del_interested_party(p->subchannels[p->checking_subchannel],
pp->pollset);
}
}
static void add_interested_parties_locked(pick_first_lb_policy *p) {
pending_pick *pp;
for (pp = p->pending_picks; pp; pp = pp->next) {
grpc_subchannel_add_interested_party(p->subchannels[p->checking_subchannel],
pp->pollset);
}
}
static void pf_connectivity_changed(void *arg, int iomgr_success) { static void pf_connectivity_changed(void *arg, int iomgr_success) {
pick_first_lb_policy *p = arg; pick_first_lb_policy *p = arg;
pending_pick *pp; pending_pick *pp;
int unref = 0; int unref = 0;
gpr_mu_lock(&p->mu); gpr_mu_lock(&p->mu);
loop:
if (p->shutdown) {
unref = 1;
} else if (p->selected != NULL) {
grpc_connectivity_state_set(&p->state_tracker, p->checking_connectivity,
"selected_changed");
if (p->checking_connectivity != GRPC_CHANNEL_FATAL_FAILURE) {
grpc_subchannel_notify_on_state_change(
p->selected, &p->checking_connectivity, &p->connectivity_changed);
} else {
unref = 1;
}
} else {
loop:
switch (p->checking_connectivity) { switch (p->checking_connectivity) {
case GRPC_CHANNEL_READY: case GRPC_CHANNEL_READY:
grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_READY,
"connecting_ready");
p->selected = p->subchannels[p->checking_subchannel]; p->selected = p->subchannels[p->checking_subchannel];
while ((pp = p->pending_picks)) { while ((pp = p->pending_picks)) {
p->pending_picks = pp->next; p->pending_picks = pp->next;
@ -162,18 +198,31 @@ loop:
grpc_iomgr_add_delayed_callback(pp->on_complete, 1); grpc_iomgr_add_delayed_callback(pp->on_complete, 1);
gpr_free(pp); gpr_free(pp);
} }
unref = 1; grpc_subchannel_notify_on_state_change(
p->selected, &p->checking_connectivity, &p->connectivity_changed);
break; break;
case GRPC_CHANNEL_TRANSIENT_FAILURE: case GRPC_CHANNEL_TRANSIENT_FAILURE:
grpc_connectivity_state_set(&p->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE,
"connecting_transient_failure");
del_interested_parties_locked(p); del_interested_parties_locked(p);
p->checking_subchannel = p->checking_subchannel =
(p->checking_subchannel + 1) % p->num_subchannels; (p->checking_subchannel + 1) % p->num_subchannels;
p->checking_connectivity = grpc_subchannel_check_connectivity( p->checking_connectivity = grpc_subchannel_check_connectivity(
p->subchannels[p->checking_subchannel]); p->subchannels[p->checking_subchannel]);
add_interested_parties_locked(p); add_interested_parties_locked(p);
if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
grpc_subchannel_notify_on_state_change(
p->subchannels[p->checking_subchannel], &p->checking_connectivity,
&p->connectivity_changed);
} else {
goto loop; goto loop;
}
break;
case GRPC_CHANNEL_CONNECTING: case GRPC_CHANNEL_CONNECTING:
case GRPC_CHANNEL_IDLE: case GRPC_CHANNEL_IDLE:
grpc_connectivity_state_set(&p->state_tracker, p->checking_connectivity,
"connecting_changed");
grpc_subchannel_notify_on_state_change( grpc_subchannel_notify_on_state_change(
p->subchannels[p->checking_subchannel], &p->checking_connectivity, p->subchannels[p->checking_subchannel], &p->checking_connectivity,
&p->connectivity_changed); &p->connectivity_changed);
@ -185,6 +234,9 @@ loop:
p->num_subchannels--; p->num_subchannels--;
GRPC_SUBCHANNEL_UNREF(p->subchannels[p->num_subchannels], "pick_first"); GRPC_SUBCHANNEL_UNREF(p->subchannels[p->num_subchannels], "pick_first");
if (p->num_subchannels == 0) { if (p->num_subchannels == 0) {
grpc_connectivity_state_set(&p->state_tracker,
GRPC_CHANNEL_FATAL_FAILURE,
"no_more_channels");
while ((pp = p->pending_picks)) { while ((pp = p->pending_picks)) {
p->pending_picks = pp->next; p->pending_picks = pp->next;
*pp->target = NULL; *pp->target = NULL;
@ -193,6 +245,9 @@ loop:
} }
unref = 1; unref = 1;
} else { } else {
grpc_connectivity_state_set(&p->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE,
"subchannel_failed");
p->checking_subchannel %= p->num_subchannels; p->checking_subchannel %= p->num_subchannels;
p->checking_connectivity = grpc_subchannel_check_connectivity( p->checking_connectivity = grpc_subchannel_check_connectivity(
p->subchannels[p->checking_subchannel]); p->subchannels[p->checking_subchannel]);
@ -200,6 +255,8 @@ loop:
goto loop; goto loop;
} }
} }
}
gpr_mu_unlock(&p->mu); gpr_mu_unlock(&p->mu);
if (unref) { if (unref) {
@ -249,8 +306,13 @@ static void pf_notify_on_state_change(grpc_lb_policy *pol,
} }
static const grpc_lb_policy_vtable pick_first_lb_policy_vtable = { static const grpc_lb_policy_vtable pick_first_lb_policy_vtable = {
pf_destroy, pf_shutdown, pf_pick, pf_destroy,
pf_broadcast, pf_check_connectivity, pf_notify_on_state_change}; pf_shutdown,
pf_pick,
pf_exit_idle,
pf_broadcast,
pf_check_connectivity,
pf_notify_on_state_change};
grpc_lb_policy *grpc_create_pick_first_lb_policy(grpc_subchannel **subchannels, grpc_lb_policy *grpc_create_pick_first_lb_policy(grpc_subchannel **subchannels,
size_t num_subchannels) { size_t num_subchannels) {
@ -260,6 +322,8 @@ grpc_lb_policy *grpc_create_pick_first_lb_policy(grpc_subchannel **subchannels,
grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable); grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable);
p->subchannels = gpr_malloc(sizeof(grpc_subchannel *) * num_subchannels); p->subchannels = gpr_malloc(sizeof(grpc_subchannel *) * num_subchannels);
p->num_subchannels = num_subchannels; p->num_subchannels = num_subchannels;
grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE,
"pick_first");
memcpy(p->subchannels, subchannels, memcpy(p->subchannels, subchannels,
sizeof(grpc_subchannel *) * num_subchannels); sizeof(grpc_subchannel *) * num_subchannels);
grpc_iomgr_closure_init(&p->connectivity_changed, pf_connectivity_changed, p); grpc_iomgr_closure_init(&p->connectivity_changed, pf_connectivity_changed, p);

@ -77,3 +77,18 @@ void grpc_lb_policy_pick(grpc_lb_policy *policy, grpc_pollset *pollset,
void grpc_lb_policy_broadcast(grpc_lb_policy *policy, grpc_transport_op *op) { void grpc_lb_policy_broadcast(grpc_lb_policy *policy, grpc_transport_op *op) {
policy->vtable->broadcast(policy, op); policy->vtable->broadcast(policy, op);
} }
void grpc_lb_policy_exit_idle(grpc_lb_policy *policy) {
policy->vtable->exit_idle(policy);
}
void grpc_lb_policy_notify_on_state_change(grpc_lb_policy *policy,
grpc_connectivity_state *state,
grpc_iomgr_closure *closure) {
policy->vtable->notify_on_state_change(policy, state, closure);
}
grpc_connectivity_state grpc_lb_policy_check_connectivity(
grpc_lb_policy *policy) {
return policy->vtable->check_connectivity(policy);
}

@ -59,6 +59,9 @@ struct grpc_lb_policy_vtable {
grpc_metadata_batch *initial_metadata, grpc_subchannel **target, grpc_metadata_batch *initial_metadata, grpc_subchannel **target,
grpc_iomgr_closure *on_complete); grpc_iomgr_closure *on_complete);
/** try to enter a READY connectivity state */
void (*exit_idle)(grpc_lb_policy *policy);
/** broadcast a transport op to all subchannels */ /** broadcast a transport op to all subchannels */
void (*broadcast)(grpc_lb_policy *policy, grpc_transport_op *op); void (*broadcast)(grpc_lb_policy *policy, grpc_transport_op *op);
@ -106,4 +109,13 @@ void grpc_lb_policy_pick(grpc_lb_policy *policy, grpc_pollset *pollset,
void grpc_lb_policy_broadcast(grpc_lb_policy *policy, grpc_transport_op *op); void grpc_lb_policy_broadcast(grpc_lb_policy *policy, grpc_transport_op *op);
void grpc_lb_policy_exit_idle(grpc_lb_policy *policy);
void grpc_lb_policy_notify_on_state_change(grpc_lb_policy *policy,
grpc_connectivity_state *state,
grpc_iomgr_closure *closure);
grpc_connectivity_state grpc_lb_policy_check_connectivity(
grpc_lb_policy *policy);
#endif /* GRPC_INTERNAL_CORE_CONFIG_LB_POLICY_H */ #endif /* GRPC_INTERNAL_CORE_CONFIG_LB_POLICY_H */

@ -0,0 +1,299 @@
/*
*
* 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/support/port_platform.h>
#include "src/core/client_config/resolvers/sockaddr_resolver.h"
#include <stdio.h>
#include <string.h>
#ifdef GPR_POSIX_SOCKET
#include <sys/un.h>
#endif
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/string_util.h>
#include "src/core/client_config/lb_policies/pick_first.h"
#include "src/core/iomgr/resolve_address.h"
#include "src/core/support/string.h"
typedef struct {
/** base class: must be first */
grpc_resolver base;
/** refcount */
gpr_refcount refs;
/** subchannel factory */
grpc_subchannel_factory *subchannel_factory;
/** load balancing policy factory */
grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels,
size_t num_subchannels);
/** the address that we've 'resolved' */
struct sockaddr_storage addr;
int addr_len;
/** mutex guarding the rest of the state */
gpr_mu mu;
/** have we published? */
int published;
/** pending next completion, or NULL */
grpc_iomgr_closure *next_completion;
/** target config address for next completion */
grpc_client_config **target_config;
} sockaddr_resolver;
static void sockaddr_destroy(grpc_resolver *r);
static void sockaddr_maybe_finish_next_locked(sockaddr_resolver *r);
static void sockaddr_shutdown(grpc_resolver *r);
static void sockaddr_channel_saw_error(grpc_resolver *r,
struct sockaddr *failing_address,
int failing_address_len);
static void sockaddr_next(grpc_resolver *r, grpc_client_config **target_config,
grpc_iomgr_closure *on_complete);
static const grpc_resolver_vtable sockaddr_resolver_vtable = {
sockaddr_destroy, sockaddr_shutdown, sockaddr_channel_saw_error,
sockaddr_next};
static void sockaddr_shutdown(grpc_resolver *resolver) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver;
gpr_mu_lock(&r->mu);
if (r->next_completion != NULL) {
*r->target_config = NULL;
/* TODO(ctiller): add delayed callback */
grpc_iomgr_add_callback(r->next_completion);
r->next_completion = NULL;
}
gpr_mu_unlock(&r->mu);
}
static void sockaddr_channel_saw_error(grpc_resolver *resolver,
struct sockaddr *sa, int len) {}
static void sockaddr_next(grpc_resolver *resolver,
grpc_client_config **target_config,
grpc_iomgr_closure *on_complete) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver;
gpr_mu_lock(&r->mu);
GPR_ASSERT(!r->next_completion);
r->next_completion = on_complete;
r->target_config = target_config;
sockaddr_maybe_finish_next_locked(r);
gpr_mu_unlock(&r->mu);
}
static void sockaddr_maybe_finish_next_locked(sockaddr_resolver *r) {
grpc_client_config *cfg;
grpc_lb_policy *lb_policy;
grpc_subchannel *subchannel;
grpc_subchannel_args args;
if (r->next_completion != NULL && !r->published) {
cfg = grpc_client_config_create();
memset(&args, 0, sizeof(args));
args.addr = (struct sockaddr *)&r->addr;
args.addr_len = r->addr_len;
subchannel =
grpc_subchannel_factory_create_subchannel(r->subchannel_factory, &args);
lb_policy = r->lb_policy_factory(&subchannel, 1);
grpc_client_config_set_lb_policy(cfg, lb_policy);
GRPC_LB_POLICY_UNREF(lb_policy, "unix");
r->published = 1;
*r->target_config = cfg;
grpc_iomgr_add_callback(r->next_completion);
r->next_completion = NULL;
}
}
static void sockaddr_destroy(grpc_resolver *gr) {
sockaddr_resolver *r = (sockaddr_resolver *)gr;
gpr_mu_destroy(&r->mu);
grpc_subchannel_factory_unref(r->subchannel_factory);
gpr_free(r);
}
#ifdef GPR_POSIX_SOCKET
static int parse_unix(grpc_uri *uri, struct sockaddr_storage *addr, int *len) {
struct sockaddr_un *un = (struct sockaddr_un *)addr;
un->sun_family = AF_UNIX;
strcpy(un->sun_path, uri->path);
*len = strlen(un->sun_path) + sizeof(un->sun_family) + 1;
return 1;
}
#endif
static int parse_ipv4(grpc_uri *uri, struct sockaddr_storage *addr, int *len) {
const char *host_port = uri->path;
char *host;
char *port;
int port_num;
int result = 0;
struct sockaddr_in *in = (struct sockaddr_in *)addr;
if (*host_port == '/') ++host_port;
if (!gpr_split_host_port(host_port, &host, &port)) {
return 0;
}
memset(in, 0, sizeof(*in));
*len = sizeof(*in);
in->sin_family = AF_INET;
if (inet_pton(AF_INET, host, &in->sin_addr) == 0) {
gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host);
goto done;
}
if (port != NULL) {
if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 ||
port_num > 65535) {
gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port);
goto done;
}
in->sin_port = htons(port_num);
} else {
gpr_log(GPR_ERROR, "no port given for ipv4 scheme");
goto done;
}
result = 1;
done:
gpr_free(host);
gpr_free(port);
return result;
}
static int parse_ipv6(grpc_uri *uri, struct sockaddr_storage *addr, int *len) {
const char *host_port = uri->path;
char *host;
char *port;
int port_num;
int result = 0;
struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr;
if (*host_port == '/') ++host_port;
if (!gpr_split_host_port(host_port, &host, &port)) {
return 0;
}
memset(in6, 0, sizeof(*in6));
*len = sizeof(*in6);
in6->sin6_family = AF_INET6;
if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) {
gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host);
goto done;
}
if (port != NULL) {
if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 ||
port_num > 65535) {
gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port);
goto done;
}
in6->sin6_port = htons(port_num);
} else {
gpr_log(GPR_ERROR, "no port given for ipv6 scheme");
goto done;
}
result = 1;
done:
gpr_free(host);
gpr_free(port);
return result;
}
static grpc_resolver *sockaddr_create(
grpc_uri *uri,
grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels,
size_t num_subchannels),
grpc_subchannel_factory *subchannel_factory,
int parse(grpc_uri *uri, struct sockaddr_storage *dst, int *len)) {
sockaddr_resolver *r;
if (0 != strcmp(uri->authority, "")) {
gpr_log(GPR_ERROR, "authority based uri's not supported");
return NULL;
}
r = gpr_malloc(sizeof(sockaddr_resolver));
memset(r, 0, sizeof(*r));
if (!parse(uri, &r->addr, &r->addr_len)) {
gpr_free(r);
return NULL;
}
gpr_ref_init(&r->refs, 1);
gpr_mu_init(&r->mu);
grpc_resolver_init(&r->base, &sockaddr_resolver_vtable);
r->subchannel_factory = subchannel_factory;
r->lb_policy_factory = lb_policy_factory;
grpc_subchannel_factory_ref(subchannel_factory);
return &r->base;
}
/*
* FACTORY
*/
static void sockaddr_factory_ref(grpc_resolver_factory *factory) {}
static void sockaddr_factory_unref(grpc_resolver_factory *factory) {}
#define DECL_FACTORY(name) \
static grpc_resolver *name##_factory_create_resolver( \
grpc_resolver_factory *factory, grpc_uri *uri, \
grpc_subchannel_factory *subchannel_factory) { \
return sockaddr_create(uri, grpc_create_pick_first_lb_policy, \
subchannel_factory, parse_##name); \
} \
static const grpc_resolver_factory_vtable name##_factory_vtable = { \
sockaddr_factory_ref, sockaddr_factory_unref, \
name##_factory_create_resolver}; \
static grpc_resolver_factory name##_resolver_factory = { \
&name##_factory_vtable}; \
grpc_resolver_factory *grpc_##name##_resolver_factory_create() { \
return &name##_resolver_factory; \
}
#ifdef GPR_POSIX_SOCKET
DECL_FACTORY(unix)
#endif
DECL_FACTORY(ipv4)
DECL_FACTORY(ipv6)

@ -38,7 +38,13 @@
#include "src/core/client_config/resolver_factory.h" #include "src/core/client_config/resolver_factory.h"
grpc_resolver_factory *grpc_ipv4_resolver_factory_create(void);
grpc_resolver_factory *grpc_ipv6_resolver_factory_create(void);
#ifdef GPR_POSIX_SOCKET
/** Create a unix resolver factory */ /** Create a unix resolver factory */
grpc_resolver_factory *grpc_unix_resolver_factory_create(void); grpc_resolver_factory *grpc_unix_resolver_factory_create(void);
#endif
#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_RESOLVERS_UNIX_RESOLVER_H */ #endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_RESOLVERS_UNIX_RESOLVER_H */

@ -1,195 +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/support/port_platform.h>
#ifdef GPR_POSIX_SOCKET
#include "src/core/client_config/resolvers/unix_resolver_posix.h"
#include <string.h>
#include <sys/un.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include "src/core/client_config/lb_policies/pick_first.h"
#include "src/core/iomgr/resolve_address.h"
#include "src/core/support/string.h"
typedef struct {
/** base class: must be first */
grpc_resolver base;
/** refcount */
gpr_refcount refs;
/** subchannel factory */
grpc_subchannel_factory *subchannel_factory;
/** load balancing policy factory */
grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels,
size_t num_subchannels);
/** the address that we've 'resolved' */
struct sockaddr_un addr;
int addr_len;
/** mutex guarding the rest of the state */
gpr_mu mu;
/** have we published? */
int published;
/** pending next completion, or NULL */
grpc_iomgr_closure *next_completion;
/** target config address for next completion */
grpc_client_config **target_config;
} unix_resolver;
static void unix_destroy(grpc_resolver *r);
static void unix_maybe_finish_next_locked(unix_resolver *r);
static void unix_shutdown(grpc_resolver *r);
static void unix_channel_saw_error(grpc_resolver *r,
struct sockaddr *failing_address,
int failing_address_len);
static void unix_next(grpc_resolver *r, grpc_client_config **target_config,
grpc_iomgr_closure *on_complete);
static const grpc_resolver_vtable unix_resolver_vtable = {
unix_destroy, unix_shutdown, unix_channel_saw_error, unix_next};
static void unix_shutdown(grpc_resolver *resolver) {
unix_resolver *r = (unix_resolver *)resolver;
gpr_mu_lock(&r->mu);
if (r->next_completion != NULL) {
*r->target_config = NULL;
/* TODO(ctiller): add delayed callback */
grpc_iomgr_add_callback(r->next_completion);
r->next_completion = NULL;
}
gpr_mu_unlock(&r->mu);
}
static void unix_channel_saw_error(grpc_resolver *resolver, struct sockaddr *sa,
int len) {}
static void unix_next(grpc_resolver *resolver,
grpc_client_config **target_config,
grpc_iomgr_closure *on_complete) {
unix_resolver *r = (unix_resolver *)resolver;
gpr_mu_lock(&r->mu);
GPR_ASSERT(!r->next_completion);
r->next_completion = on_complete;
r->target_config = target_config;
unix_maybe_finish_next_locked(r);
gpr_mu_unlock(&r->mu);
}
static void unix_maybe_finish_next_locked(unix_resolver *r) {
grpc_client_config *cfg;
grpc_lb_policy *lb_policy;
grpc_subchannel *subchannel;
grpc_subchannel_args args;
if (r->next_completion != NULL && !r->published) {
cfg = grpc_client_config_create();
memset(&args, 0, sizeof(args));
args.addr = (struct sockaddr *)&r->addr;
args.addr_len = r->addr_len;
subchannel =
grpc_subchannel_factory_create_subchannel(r->subchannel_factory, &args);
lb_policy = r->lb_policy_factory(&subchannel, 1);
grpc_client_config_set_lb_policy(cfg, lb_policy);
GRPC_LB_POLICY_UNREF(lb_policy, "unix");
r->published = 1;
*r->target_config = cfg;
grpc_iomgr_add_callback(r->next_completion);
r->next_completion = NULL;
}
}
static void unix_destroy(grpc_resolver *gr) {
unix_resolver *r = (unix_resolver *)gr;
gpr_mu_destroy(&r->mu);
grpc_subchannel_factory_unref(r->subchannel_factory);
gpr_free(r);
}
static grpc_resolver *unix_create(
grpc_uri *uri,
grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels,
size_t num_subchannels),
grpc_subchannel_factory *subchannel_factory) {
unix_resolver *r;
if (0 != strcmp(uri->authority, "")) {
gpr_log(GPR_ERROR, "authority based uri's not supported");
return NULL;
}
r = gpr_malloc(sizeof(unix_resolver));
memset(r, 0, sizeof(*r));
gpr_ref_init(&r->refs, 1);
gpr_mu_init(&r->mu);
grpc_resolver_init(&r->base, &unix_resolver_vtable);
r->subchannel_factory = subchannel_factory;
r->lb_policy_factory = lb_policy_factory;
r->addr.sun_family = AF_UNIX;
strcpy(r->addr.sun_path, uri->path);
r->addr_len = strlen(r->addr.sun_path) + sizeof(r->addr.sun_family) + 1;
grpc_subchannel_factory_ref(subchannel_factory);
return &r->base;
}
/*
* FACTORY
*/
static void unix_factory_ref(grpc_resolver_factory *factory) {}
static void unix_factory_unref(grpc_resolver_factory *factory) {}
static grpc_resolver *unix_factory_create_resolver(
grpc_resolver_factory *factory, grpc_uri *uri,
grpc_subchannel_factory *subchannel_factory) {
return unix_create(uri, grpc_create_pick_first_lb_policy, subchannel_factory);
}
static const grpc_resolver_factory_vtable unix_factory_vtable = {
unix_factory_ref, unix_factory_unref, unix_factory_create_resolver};
static grpc_resolver_factory unix_resolver_factory = {&unix_factory_vtable};
grpc_resolver_factory *grpc_unix_resolver_factory_create() {
return &unix_resolver_factory;
}
#endif

@ -38,9 +38,11 @@
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include "src/core/channel/channel_args.h" #include "src/core/channel/channel_args.h"
#include "src/core/channel/client_channel.h"
#include "src/core/channel/connected_channel.h" #include "src/core/channel/connected_channel.h"
#include "src/core/iomgr/alarm.h" #include "src/core/iomgr/alarm.h"
#include "src/core/transport/connectivity_state.h" #include "src/core/transport/connectivity_state.h"
#include "src/core/surface/channel.h"
typedef struct { typedef struct {
/* all fields protected by subchannel->mu */ /* all fields protected by subchannel->mu */
@ -94,8 +96,10 @@ struct grpc_subchannel {
grpc_iomgr_closure connected; grpc_iomgr_closure connected;
/** pollset_set tracking who's interested in a connection /** pollset_set tracking who's interested in a connection
being setup */ being setup - owned by the master channel (in particular the
grpc_pollset_set pollset_set; client_channel
filter there-in) */
grpc_pollset_set *pollset_set;
/** mutex protecting remaining elements */ /** mutex protecting remaining elements */
gpr_mu mu; gpr_mu mu;
@ -132,7 +136,8 @@ struct grpc_subchannel_call {
#define CHANNEL_STACK_FROM_CONNECTION(con) ((grpc_channel_stack *)((con) + 1)) #define CHANNEL_STACK_FROM_CONNECTION(con) ((grpc_channel_stack *)((con) + 1))
static grpc_subchannel_call *create_call(connection *con); static grpc_subchannel_call *create_call(connection *con);
static void connectivity_state_changed_locked(grpc_subchannel *c); static void connectivity_state_changed_locked(grpc_subchannel *c,
const char *reason);
static grpc_connectivity_state compute_connectivity_locked(grpc_subchannel *c); static grpc_connectivity_state compute_connectivity_locked(grpc_subchannel *c);
static gpr_timespec compute_connect_deadline(grpc_subchannel *c); static gpr_timespec compute_connect_deadline(grpc_subchannel *c);
static void subchannel_connected(void *subchannel, int iomgr_success); static void subchannel_connected(void *subchannel, int iomgr_success);
@ -244,7 +249,6 @@ static void subchannel_destroy(grpc_subchannel *c) {
grpc_channel_args_destroy(c->args); grpc_channel_args_destroy(c->args);
gpr_free(c->addr); gpr_free(c->addr);
grpc_mdctx_unref(c->mdctx); grpc_mdctx_unref(c->mdctx);
grpc_pollset_set_destroy(&c->pollset_set);
grpc_connectivity_state_destroy(&c->state_tracker); grpc_connectivity_state_destroy(&c->state_tracker);
grpc_connector_unref(c->connector); grpc_connector_unref(c->connector);
gpr_free(c); gpr_free(c);
@ -252,17 +256,19 @@ static void subchannel_destroy(grpc_subchannel *c) {
void grpc_subchannel_add_interested_party(grpc_subchannel *c, void grpc_subchannel_add_interested_party(grpc_subchannel *c,
grpc_pollset *pollset) { grpc_pollset *pollset) {
grpc_pollset_set_add_pollset(&c->pollset_set, pollset); grpc_pollset_set_add_pollset(c->pollset_set, pollset);
} }
void grpc_subchannel_del_interested_party(grpc_subchannel *c, void grpc_subchannel_del_interested_party(grpc_subchannel *c,
grpc_pollset *pollset) { grpc_pollset *pollset) {
grpc_pollset_set_del_pollset(&c->pollset_set, pollset); grpc_pollset_set_del_pollset(c->pollset_set, pollset);
} }
grpc_subchannel *grpc_subchannel_create(grpc_connector *connector, grpc_subchannel *grpc_subchannel_create(grpc_connector *connector,
grpc_subchannel_args *args) { grpc_subchannel_args *args) {
grpc_subchannel *c = gpr_malloc(sizeof(*c)); grpc_subchannel *c = gpr_malloc(sizeof(*c));
grpc_channel_element *parent_elem = grpc_channel_stack_last_element(
grpc_channel_get_channel_stack(args->master));
memset(c, 0, sizeof(*c)); memset(c, 0, sizeof(*c));
c->refs = 1; c->refs = 1;
c->connector = connector; c->connector = connector;
@ -277,10 +283,11 @@ grpc_subchannel *grpc_subchannel_create(grpc_connector *connector,
c->args = grpc_channel_args_copy(args->args); c->args = grpc_channel_args_copy(args->args);
c->mdctx = args->mdctx; c->mdctx = args->mdctx;
c->master = args->master; c->master = args->master;
c->pollset_set = grpc_client_channel_get_connecting_pollset_set(parent_elem);
grpc_mdctx_ref(c->mdctx); grpc_mdctx_ref(c->mdctx);
grpc_pollset_set_init(&c->pollset_set);
grpc_iomgr_closure_init(&c->connected, subchannel_connected, c); grpc_iomgr_closure_init(&c->connected, subchannel_connected, c);
grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE); grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE,
"subchannel");
gpr_mu_init(&c->mu); gpr_mu_init(&c->mu);
return c; return c;
} }
@ -288,7 +295,7 @@ grpc_subchannel *grpc_subchannel_create(grpc_connector *connector,
static void continue_connect(grpc_subchannel *c) { static void continue_connect(grpc_subchannel *c) {
grpc_connect_in_args args; grpc_connect_in_args args;
args.interested_parties = &c->pollset_set; args.interested_parties = c->pollset_set;
args.addr = c->addr; args.addr = c->addr;
args.addr_len = c->addr_len; args.addr_len = c->addr_len;
args.deadline = compute_connect_deadline(c); args.deadline = compute_connect_deadline(c);
@ -300,7 +307,7 @@ static void continue_connect(grpc_subchannel *c) {
} }
static void start_connect(grpc_subchannel *c) { static void start_connect(grpc_subchannel *c) {
gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
c->next_attempt = now; c->next_attempt = now;
c->backoff_delta = gpr_time_from_seconds(1, GPR_TIMESPAN); c->backoff_delta = gpr_time_from_seconds(1, GPR_TIMESPAN);
@ -309,6 +316,7 @@ static void start_connect(grpc_subchannel *c) {
static void continue_creating_call(void *arg, int iomgr_success) { static void continue_creating_call(void *arg, int iomgr_success) {
waiting_for_connect *w4c = arg; waiting_for_connect *w4c = arg;
grpc_subchannel_del_interested_party(w4c->subchannel, w4c->pollset);
grpc_subchannel_create_call(w4c->subchannel, w4c->pollset, w4c->target, grpc_subchannel_create_call(w4c->subchannel, w4c->pollset, w4c->target,
w4c->notify); w4c->notify);
GRPC_SUBCHANNEL_UNREF(w4c->subchannel, "waiting_for_connect"); GRPC_SUBCHANNEL_UNREF(w4c->subchannel, "waiting_for_connect");
@ -341,9 +349,10 @@ void grpc_subchannel_create_call(grpc_subchannel *c, grpc_pollset *pollset,
grpc_subchannel_add_interested_party(c, pollset); grpc_subchannel_add_interested_party(c, pollset);
if (!c->connecting) { if (!c->connecting) {
c->connecting = 1; c->connecting = 1;
connectivity_state_changed_locked(c); connectivity_state_changed_locked(c, "create_call");
/* released by connection */ /* released by connection */
SUBCHANNEL_REF_LOCKED(c, "connecting"); SUBCHANNEL_REF_LOCKED(c, "connecting");
GRPC_CHANNEL_INTERNAL_REF(c->master, "connecting");
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
start_connect(c); start_connect(c);
@ -372,7 +381,8 @@ void grpc_subchannel_notify_on_state_change(grpc_subchannel *c,
c->connecting = 1; c->connecting = 1;
/* released by connection */ /* released by connection */
SUBCHANNEL_REF_LOCKED(c, "connecting"); SUBCHANNEL_REF_LOCKED(c, "connecting");
connectivity_state_changed_locked(c); GRPC_CHANNEL_INTERNAL_REF(c->master, "connecting");
connectivity_state_changed_locked(c, "state_change");
} }
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
if (do_connect) { if (do_connect) {
@ -388,7 +398,7 @@ void grpc_subchannel_process_transport_op(grpc_subchannel *c,
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
if (op->disconnect) { if (op->disconnect) {
c->disconnected = 1; c->disconnected = 1;
connectivity_state_changed_locked(c); connectivity_state_changed_locked(c, "disconnect");
if (c->have_alarm) { if (c->have_alarm) {
cancel_alarm = 1; cancel_alarm = 1;
} }
@ -456,13 +466,15 @@ static void on_state_changed(void *p, int iomgr_success) {
destroy_connection = sw->subchannel->active; destroy_connection = sw->subchannel->active;
} }
sw->subchannel->active = NULL; sw->subchannel->active = NULL;
grpc_connectivity_state_set(&c->state_tracker, grpc_connectivity_state_set(
GRPC_CHANNEL_TRANSIENT_FAILURE); &c->state_tracker, c->disconnected ? GRPC_CHANNEL_FATAL_FAILURE
: GRPC_CHANNEL_TRANSIENT_FAILURE,
"connection_failed");
break; break;
} }
done: done:
connectivity_state_changed_locked(c); connectivity_state_changed_locked(c, "transport_state_changed");
destroy = SUBCHANNEL_UNREF_LOCKED(c, "state_watcher"); destroy = SUBCHANNEL_UNREF_LOCKED(c, "state_watcher");
gpr_free(sw); gpr_free(sw);
gpr_mu_unlock(mu); gpr_mu_unlock(mu);
@ -486,6 +498,8 @@ static void publish_transport(grpc_subchannel *c) {
connection *destroy_connection = NULL; connection *destroy_connection = NULL;
grpc_channel_element *elem; grpc_channel_element *elem;
gpr_log(GPR_DEBUG, "publish_transport: %p", c->master);
/* build final filter list */ /* build final filter list */
num_filters = c->num_filters + c->connecting_result.num_filters + 1; num_filters = c->num_filters + c->connecting_result.num_filters + 1;
filters = gpr_malloc(sizeof(*filters) * num_filters); filters = gpr_malloc(sizeof(*filters) * num_filters);
@ -519,6 +533,8 @@ static void publish_transport(grpc_subchannel *c) {
gpr_free(sw); gpr_free(sw);
gpr_free(filters); gpr_free(filters);
grpc_channel_stack_destroy(stk); grpc_channel_stack_destroy(stk);
GRPC_CHANNEL_INTERNAL_UNREF(c->master, "connecting");
GRPC_SUBCHANNEL_UNREF(c, "connecting");
return; return;
} }
@ -536,14 +552,16 @@ static void publish_transport(grpc_subchannel *c) {
memset(&op, 0, sizeof(op)); memset(&op, 0, sizeof(op));
op.connectivity_state = &sw->connectivity_state; op.connectivity_state = &sw->connectivity_state;
op.on_connectivity_state_change = &sw->closure; op.on_connectivity_state_change = &sw->closure;
op.bind_pollset_set = c->pollset_set;
SUBCHANNEL_REF_LOCKED(c, "state_watcher"); SUBCHANNEL_REF_LOCKED(c, "state_watcher");
GRPC_CHANNEL_INTERNAL_UNREF(c->master, "connecting");
GPR_ASSERT(!SUBCHANNEL_UNREF_LOCKED(c, "connecting")); GPR_ASSERT(!SUBCHANNEL_UNREF_LOCKED(c, "connecting"));
elem = elem =
grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(c->active), 0); grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(c->active), 0);
elem->filter->start_transport_op(elem, &op); elem->filter->start_transport_op(elem, &op);
/* signal completion */ /* signal completion */
connectivity_state_changed_locked(c); connectivity_state_changed_locked(c, "connected");
while ((w4c = c->waiting)) { while ((w4c = c->waiting)) {
c->waiting = w4c->next; c->waiting = w4c->next;
grpc_iomgr_add_callback(&w4c->continuation); grpc_iomgr_add_callback(&w4c->continuation);
@ -565,11 +583,12 @@ static void on_alarm(void *arg, int iomgr_success) {
if (c->disconnected) { if (c->disconnected) {
iomgr_success = 0; iomgr_success = 0;
} }
connectivity_state_changed_locked(c); connectivity_state_changed_locked(c, "alarm");
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
if (iomgr_success) { if (iomgr_success) {
continue_connect(c); continue_connect(c);
} else { } else {
GRPC_CHANNEL_INTERNAL_UNREF(c->master, "connecting");
GRPC_SUBCHANNEL_UNREF(c, "connecting"); GRPC_SUBCHANNEL_UNREF(c, "connecting");
} }
} }
@ -579,13 +598,17 @@ static void subchannel_connected(void *arg, int iomgr_success) {
if (c->connecting_result.transport != NULL) { if (c->connecting_result.transport != NULL) {
publish_transport(c); publish_transport(c);
} else { } else {
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
connectivity_state_changed_locked(c);
GPR_ASSERT(!c->have_alarm); GPR_ASSERT(!c->have_alarm);
c->have_alarm = 1; c->have_alarm = 1;
connectivity_state_changed_locked(c, "connect_failed");
c->next_attempt = gpr_time_add(c->next_attempt, c->backoff_delta); c->next_attempt = gpr_time_add(c->next_attempt, c->backoff_delta);
if (gpr_time_cmp(c->backoff_delta,
gpr_time_from_seconds(60, GPR_TIMESPAN)) < 0) {
c->backoff_delta = gpr_time_add(c->backoff_delta, c->backoff_delta); c->backoff_delta = gpr_time_add(c->backoff_delta, c->backoff_delta);
grpc_alarm_init(&c->alarm, c->next_attempt, on_alarm, c, gpr_now(GPR_CLOCK_REALTIME)); }
grpc_alarm_init(&c->alarm, c->next_attempt, on_alarm, c, now);
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
} }
} }
@ -610,9 +633,10 @@ static grpc_connectivity_state compute_connectivity_locked(grpc_subchannel *c) {
return GRPC_CHANNEL_IDLE; return GRPC_CHANNEL_IDLE;
} }
static void connectivity_state_changed_locked(grpc_subchannel *c) { static void connectivity_state_changed_locked(grpc_subchannel *c,
const char *reason) {
grpc_connectivity_state current = compute_connectivity_locked(c); grpc_connectivity_state current = compute_connectivity_locked(c);
grpc_connectivity_state_set(&c->state_tracker, current); grpc_connectivity_state_set(&c->state_tracker, current, reason);
} }
/* /*
@ -640,6 +664,12 @@ void grpc_subchannel_call_unref(
} }
} }
char *grpc_subchannel_call_get_peer(grpc_subchannel_call *call) {
grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0);
return top_elem->filter->get_peer(top_elem);
}
void grpc_subchannel_call_process_op(grpc_subchannel_call *call, void grpc_subchannel_call_process_op(grpc_subchannel_call *call,
grpc_transport_stream_op *op) { grpc_transport_stream_op *op) {
grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call); grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);

@ -100,6 +100,9 @@ void grpc_subchannel_del_interested_party(grpc_subchannel *channel,
void grpc_subchannel_call_process_op(grpc_subchannel_call *subchannel_call, void grpc_subchannel_call_process_op(grpc_subchannel_call *subchannel_call,
grpc_transport_stream_op *op); grpc_transport_stream_op *op);
/** continue querying for peer */
char *grpc_subchannel_call_get_peer(grpc_subchannel_call *subchannel_call);
struct grpc_subchannel_args { struct grpc_subchannel_args {
/** Channel filters for this channel - wrapped factories will likely /** Channel filters for this channel - wrapped factories will likely
want to mutate this */ want to mutate this */

@ -36,6 +36,7 @@
#include "src/core/iomgr/alarm_heap.h" #include "src/core/iomgr/alarm_heap.h"
#include "src/core/iomgr/alarm_internal.h" #include "src/core/iomgr/alarm_internal.h"
#include "src/core/iomgr/time_averaged_stats.h" #include "src/core/iomgr/time_averaged_stats.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>
@ -67,6 +68,7 @@ typedef struct {
static gpr_mu g_mu; static gpr_mu g_mu;
/* Allow only one run_some_expired_alarms at once */ /* Allow only one run_some_expired_alarms at once */
static gpr_mu g_checker_mu; static gpr_mu g_checker_mu;
static gpr_clock_type g_clock_type;
static shard_type g_shards[NUM_SHARDS]; static shard_type g_shards[NUM_SHARDS];
/* Protected by g_mu */ /* Protected by g_mu */
static shard_type *g_shard_queue[NUM_SHARDS]; static shard_type *g_shard_queue[NUM_SHARDS];
@ -85,6 +87,7 @@ void grpc_alarm_list_init(gpr_timespec now) {
gpr_mu_init(&g_mu); gpr_mu_init(&g_mu);
gpr_mu_init(&g_checker_mu); gpr_mu_init(&g_checker_mu);
g_clock_type = now.clock_type;
for (i = 0; i < NUM_SHARDS; i++) { for (i = 0; i < NUM_SHARDS; i++) {
shard_type *shard = &g_shards[i]; shard_type *shard = &g_shards[i];
@ -102,7 +105,7 @@ void grpc_alarm_list_init(gpr_timespec now) {
void grpc_alarm_list_shutdown(void) { void grpc_alarm_list_shutdown(void) {
int i; int i;
while (run_some_expired_alarms(NULL, gpr_inf_future(GPR_CLOCK_REALTIME), NULL, while (run_some_expired_alarms(NULL, gpr_inf_future(g_clock_type), NULL,
0)) 0))
; ;
for (i = 0; i < NUM_SHARDS; i++) { for (i = 0; i < NUM_SHARDS; i++) {
@ -175,6 +178,8 @@ void grpc_alarm_init(grpc_alarm *alarm, gpr_timespec deadline,
gpr_timespec now) { gpr_timespec now) {
int is_first_alarm = 0; int is_first_alarm = 0;
shard_type *shard = &g_shards[shard_idx(alarm)]; shard_type *shard = &g_shards[shard_idx(alarm)];
GPR_ASSERT(deadline.clock_type == g_clock_type);
GPR_ASSERT(now.clock_type == g_clock_type);
alarm->cb = alarm_cb; alarm->cb = alarm_cb;
alarm->cb_arg = alarm_cb_arg; alarm->cb_arg = alarm_cb_arg;
alarm->deadline = deadline; alarm->deadline = deadline;
@ -355,7 +360,10 @@ static int run_some_expired_alarms(gpr_mu *drop_mu, gpr_timespec now,
} }
int grpc_alarm_check(gpr_mu *drop_mu, gpr_timespec now, gpr_timespec *next) { int grpc_alarm_check(gpr_mu *drop_mu, gpr_timespec now, gpr_timespec *next) {
return run_some_expired_alarms(drop_mu, now, next, 1); GPR_ASSERT(now.clock_type == g_clock_type);
return run_some_expired_alarms(
drop_mu, now, next,
gpr_time_cmp(now, gpr_inf_future(now.clock_type)) != 0);
} }
gpr_timespec grpc_alarm_list_next_timeout(void) { gpr_timespec grpc_alarm_list_next_timeout(void) {

@ -50,6 +50,14 @@ void grpc_endpoint_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) {
ep->vtable->add_to_pollset(ep, pollset); ep->vtable->add_to_pollset(ep, pollset);
} }
void grpc_endpoint_add_to_pollset_set(grpc_endpoint *ep, grpc_pollset_set *pollset_set) {
ep->vtable->add_to_pollset_set(ep, pollset_set);
}
void grpc_endpoint_shutdown(grpc_endpoint *ep) { ep->vtable->shutdown(ep); } void grpc_endpoint_shutdown(grpc_endpoint *ep) { ep->vtable->shutdown(ep); }
void grpc_endpoint_destroy(grpc_endpoint *ep) { ep->vtable->destroy(ep); } void grpc_endpoint_destroy(grpc_endpoint *ep) { ep->vtable->destroy(ep); }
char *grpc_endpoint_get_peer(grpc_endpoint *ep) {
return ep->vtable->get_peer(ep);
}

@ -35,6 +35,7 @@
#define GRPC_INTERNAL_CORE_IOMGR_ENDPOINT_H #define GRPC_INTERNAL_CORE_IOMGR_ENDPOINT_H
#include "src/core/iomgr/pollset.h" #include "src/core/iomgr/pollset.h"
#include "src/core/iomgr/pollset_set.h"
#include <grpc/support/slice.h> #include <grpc/support/slice.h>
#include <grpc/support/time.h> #include <grpc/support/time.h>
@ -70,14 +71,18 @@ struct grpc_endpoint_vtable {
size_t nslices, grpc_endpoint_write_cb cb, size_t nslices, grpc_endpoint_write_cb cb,
void *user_data); void *user_data);
void (*add_to_pollset)(grpc_endpoint *ep, grpc_pollset *pollset); void (*add_to_pollset)(grpc_endpoint *ep, grpc_pollset *pollset);
void (*add_to_pollset_set)(grpc_endpoint *ep, grpc_pollset_set *pollset);
void (*shutdown)(grpc_endpoint *ep); void (*shutdown)(grpc_endpoint *ep);
void (*destroy)(grpc_endpoint *ep); void (*destroy)(grpc_endpoint *ep);
char *(*get_peer)(grpc_endpoint *ep);
}; };
/* When data is available on the connection, calls the callback with slices. */ /* When data is available on the connection, calls the callback with slices. */
void grpc_endpoint_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, void grpc_endpoint_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb,
void *user_data); void *user_data);
char *grpc_endpoint_get_peer(grpc_endpoint *ep);
/* Write slices out to the socket. /* Write slices out to the socket.
If the connection is ready for more data after the end of the call, it If the connection is ready for more data after the end of the call, it
@ -98,6 +103,7 @@ void grpc_endpoint_destroy(grpc_endpoint *ep);
/* Add an endpoint to a pollset, so that when the pollset is polled, events from /* Add an endpoint to a pollset, so that when the pollset is polled, events from
this endpoint are considered */ this endpoint are considered */
void grpc_endpoint_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset); void grpc_endpoint_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset);
void grpc_endpoint_add_to_pollset_set(grpc_endpoint *ep, grpc_pollset_set *pollset_set);
struct grpc_endpoint { struct grpc_endpoint {
const grpc_endpoint_vtable *vtable; const grpc_endpoint_vtable *vtable;

@ -66,12 +66,12 @@ grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name,
create_sockets(sv); create_sockets(sv);
gpr_asprintf(&final_name, "%s:client", name); gpr_asprintf(&final_name, "%s:client", name);
p.client = p.client = grpc_tcp_create(grpc_fd_create(sv[1], final_name), read_slice_size,
grpc_tcp_create(grpc_fd_create(sv[1], final_name), read_slice_size); "socketpair-server");
gpr_free(final_name); gpr_free(final_name);
gpr_asprintf(&final_name, "%s:server", name); gpr_asprintf(&final_name, "%s:server", name);
p.server = p.server = grpc_tcp_create(grpc_fd_create(sv[0], final_name), read_slice_size,
grpc_tcp_create(grpc_fd_create(sv[0], final_name), read_slice_size); "socketpair-client");
gpr_free(final_name); gpr_free(final_name);
return p; return p;
} }

@ -81,8 +81,10 @@ grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name, size_t read
SOCKET sv[2]; SOCKET sv[2];
grpc_endpoint_pair p; grpc_endpoint_pair p;
create_sockets(sv); create_sockets(sv);
p.client = grpc_tcp_create(grpc_winsocket_create(sv[1], "endpoint:client")); p.client = grpc_tcp_create(grpc_winsocket_create(sv[1], "endpoint:client"),
p.server = grpc_tcp_create(grpc_winsocket_create(sv[0], "endpoint:server")); "endpoint:server");
p.server = grpc_tcp_create(grpc_winsocket_create(sv[0], "endpoint:server"),
"endpoint:client");
return p; return p;
} }

@ -57,9 +57,9 @@ static grpc_iomgr_object g_root_object;
static void background_callback_executor(void *ignored) { static void background_callback_executor(void *ignored) {
gpr_mu_lock(&g_mu); gpr_mu_lock(&g_mu);
while (!g_shutdown) { while (!g_shutdown) {
gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_REALTIME); gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
gpr_timespec short_deadline = gpr_time_add( gpr_timespec short_deadline = gpr_time_add(
gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(100, GPR_TIMESPAN)); gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_millis(100, GPR_TIMESPAN));
if (g_cbs_head) { if (g_cbs_head) {
grpc_iomgr_closure *closure = g_cbs_head; grpc_iomgr_closure *closure = g_cbs_head;
g_cbs_head = closure->next; g_cbs_head = closure->next;
@ -67,7 +67,7 @@ static void background_callback_executor(void *ignored) {
gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_mu);
closure->cb(closure->cb_arg, closure->success); closure->cb(closure->cb_arg, closure->success);
gpr_mu_lock(&g_mu); gpr_mu_lock(&g_mu);
} else if (grpc_alarm_check(&g_mu, gpr_now(GPR_CLOCK_REALTIME), } else if (grpc_alarm_check(&g_mu, gpr_now(GPR_CLOCK_MONOTONIC),
&deadline)) { &deadline)) {
} else { } else {
gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_mu);
@ -88,9 +88,10 @@ void grpc_kick_poller(void) {
void grpc_iomgr_init(void) { void grpc_iomgr_init(void) {
gpr_thd_id id; gpr_thd_id id;
g_shutdown = 0;
gpr_mu_init(&g_mu); gpr_mu_init(&g_mu);
gpr_cv_init(&g_rcv); gpr_cv_init(&g_rcv);
grpc_alarm_list_init(gpr_now(GPR_CLOCK_REALTIME)); grpc_alarm_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";
grpc_iomgr_platform_init(); grpc_iomgr_platform_init();
@ -145,8 +146,7 @@ void grpc_iomgr_shutdown(void) {
} while (g_cbs_head); } while (g_cbs_head);
continue; continue;
} }
if (grpc_alarm_check(&g_mu, gpr_inf_future(GPR_CLOCK_REALTIME), NULL)) { if (grpc_alarm_check(&g_mu, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL)) {
gpr_log(GPR_DEBUG, "got late alarm");
continue; continue;
} }
if (g_root_object.next != &g_root_object) { if (g_root_object.next != &g_root_object) {

@ -136,7 +136,7 @@ static void finish_shutdown(grpc_pollset *pollset) {
int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) { int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) {
/* pollset->mu already held */ /* pollset->mu already held */
gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
if (gpr_time_cmp(now, deadline) > 0) { if (gpr_time_cmp(now, deadline) > 0) {
return 0; return 0;
} }
@ -205,7 +205,7 @@ int grpc_poll_deadline_to_millis_timeout(gpr_timespec deadline,
gpr_timespec now) { gpr_timespec now) {
gpr_timespec timeout; gpr_timespec timeout;
static const int max_spin_polling_us = 10; static const int max_spin_polling_us = 10;
if (gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_REALTIME)) == 0) { if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) {
return -1; return -1;
} }
if (gpr_time_cmp(deadline, gpr_time_add(now, gpr_time_from_micros( if (gpr_time_cmp(deadline, gpr_time_add(now, gpr_time_from_micros(

@ -60,7 +60,7 @@ void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set) {
void grpc_pollset_set_add_pollset(grpc_pollset_set *pollset_set, void grpc_pollset_set_add_pollset(grpc_pollset_set *pollset_set,
grpc_pollset *pollset) { grpc_pollset *pollset) {
size_t i; size_t i, j;
gpr_mu_lock(&pollset_set->mu); gpr_mu_lock(&pollset_set->mu);
if (pollset_set->pollset_count == pollset_set->pollset_capacity) { if (pollset_set->pollset_count == pollset_set->pollset_capacity) {
pollset_set->pollset_capacity = pollset_set->pollset_capacity =
@ -70,9 +70,15 @@ void grpc_pollset_set_add_pollset(grpc_pollset_set *pollset_set,
sizeof(*pollset_set->pollsets)); sizeof(*pollset_set->pollsets));
} }
pollset_set->pollsets[pollset_set->pollset_count++] = pollset; pollset_set->pollsets[pollset_set->pollset_count++] = pollset;
for (i = 0; i < pollset_set->fd_count; i++) { for (i = 0, j = 0; i < pollset_set->fd_count; i++) {
if (grpc_fd_is_orphaned(pollset_set->fds[i])) {
GRPC_FD_UNREF(pollset_set->fds[i], "pollset");
} else {
grpc_pollset_add_fd(pollset, pollset_set->fds[i]); grpc_pollset_add_fd(pollset, pollset_set->fds[i]);
pollset_set->fds[j++] = pollset_set->fds[i];
}
} }
pollset_set->fd_count = j;
gpr_mu_unlock(&pollset_set->mu); gpr_mu_unlock(&pollset_set->mu);
} }

@ -70,7 +70,7 @@ void grpc_pollset_destroy(grpc_pollset *pollset) {
int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) { int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) {
gpr_timespec now; gpr_timespec now;
now = gpr_now(GPR_CLOCK_REALTIME); now = gpr_now(GPR_CLOCK_MONOTONIC);
if (gpr_time_cmp(now, deadline) > 0) { if (gpr_time_cmp(now, deadline) > 0) {
return 0 /* GPR_FALSE */; return 0 /* GPR_FALSE */;
} }

@ -36,12 +36,18 @@
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include "src/core/support/string.h" #ifdef GPR_POSIX_SOCKET
#include <sys/un.h>
#endif
#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>
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/support/string.h"
static const gpr_uint8 kV4MappedPrefix[] = {0, 0, 0, 0, 0, 0, static const gpr_uint8 kV4MappedPrefix[] = {0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0xff, 0xff}; 0, 0, 0, 0, 0xff, 0xff};
@ -161,6 +167,31 @@ int grpc_sockaddr_to_string(char **out, const struct sockaddr *addr,
return ret; return ret;
} }
char *grpc_sockaddr_to_uri(const struct sockaddr *addr) {
char *temp;
char *result;
switch (addr->sa_family) {
case AF_INET:
grpc_sockaddr_to_string(&temp, addr, 0);
gpr_asprintf(&result, "ipv4:%s", temp);
gpr_free(temp);
return result;
case AF_INET6:
grpc_sockaddr_to_string(&temp, addr, 0);
gpr_asprintf(&result, "ipv6:%s", temp);
gpr_free(temp);
return result;
#ifdef GPR_POSIX_SOCKET
case AF_UNIX:
gpr_asprintf(&result, "unix:%s", ((struct sockaddr_un *)addr)->sun_path);
return result;
#endif
}
return NULL;
}
int grpc_sockaddr_get_port(const struct sockaddr *addr) { int grpc_sockaddr_get_port(const struct sockaddr *addr) {
switch (addr->sa_family) { switch (addr->sa_family) {
case AF_INET: case AF_INET:

@ -84,4 +84,6 @@ int grpc_sockaddr_set_port(const struct sockaddr *addr, int port);
int grpc_sockaddr_to_string(char **out, const struct sockaddr *addr, int grpc_sockaddr_to_string(char **out, const struct sockaddr *addr,
int normalize); int normalize);
char *grpc_sockaddr_to_uri(const struct sockaddr *addr);
#endif /* GRPC_INTERNAL_CORE_IOMGR_SOCKADDR_UTILS_H */ #endif /* GRPC_INTERNAL_CORE_IOMGR_SOCKADDR_UTILS_H */

@ -64,6 +64,7 @@ typedef struct {
int refs; int refs;
grpc_iomgr_closure write_closure; grpc_iomgr_closure write_closure;
grpc_pollset_set *interested_parties; grpc_pollset_set *interested_parties;
char *addr_str;
} async_connect; } async_connect;
static int prepare_socket(const struct sockaddr *addr, int fd) { static int prepare_socket(const struct sockaddr *addr, int fd) {
@ -88,17 +89,18 @@ error:
return 0; return 0;
} }
static void on_alarm(void *acp, int success) { static void tc_on_alarm(void *acp, int success) {
int done; int done;
async_connect *ac = acp; async_connect *ac = acp;
gpr_mu_lock(&ac->mu); gpr_mu_lock(&ac->mu);
if (ac->fd != NULL && success) { if (ac->fd != NULL) {
grpc_fd_shutdown(ac->fd); grpc_fd_shutdown(ac->fd);
} }
done = (--ac->refs == 0); done = (--ac->refs == 0);
gpr_mu_unlock(&ac->mu); gpr_mu_unlock(&ac->mu);
if (done) { if (done) {
gpr_mu_destroy(&ac->mu); gpr_mu_destroy(&ac->mu);
gpr_free(ac->addr_str);
gpr_free(ac); gpr_free(ac);
} }
} }
@ -108,17 +110,25 @@ static void on_writable(void *acp, int success) {
int so_error = 0; int so_error = 0;
socklen_t so_error_size; socklen_t so_error_size;
int err; int err;
int fd = ac->fd->fd;
int done; int done;
grpc_endpoint *ep = NULL; grpc_endpoint *ep = NULL;
void (*cb)(void *arg, grpc_endpoint *tcp) = ac->cb; void (*cb)(void *arg, grpc_endpoint *tcp) = ac->cb;
void *cb_arg = ac->cb_arg; void *cb_arg = ac->cb_arg;
grpc_fd *fd;
gpr_mu_lock(&ac->mu);
GPR_ASSERT(ac->fd);
fd = ac->fd;
ac->fd = NULL;
gpr_mu_unlock(&ac->mu);
grpc_alarm_cancel(&ac->alarm);
gpr_mu_lock(&ac->mu); gpr_mu_lock(&ac->mu);
if (success) { if (success) {
do { do {
so_error_size = sizeof(so_error); so_error_size = sizeof(so_error);
err = getsockopt(fd, SOL_SOCKET, SO_ERROR, &so_error, &so_error_size); err = getsockopt(fd->fd, SOL_SOCKET, SO_ERROR, &so_error, &so_error_size);
} while (err < 0 && errno == EINTR); } while (err < 0 && errno == EINTR);
if (err < 0) { if (err < 0) {
gpr_log(GPR_ERROR, "getsockopt(ERROR): %s", strerror(errno)); gpr_log(GPR_ERROR, "getsockopt(ERROR): %s", strerror(errno));
@ -141,7 +151,7 @@ static void on_writable(void *acp, int success) {
don't do that! */ don't do that! */
gpr_log(GPR_ERROR, "kernel out of buffers"); gpr_log(GPR_ERROR, "kernel out of buffers");
gpr_mu_unlock(&ac->mu); gpr_mu_unlock(&ac->mu);
grpc_fd_notify_on_write(ac->fd, &ac->write_closure); grpc_fd_notify_on_write(fd, &ac->write_closure);
return; return;
} else { } else {
switch (so_error) { switch (so_error) {
@ -155,8 +165,9 @@ static void on_writable(void *acp, int success) {
goto finish; goto finish;
} }
} else { } else {
grpc_pollset_set_del_fd(ac->interested_parties, ac->fd); grpc_pollset_set_del_fd(ac->interested_parties, fd);
ep = grpc_tcp_create(ac->fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE); ep = grpc_tcp_create(fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, ac->addr_str);
fd = NULL;
goto finish; goto finish;
} }
} else { } else {
@ -167,19 +178,17 @@ static void on_writable(void *acp, int success) {
abort(); abort();
finish: finish:
if (ep == NULL) { if (fd != NULL) {
grpc_pollset_set_del_fd(ac->interested_parties, ac->fd); grpc_pollset_set_del_fd(ac->interested_parties, fd);
grpc_fd_orphan(ac->fd, NULL, "tcp_client_orphan"); grpc_fd_orphan(fd, NULL, "tcp_client_orphan");
} else { fd = NULL;
ac->fd = NULL;
} }
done = (--ac->refs == 0); done = (--ac->refs == 0);
gpr_mu_unlock(&ac->mu); gpr_mu_unlock(&ac->mu);
if (done) { if (done) {
gpr_mu_destroy(&ac->mu); gpr_mu_destroy(&ac->mu);
gpr_free(ac->addr_str);
gpr_free(ac); gpr_free(ac);
} else {
grpc_alarm_cancel(&ac->alarm);
} }
cb(cb_arg, ep); cb(cb_arg, ep);
} }
@ -223,13 +232,13 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
err = connect(fd, addr, addr_len); err = connect(fd, addr, addr_len);
} while (err < 0 && errno == EINTR); } while (err < 0 && errno == EINTR);
grpc_sockaddr_to_string(&addr_str, addr, 1); addr_str = grpc_sockaddr_to_uri(addr);
gpr_asprintf(&name, "tcp-client:%s", addr_str); gpr_asprintf(&name, "tcp-client:%s", addr_str);
fdobj = grpc_fd_create(fd, name); fdobj = grpc_fd_create(fd, name);
if (err >= 0) { if (err >= 0) {
cb(arg, grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE)); cb(arg, grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str));
goto done; goto done;
} }
@ -247,14 +256,16 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
ac->cb_arg = arg; ac->cb_arg = arg;
ac->fd = fdobj; ac->fd = fdobj;
ac->interested_parties = interested_parties; ac->interested_parties = interested_parties;
ac->addr_str = addr_str;
addr_str = NULL;
gpr_mu_init(&ac->mu); gpr_mu_init(&ac->mu);
ac->refs = 2; ac->refs = 2;
ac->write_closure.cb = on_writable; ac->write_closure.cb = on_writable;
ac->write_closure.cb_arg = ac; ac->write_closure.cb_arg = ac;
gpr_mu_lock(&ac->mu); gpr_mu_lock(&ac->mu);
grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, grpc_alarm_init(&ac->alarm, gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
gpr_now(GPR_CLOCK_REALTIME)); tc_on_alarm, ac, gpr_now(GPR_CLOCK_MONOTONIC));
grpc_fd_notify_on_write(ac->fd, &ac->write_closure); grpc_fd_notify_on_write(ac->fd, &ac->write_closure);
gpr_mu_unlock(&ac->mu); gpr_mu_unlock(&ac->mu);

@ -58,6 +58,7 @@ typedef struct {
grpc_winsocket *socket; grpc_winsocket *socket;
gpr_timespec deadline; gpr_timespec deadline;
grpc_alarm alarm; grpc_alarm alarm;
char *addr_name;
int refs; int refs;
int aborted; int aborted;
} async_connect; } async_connect;
@ -67,6 +68,7 @@ static void async_connect_cleanup(async_connect *ac) {
gpr_mu_unlock(&ac->mu); gpr_mu_unlock(&ac->mu);
if (done) { if (done) {
gpr_mu_destroy(&ac->mu); gpr_mu_destroy(&ac->mu);
gpr_free(ac->addr_name);
gpr_free(ac); gpr_free(ac);
} }
} }
@ -107,7 +109,7 @@ static void on_connect(void *acp, int from_iocp) {
gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message); gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message);
gpr_free(utf8_message); gpr_free(utf8_message);
} else if (!aborted) { } else if (!aborted) {
ep = grpc_tcp_create(ac->socket); ep = grpc_tcp_create(ac->socket, ac->addr_name);
} }
} else { } else {
gpr_log(GPR_ERROR, "on_connect is shutting down"); gpr_log(GPR_ERROR, "on_connect is shutting down");
@ -213,10 +215,11 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *tcp),
ac->socket = socket; ac->socket = socket;
gpr_mu_init(&ac->mu); gpr_mu_init(&ac->mu);
ac->refs = 2; ac->refs = 2;
ac->addr_name = grpc_sockaddr_to_uri(addr);
ac->aborted = 0; ac->aborted = 0;
grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac,
gpr_now(GPR_CLOCK_REALTIME)); gpr_now(GPR_CLOCK_MONOTONIC));
socket->write_info.outstanding = 1; socket->write_info.outstanding = 1;
grpc_socket_notify_on_write(socket, on_connect, ac); grpc_socket_notify_on_write(socket, on_connect, ac);
return; return;

@ -44,15 +44,17 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#include "src/core/support/string.h"
#include "src/core/debug/trace.h"
#include "src/core/profiling/timers.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/slice.h> #include <grpc/support/slice.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h> #include <grpc/support/sync.h>
#include <grpc/support/time.h> #include <grpc/support/time.h>
#include "src/core/support/string.h"
#include "src/core/debug/trace.h"
#include "src/core/profiling/timers.h"
#ifdef GPR_HAVE_MSG_NOSIGNAL #ifdef GPR_HAVE_MSG_NOSIGNAL
#define SENDMSG_FLAGS MSG_NOSIGNAL #define SENDMSG_FLAGS MSG_NOSIGNAL
#else #else
@ -282,6 +284,8 @@ typedef struct {
grpc_iomgr_closure write_closure; grpc_iomgr_closure write_closure;
grpc_iomgr_closure handle_read_closure; grpc_iomgr_closure handle_read_closure;
char *peer_string;
} grpc_tcp; } grpc_tcp;
static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success); static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success);
@ -296,6 +300,7 @@ static void grpc_tcp_unref(grpc_tcp *tcp) {
int refcount_zero = gpr_unref(&tcp->refcount); int refcount_zero = gpr_unref(&tcp->refcount);
if (refcount_zero) { if (refcount_zero) {
grpc_fd_orphan(tcp->em_fd, NULL, "tcp_unref_orphan"); grpc_fd_orphan(tcp->em_fd, NULL, "tcp_unref_orphan");
gpr_free(tcp->peer_string);
gpr_free(tcp); gpr_free(tcp);
} }
} }
@ -314,7 +319,7 @@ static void call_read_cb(grpc_tcp *tcp, gpr_slice *slices, size_t nslices,
gpr_log(GPR_DEBUG, "read: status=%d", status); gpr_log(GPR_DEBUG, "read: status=%d", status);
for (i = 0; i < nslices; i++) { for (i = 0; i < nslices; i++) {
char *dump = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); char *dump = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_DEBUG, "READ: %s", dump); gpr_log(GPR_DEBUG, "READ %p: %s", tcp, dump);
gpr_free(dump); gpr_free(dump);
} }
} }
@ -443,7 +448,7 @@ static void grpc_tcp_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb,
grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure); grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure);
} else { } else {
tcp->handle_read_closure.cb_arg = tcp; tcp->handle_read_closure.cb_arg = tcp;
grpc_iomgr_add_callback(&tcp->handle_read_closure); grpc_iomgr_add_delayed_callback(&tcp->handle_read_closure, 1);
} }
} }
@ -567,13 +572,27 @@ static void grpc_tcp_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) {
grpc_pollset_add_fd(pollset, tcp->em_fd); grpc_pollset_add_fd(pollset, tcp->em_fd);
} }
static void grpc_tcp_add_to_pollset_set(grpc_endpoint *ep, grpc_pollset_set *pollset_set) {
grpc_tcp *tcp = (grpc_tcp *)ep;
grpc_pollset_set_add_fd(pollset_set, tcp->em_fd);
}
static char *grpc_tcp_get_peer(grpc_endpoint *ep) {
grpc_tcp *tcp = (grpc_tcp *)ep;
return gpr_strdup(tcp->peer_string);
}
static const grpc_endpoint_vtable vtable = { static const grpc_endpoint_vtable vtable = {
grpc_tcp_notify_on_read, grpc_tcp_write, grpc_tcp_add_to_pollset, grpc_tcp_notify_on_read, grpc_tcp_write,
grpc_tcp_shutdown, grpc_tcp_destroy}; grpc_tcp_add_to_pollset, grpc_tcp_add_to_pollset_set,
grpc_tcp_shutdown, grpc_tcp_destroy,
grpc_tcp_get_peer};
grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size) { grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size,
const char *peer_string) {
grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp));
tcp->base.vtable = &vtable; tcp->base.vtable = &vtable;
tcp->peer_string = gpr_strdup(peer_string);
tcp->fd = em_fd->fd; tcp->fd = em_fd->fd;
tcp->read_cb = NULL; tcp->read_cb = NULL;
tcp->write_cb = NULL; tcp->write_cb = NULL;

@ -53,6 +53,7 @@ extern int grpc_tcp_trace;
/* Create a tcp endpoint given a file desciptor and a read slice size. /* Create a tcp endpoint given a file desciptor and a read slice size.
Takes ownership of fd. */ Takes ownership of fd. */
grpc_endpoint *grpc_tcp_create(grpc_fd *fd, size_t read_slice_size); grpc_endpoint *grpc_tcp_create(grpc_fd *fd, size_t read_slice_size,
const char *peer_string);
#endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_POSIX_H */ #endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_POSIX_H */

@ -332,7 +332,7 @@ static void on_read(void *arg, int success) {
grpc_set_socket_no_sigpipe_if_possible(fd); grpc_set_socket_no_sigpipe_if_possible(fd);
grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1); addr_str = grpc_sockaddr_to_uri((struct sockaddr *)&addr);
gpr_asprintf(&name, "tcp-server-connection:%s", addr_str); gpr_asprintf(&name, "tcp-server-connection:%s", addr_str);
fdobj = grpc_fd_create(fd, name); fdobj = grpc_fd_create(fd, name);
@ -342,8 +342,9 @@ static void on_read(void *arg, int success) {
for (i = 0; i < sp->server->pollset_count; i++) { for (i = 0; i < sp->server->pollset_count; i++) {
grpc_pollset_add_fd(sp->server->pollsets[i], fdobj); grpc_pollset_add_fd(sp->server->pollsets[i], fdobj);
} }
sp->server->cb(sp->server->cb_arg, sp->server->cb(
grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE)); sp->server->cb_arg,
grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str));
gpr_free(name); gpr_free(name);
gpr_free(addr_str); gpr_free(addr_str);

@ -79,6 +79,8 @@ struct grpc_tcp_server {
/* active port count: how many ports are actually still listening */ /* active port count: how many ports are actually still listening */
int active_ports; int active_ports;
/* number of iomgr callbacks that have been explicitly scheduled during shutdown */
int iomgr_callbacks_pending;
/* all listening ports */ /* all listening ports */
server_port *ports; server_port *ports;
@ -93,6 +95,7 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
gpr_mu_init(&s->mu); gpr_mu_init(&s->mu);
gpr_cv_init(&s->cv); gpr_cv_init(&s->cv);
s->active_ports = 0; s->active_ports = 0;
s->iomgr_callbacks_pending = 0;
s->cb = NULL; s->cb = NULL;
s->cb_arg = NULL; s->cb_arg = NULL;
s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP); s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP);
@ -112,10 +115,10 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s,
for (i = 0; i < s->nports; i++) { for (i = 0; i < s->nports; i++) {
server_port *sp = &s->ports[i]; server_port *sp = &s->ports[i];
sp->shutting_down = 1; sp->shutting_down = 1;
grpc_winsocket_shutdown(sp->socket); s->iomgr_callbacks_pending += grpc_winsocket_shutdown(sp->socket);
} }
/* This happens asynchronously. Wait while that happens. */ /* This happens asynchronously. Wait while that happens. */
while (s->active_ports) { while (s->active_ports || s->iomgr_callbacks_pending) {
gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future(GPR_CLOCK_REALTIME)); gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future(GPR_CLOCK_REALTIME));
} }
gpr_mu_unlock(&s->mu); gpr_mu_unlock(&s->mu);
@ -243,14 +246,27 @@ static void on_accept(void *arg, int from_iocp) {
SOCKET sock = sp->new_socket; SOCKET sock = sp->new_socket;
grpc_winsocket_callback_info *info = &sp->socket->read_info; grpc_winsocket_callback_info *info = &sp->socket->read_info;
grpc_endpoint *ep = NULL; grpc_endpoint *ep = NULL;
struct sockaddr_storage peer_name;
char *peer_name_string;
char *fd_name;
int peer_name_len = sizeof(peer_name);
DWORD transfered_bytes; DWORD transfered_bytes;
DWORD flags; DWORD flags;
BOOL wsa_success; BOOL wsa_success;
int err;
/* The general mechanism for shutting down is to queue abortion calls. While /* The general mechanism for shutting down is to queue abortion calls. While
this is necessary in the read/write case, it's useless for the accept this is necessary in the read/write case, it's useless for the accept
case. Let's do nothing. */ case. We only need to adjust the pending callback count */
if (!from_iocp) return; if (!from_iocp) {
gpr_mu_lock(&sp->server->mu);
GPR_ASSERT(sp->server->iomgr_callbacks_pending > 0);
if (0 == --sp->server->iomgr_callbacks_pending) {
gpr_cv_broadcast(&sp->server->cv);
}
gpr_mu_unlock(&sp->server->mu);
return;
}
/* The IOCP notified us of a completed operation. Let's grab the results, /* The IOCP notified us of a completed operation. Let's grab the results,
and act accordingly. */ and act accordingly. */
@ -259,11 +275,12 @@ static void on_accept(void *arg, int from_iocp) {
&transfered_bytes, FALSE, &flags); &transfered_bytes, FALSE, &flags);
if (!wsa_success) { if (!wsa_success) {
if (sp->shutting_down) { if (sp->shutting_down) {
/* During the shutdown case, we ARE expecting an error. So that's swell, /* During the shutdown case, we ARE expecting an error. So that's well,
and we can wake up the shutdown thread. */ and we can wake up the shutdown thread. */
sp->shutting_down = 0; sp->shutting_down = 0;
sp->socket->read_info.outstanding = 0; sp->socket->read_info.outstanding = 0;
gpr_mu_lock(&sp->server->mu); gpr_mu_lock(&sp->server->mu);
GPR_ASSERT(sp->server->active_ports > 0);
if (0 == --sp->server->active_ports) { if (0 == --sp->server->active_ports) {
gpr_cv_broadcast(&sp->server->cv); gpr_cv_broadcast(&sp->server->cv);
} }
@ -277,8 +294,28 @@ static void on_accept(void *arg, int from_iocp) {
} }
} else { } else {
if (!sp->shutting_down) { if (!sp->shutting_down) {
/* TODO(ctiller): add sockaddr address to label */ peer_name_string = NULL;
ep = grpc_tcp_create(grpc_winsocket_create(sock, "server")); err = setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
(char *)&sp->socket->socket,
sizeof(sp->socket->socket));
if (err) {
char *utf8_message = gpr_format_message(WSAGetLastError());
gpr_log(GPR_ERROR, "setsockopt error: %s", utf8_message);
gpr_free(utf8_message);
}
err = getpeername(sock, (struct sockaddr*)&peer_name, &peer_name_len);
if (!err) {
peer_name_string = grpc_sockaddr_to_uri((struct sockaddr*)&peer_name);
} else {
char *utf8_message = gpr_format_message(WSAGetLastError());
gpr_log(GPR_ERROR, "getpeername error: %s", utf8_message);
gpr_free(utf8_message);
}
gpr_asprintf(&fd_name, "tcp_server:%s", peer_name_string);
ep = grpc_tcp_create(grpc_winsocket_create(sock, fd_name),
peer_name_string);
gpr_free(fd_name);
gpr_free(peer_name_string);
} }
} }

@ -96,6 +96,8 @@ typedef struct grpc_tcp {
to protect ourselves when requesting a shutdown. */ to protect ourselves when requesting a shutdown. */
gpr_mu mu; gpr_mu mu;
int shutting_down; int shutting_down;
char *peer_string;
} grpc_tcp; } grpc_tcp;
static void tcp_ref(grpc_tcp *tcp) { static void tcp_ref(grpc_tcp *tcp) {
@ -107,6 +109,7 @@ static void tcp_unref(grpc_tcp *tcp) {
gpr_slice_buffer_destroy(&tcp->write_slices); gpr_slice_buffer_destroy(&tcp->write_slices);
grpc_winsocket_orphan(tcp->socket); grpc_winsocket_orphan(tcp->socket);
gpr_mu_destroy(&tcp->mu); gpr_mu_destroy(&tcp->mu);
gpr_free(tcp->peer_string);
gpr_free(tcp); gpr_free(tcp);
} }
} }
@ -365,7 +368,14 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep,
return GRPC_ENDPOINT_WRITE_PENDING; return GRPC_ENDPOINT_WRITE_PENDING;
} }
static void win_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) { static void win_add_to_pollset(grpc_endpoint *ep, grpc_pollset *ps) {
(void) ps;
grpc_tcp *tcp = (grpc_tcp *) ep;
grpc_iocp_add_socket(tcp->socket);
}
static void win_add_to_pollset_set(grpc_endpoint *ep, grpc_pollset_set *pss) {
(void) pss;
grpc_tcp *tcp = (grpc_tcp *) ep; grpc_tcp *tcp = (grpc_tcp *) ep;
grpc_iocp_add_socket(tcp->socket); grpc_iocp_add_socket(tcp->socket);
} }
@ -393,11 +403,17 @@ static void win_destroy(grpc_endpoint *ep) {
tcp_unref(tcp); tcp_unref(tcp);
} }
static grpc_endpoint_vtable vtable = { static char *win_get_peer(grpc_endpoint *ep) {
win_notify_on_read, win_write, win_add_to_pollset, win_shutdown, win_destroy grpc_tcp *tcp = (grpc_tcp *)ep;
}; return gpr_strdup(tcp->peer_string);
}
static grpc_endpoint_vtable vtable = {win_notify_on_read, win_write,
win_add_to_pollset, win_add_to_pollset_set,
win_shutdown, win_destroy,
win_get_peer};
grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket) { grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string) {
grpc_tcp *tcp = (grpc_tcp *) gpr_malloc(sizeof(grpc_tcp)); grpc_tcp *tcp = (grpc_tcp *) gpr_malloc(sizeof(grpc_tcp));
memset(tcp, 0, sizeof(grpc_tcp)); memset(tcp, 0, sizeof(grpc_tcp));
tcp->base.vtable = &vtable; tcp->base.vtable = &vtable;
@ -405,6 +421,7 @@ grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket) {
gpr_mu_init(&tcp->mu); gpr_mu_init(&tcp->mu);
gpr_slice_buffer_init(&tcp->write_slices); gpr_slice_buffer_init(&tcp->write_slices);
gpr_ref_init(&tcp->refcount, 1); gpr_ref_init(&tcp->refcount, 1);
tcp->peer_string = gpr_strdup(peer_string);
return &tcp->base; return &tcp->base;
} }

@ -50,7 +50,7 @@
/* Create a tcp endpoint given a winsock handle. /* Create a tcp endpoint given a winsock handle.
* Takes ownership of the handle. * Takes ownership of the handle.
*/ */
grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket); grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string);
int grpc_tcp_prepare_socket(SOCKET sock); int grpc_tcp_prepare_socket(SOCKET sock);

@ -80,7 +80,7 @@ static void bubble_up_error(grpc_call_element *elem, const char *error_msg) {
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
grpc_transport_stream_op_add_cancellation( grpc_transport_stream_op_add_cancellation(
&calld->op, GRPC_STATUS_UNAUTHENTICATED, &calld->op, GRPC_STATUS_UNAUTHENTICATED,
grpc_mdstr_from_string(chand->md_ctx, error_msg)); grpc_mdstr_from_string(chand->md_ctx, error_msg, 0));
grpc_call_next_op(elem, &calld->op); grpc_call_next_op(elem, &calld->op);
} }
@ -316,10 +316,10 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
(grpc_channel_security_connector *)GRPC_SECURITY_CONNECTOR_REF( (grpc_channel_security_connector *)GRPC_SECURITY_CONNECTOR_REF(
sc, "client_auth_filter"); sc, "client_auth_filter");
chand->md_ctx = metadata_context; chand->md_ctx = metadata_context;
chand->authority_string = grpc_mdstr_from_string(chand->md_ctx, ":authority"); chand->authority_string = grpc_mdstr_from_string(chand->md_ctx, ":authority", 0);
chand->path_string = grpc_mdstr_from_string(chand->md_ctx, ":path"); chand->path_string = grpc_mdstr_from_string(chand->md_ctx, ":path", 0);
chand->error_msg_key = grpc_mdstr_from_string(chand->md_ctx, "grpc-message"); chand->error_msg_key = grpc_mdstr_from_string(chand->md_ctx, "grpc-message", 0);
chand->status_key = grpc_mdstr_from_string(chand->md_ctx, "grpc-status"); chand->status_key = grpc_mdstr_from_string(chand->md_ctx, "grpc-status", 0);
} }
/* Destructor for channel data */ /* Destructor for channel data */
@ -344,6 +344,8 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
} }
const grpc_channel_filter grpc_client_auth_filter = { const grpc_channel_filter grpc_client_auth_filter = {
auth_start_transport_op, grpc_channel_next_op, sizeof(call_data), auth_start_transport_op, grpc_channel_next_op,
init_call_elem, destroy_call_elem, sizeof(channel_data), sizeof(call_data), init_call_elem,
init_channel_elem, destroy_channel_elem, "client-auth"}; destroy_call_elem, sizeof(channel_data),
init_channel_elem, destroy_channel_elem,
grpc_call_next_get_peer, "client-auth"};

@ -259,8 +259,10 @@ static void ssl_build_config(const char *pem_root_certs,
static void ssl_build_server_config( static void ssl_build_server_config(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
size_t num_key_cert_pairs, grpc_ssl_server_config *config) { size_t num_key_cert_pairs, int force_client_auth,
grpc_ssl_server_config *config) {
size_t i; size_t i;
config->force_client_auth = force_client_auth;
if (pem_root_certs != NULL) { if (pem_root_certs != NULL) {
ssl_copy_key_material(pem_root_certs, &config->pem_root_certs, ssl_copy_key_material(pem_root_certs, &config->pem_root_certs,
&config->pem_root_certs_size); &config->pem_root_certs_size);
@ -302,20 +304,20 @@ grpc_credentials *grpc_ssl_credentials_create(
grpc_server_credentials *grpc_ssl_server_credentials_create( grpc_server_credentials *grpc_ssl_server_credentials_create(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
size_t num_key_cert_pairs) { size_t num_key_cert_pairs, int force_client_auth) {
grpc_ssl_server_credentials *c = grpc_ssl_server_credentials *c =
gpr_malloc(sizeof(grpc_ssl_server_credentials)); gpr_malloc(sizeof(grpc_ssl_server_credentials));
memset(c, 0, sizeof(grpc_ssl_server_credentials)); memset(c, 0, sizeof(grpc_ssl_server_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_SSL; c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
c->base.vtable = &ssl_server_vtable; c->base.vtable = &ssl_server_vtable;
ssl_build_server_config(pem_root_certs, pem_key_cert_pairs, ssl_build_server_config(pem_root_certs, pem_key_cert_pairs,
num_key_cert_pairs, &c->config); num_key_cert_pairs, force_client_auth, &c->config);
return &c->base; return &c->base;
} }
/* -- Jwt credentials -- */ /* -- Jwt credentials -- */
static void jwt_reset_cache(grpc_jwt_credentials *c) { static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) {
if (c->cached.jwt_md != NULL) { if (c->cached.jwt_md != NULL) {
grpc_credentials_md_store_unref(c->cached.jwt_md); grpc_credentials_md_store_unref(c->cached.jwt_md);
c->cached.jwt_md = NULL; c->cached.jwt_md = NULL;
@ -328,7 +330,8 @@ static void jwt_reset_cache(grpc_jwt_credentials *c) {
} }
static void jwt_destroy(grpc_credentials *creds) { static void jwt_destroy(grpc_credentials *creds) {
grpc_jwt_credentials *c = (grpc_jwt_credentials *)creds; grpc_service_account_jwt_access_credentials *c =
(grpc_service_account_jwt_access_credentials *)creds;
grpc_auth_json_key_destruct(&c->key); grpc_auth_json_key_destruct(&c->key);
jwt_reset_cache(c); jwt_reset_cache(c);
gpr_mu_destroy(&c->cache_mu); gpr_mu_destroy(&c->cache_mu);
@ -346,7 +349,8 @@ static void jwt_get_request_metadata(grpc_credentials *creds,
const char *service_url, const char *service_url,
grpc_credentials_metadata_cb cb, grpc_credentials_metadata_cb cb,
void *user_data) { void *user_data) {
grpc_jwt_credentials *c = (grpc_jwt_credentials *)creds; grpc_service_account_jwt_access_credentials *c =
(grpc_service_account_jwt_access_credentials *)creds;
gpr_timespec refresh_threshold = gpr_time_from_seconds( gpr_timespec refresh_threshold = gpr_time_from_seconds(
GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN); GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
@ -399,15 +403,16 @@ static grpc_credentials_vtable jwt_vtable = {
jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only, jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only,
jwt_get_request_metadata, NULL}; jwt_get_request_metadata, NULL};
grpc_credentials *grpc_jwt_credentials_create_from_auth_json_key( grpc_credentials *
grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
grpc_auth_json_key key, gpr_timespec token_lifetime) { grpc_auth_json_key key, gpr_timespec token_lifetime) {
grpc_jwt_credentials *c; grpc_service_account_jwt_access_credentials *c;
if (!grpc_auth_json_key_is_valid(&key)) { if (!grpc_auth_json_key_is_valid(&key)) {
gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation"); gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation");
return NULL; return NULL;
} }
c = gpr_malloc(sizeof(grpc_jwt_credentials)); c = gpr_malloc(sizeof(grpc_service_account_jwt_access_credentials));
memset(c, 0, sizeof(grpc_jwt_credentials)); memset(c, 0, sizeof(grpc_service_account_jwt_access_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_JWT; c->base.type = GRPC_CREDENTIALS_TYPE_JWT;
gpr_ref_init(&c->base.refcount, 1); gpr_ref_init(&c->base.refcount, 1);
c->base.vtable = &jwt_vtable; c->base.vtable = &jwt_vtable;
@ -418,9 +423,9 @@ grpc_credentials *grpc_jwt_credentials_create_from_auth_json_key(
return &c->base; return &c->base;
} }
grpc_credentials *grpc_jwt_credentials_create(const char *json_key, grpc_credentials *grpc_service_account_jwt_access_credentials_create(
gpr_timespec token_lifetime) { const char *json_key, gpr_timespec token_lifetime) {
return grpc_jwt_credentials_create_from_auth_json_key( return grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
grpc_auth_json_key_create_from_string(json_key), token_lifetime); grpc_auth_json_key_create_from_string(json_key), token_lifetime);
} }

@ -52,6 +52,8 @@ typedef enum {
GRPC_CREDENTIALS_ERROR GRPC_CREDENTIALS_ERROR
} grpc_credentials_status; } grpc_credentials_status;
#define GRPC_FAKE_TRANSPORT_SECURITY_TYPE "fake"
#define GRPC_CREDENTIALS_TYPE_SSL "Ssl" #define GRPC_CREDENTIALS_TYPE_SSL "Ssl"
#define GRPC_CREDENTIALS_TYPE_OAUTH2 "Oauth2" #define GRPC_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
#define GRPC_CREDENTIALS_TYPE_JWT "Jwt" #define GRPC_CREDENTIALS_TYPE_JWT "Jwt"
@ -112,6 +114,12 @@ void grpc_credentials_md_store_unref(grpc_credentials_md_store *store);
/* --- grpc_credentials. --- */ /* --- grpc_credentials. --- */
/* Creates a fake transport security credentials object for testing. */
grpc_credentials *grpc_fake_transport_security_credentials_create(void);
/* Creates a fake server transport security credentials object for testing. */
grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
void);
/* It is the caller's responsibility to gpr_free the result if not NULL. */ /* It is the caller's responsibility to gpr_free the result if not NULL. */
char *grpc_get_well_known_google_credentials_file_path(void); char *grpc_get_well_known_google_credentials_file_path(void);
@ -188,7 +196,8 @@ grpc_credentials *grpc_fake_oauth2_credentials_create(
/* Private constructor for jwt credentials from an already parsed json key. /* Private constructor for jwt credentials from an already parsed json key.
Takes ownership of the key. */ Takes ownership of the key. */
grpc_credentials *grpc_jwt_credentials_create_from_auth_json_key( grpc_credentials *
grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
grpc_auth_json_key key, gpr_timespec token_lifetime); grpc_auth_json_key key, gpr_timespec token_lifetime);
/* Private constructor for refresh token credentials from an already parsed /* Private constructor for refresh token credentials from an already parsed
@ -240,7 +249,7 @@ typedef struct {
grpc_auth_json_key key; grpc_auth_json_key key;
gpr_timespec jwt_lifetime; gpr_timespec jwt_lifetime;
} grpc_jwt_credentials; } grpc_service_account_jwt_access_credentials;
/* -- Oauth2TokenFetcher credentials -- /* -- Oauth2TokenFetcher credentials --

@ -140,7 +140,8 @@ static grpc_credentials *create_default_creds_from_path(char *creds_path) {
/* First, try an auth json key. */ /* First, try an auth json key. */
key = grpc_auth_json_key_create_from_json(json); key = grpc_auth_json_key_create_from_json(json);
if (grpc_auth_json_key_is_valid(&key)) { if (grpc_auth_json_key_is_valid(&key)) {
result = grpc_jwt_credentials_create_from_auth_json_key( result =
grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
key, grpc_max_auth_token_lifetime); key, grpc_max_auth_token_lifetime);
goto end; goto end;
} }

@ -331,9 +331,22 @@ static void endpoint_add_to_pollset(grpc_endpoint *secure_ep,
grpc_endpoint_add_to_pollset(ep->wrapped_ep, pollset); grpc_endpoint_add_to_pollset(ep->wrapped_ep, pollset);
} }
static void endpoint_add_to_pollset_set(grpc_endpoint *secure_ep,
grpc_pollset_set *pollset_set) {
secure_endpoint *ep = (secure_endpoint *)secure_ep;
grpc_endpoint_add_to_pollset_set(ep->wrapped_ep, pollset_set);
}
static char *endpoint_get_peer(grpc_endpoint *secure_ep) {
secure_endpoint *ep = (secure_endpoint *)secure_ep;
return grpc_endpoint_get_peer(ep->wrapped_ep);
}
static const grpc_endpoint_vtable vtable = { static const grpc_endpoint_vtable vtable = {
endpoint_notify_on_read, endpoint_write, endpoint_add_to_pollset, endpoint_notify_on_read, endpoint_write,
endpoint_shutdown, endpoint_unref}; endpoint_add_to_pollset, endpoint_add_to_pollset_set,
endpoint_shutdown, endpoint_unref,
endpoint_get_peer};
grpc_endpoint *grpc_secure_endpoint_create( grpc_endpoint *grpc_secure_endpoint_create(
struct tsi_frame_protector *protector, grpc_endpoint *transport, struct tsi_frame_protector *protector, grpc_endpoint *transport,

@ -653,9 +653,10 @@ grpc_security_status grpc_ssl_server_security_connector_create(
config->pem_private_keys_sizes, config->pem_private_keys_sizes,
(const unsigned char **)config->pem_cert_chains, (const unsigned char **)config->pem_cert_chains,
config->pem_cert_chains_sizes, config->num_key_cert_pairs, config->pem_cert_chains_sizes, config->num_key_cert_pairs,
config->pem_root_certs, config->pem_root_certs_size, ssl_cipher_suites(), config->pem_root_certs, config->pem_root_certs_size,
alpn_protocol_strings, alpn_protocol_string_lengths, config->force_client_auth, ssl_cipher_suites(), alpn_protocol_strings,
(uint16_t)num_alpn_protocols, &c->handshaker_factory); alpn_protocol_string_lengths, (uint16_t)num_alpn_protocols,
&c->handshaker_factory);
if (result != TSI_OK) { if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
tsi_result_to_string(result)); tsi_result_to_string(result));

@ -201,6 +201,7 @@ typedef struct {
size_t num_key_cert_pairs; size_t num_key_cert_pairs;
unsigned char *pem_root_certs; unsigned char *pem_root_certs;
size_t pem_root_certs_size; size_t pem_root_certs_size;
int force_client_auth;
} grpc_ssl_server_config; } grpc_ssl_server_config;
/* Creates an SSL server_security_connector. /* Creates an SSL server_security_connector.

@ -120,6 +120,8 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
} }
const grpc_channel_filter grpc_server_auth_filter = { const grpc_channel_filter grpc_server_auth_filter = {
auth_start_transport_op, grpc_channel_next_op, sizeof(call_data), auth_start_transport_op, grpc_channel_next_op,
init_call_elem, destroy_call_elem, sizeof(channel_data), sizeof(call_data), init_call_elem,
init_channel_elem, destroy_channel_elem, "server-auth"}; destroy_call_elem, sizeof(channel_data),
init_channel_elem, destroy_channel_elem,
grpc_call_next_get_peer, "server-auth"};

@ -50,7 +50,7 @@ int gpr_join_host_port(char **out, const char *host, int port) {
} }
} }
void gpr_split_host_port(const char *name, char **host, char **port) { int gpr_split_host_port(const char *name, char **host, char **port) {
const char *host_start; const char *host_start;
size_t host_len; size_t host_len;
const char *port_start; const char *port_start;
@ -63,7 +63,7 @@ void gpr_split_host_port(const char *name, char **host, char **port) {
const char *rbracket = strchr(name, ']'); const char *rbracket = strchr(name, ']');
if (rbracket == NULL) { if (rbracket == NULL) {
/* Unmatched [ */ /* Unmatched [ */
return; return 0;
} }
if (rbracket[1] == '\0') { if (rbracket[1] == '\0') {
/* ]<end> */ /* ]<end> */
@ -73,14 +73,14 @@ void gpr_split_host_port(const char *name, char **host, char **port) {
port_start = rbracket + 2; port_start = rbracket + 2;
} else { } else {
/* ]<invalid> */ /* ]<invalid> */
return; return 0;
} }
host_start = name + 1; host_start = name + 1;
host_len = (size_t)(rbracket - host_start); host_len = (size_t)(rbracket - host_start);
if (memchr(host_start, ':', host_len) == NULL) { if (memchr(host_start, ':', host_len) == NULL) {
/* Require all bracketed hosts to contain a colon, because a hostname or /* Require all bracketed hosts to contain a colon, because a hostname or
IPv4 address should never use brackets. */ IPv4 address should never use brackets. */
return; return 0;
} }
} else { } else {
const char *colon = strchr(name, ':'); const char *colon = strchr(name, ':');
@ -105,4 +105,6 @@ void gpr_split_host_port(const char *name, char **host, char **port) {
if (port_start != NULL) { if (port_start != NULL) {
*port = gpr_strdup(port_start); *port = gpr_strdup(port_start);
} }
return 1;
} }

@ -72,6 +72,11 @@ typedef union lockfree_node {
struct gpr_stack_lockfree { struct gpr_stack_lockfree {
lockfree_node *entries; lockfree_node *entries;
lockfree_node head; /* An atomic entry describing curr head */ lockfree_node head; /* An atomic entry describing curr head */
#ifndef NDEBUG
/* Bitmap of pushed entries to check for double-push or pop */
gpr_atm pushed[(INVALID_ENTRY_INDEX+1)/(8*sizeof(gpr_atm))];
#endif
}; };
gpr_stack_lockfree *gpr_stack_lockfree_create(int entries) { gpr_stack_lockfree *gpr_stack_lockfree_create(int entries) {
@ -86,6 +91,9 @@ gpr_stack_lockfree *gpr_stack_lockfree_create(int entries) {
/* Clear out all entries */ /* Clear out all entries */
memset(stack->entries, 0, entries * sizeof(stack->entries[0])); memset(stack->entries, 0, entries * sizeof(stack->entries[0]));
memset(&stack->head, 0, sizeof(stack->head)); memset(&stack->head, 0, sizeof(stack->head));
#ifndef NDEBUG
memset(&stack->pushed, 0, sizeof(stack->pushed));
#endif
/* Point the head at reserved dummy entry */ /* Point the head at reserved dummy entry */
stack->head.contents.index = INVALID_ENTRY_INDEX; stack->head.contents.index = INVALID_ENTRY_INDEX;
@ -106,6 +114,19 @@ int gpr_stack_lockfree_push(gpr_stack_lockfree *stack, int entry) {
/* Also post-increment the aba_ctr */ /* Also post-increment the aba_ctr */
newhead.contents.aba_ctr = stack->entries[entry].contents.aba_ctr++; newhead.contents.aba_ctr = stack->entries[entry].contents.aba_ctr++;
#ifndef NDEBUG
/* Check for double push */
{
int pushed_index = entry / (8*sizeof(gpr_atm));
int pushed_bit = entry % (8*sizeof(gpr_atm));
gpr_atm old_val;
old_val = gpr_atm_no_barrier_fetch_add(&stack->pushed[pushed_index],
(gpr_atm)(1UL << pushed_bit));
GPR_ASSERT((old_val & (1UL<<pushed_bit)) == 0);
}
#endif
do { do {
/* Atomically get the existing head value for use */ /* Atomically get the existing head value for use */
head.atm = gpr_atm_no_barrier_load(&(stack->head.atm)); head.atm = gpr_atm_no_barrier_load(&(stack->head.atm));
@ -119,6 +140,7 @@ int gpr_stack_lockfree_push(gpr_stack_lockfree *stack, int entry) {
int gpr_stack_lockfree_pop(gpr_stack_lockfree *stack) { int gpr_stack_lockfree_pop(gpr_stack_lockfree *stack) {
lockfree_node head; lockfree_node head;
lockfree_node newhead; lockfree_node newhead;
do { do {
head.atm = gpr_atm_acq_load(&(stack->head.atm)); head.atm = gpr_atm_acq_load(&(stack->head.atm));
if (head.contents.index == INVALID_ENTRY_INDEX) { if (head.contents.index == INVALID_ENTRY_INDEX) {
@ -128,5 +150,18 @@ int gpr_stack_lockfree_pop(gpr_stack_lockfree *stack) {
gpr_atm_no_barrier_load(&(stack->entries[head.contents.index].atm)); gpr_atm_no_barrier_load(&(stack->entries[head.contents.index].atm));
} while (!gpr_atm_no_barrier_cas(&(stack->head.atm), head.atm, newhead.atm)); } while (!gpr_atm_no_barrier_cas(&(stack->head.atm), head.atm, newhead.atm));
#ifndef NDEBUG
/* Check for valid pop */
{
int pushed_index = head.contents.index / (8*sizeof(gpr_atm));
int pushed_bit = head.contents.index % (8*sizeof(gpr_atm));
gpr_atm old_val;
old_val = gpr_atm_no_barrier_fetch_add(&stack->pushed[pushed_index],
-(gpr_atm)(1UL << pushed_bit));
GPR_ASSERT((old_val & (1UL<<pushed_bit)) != 0);
}
#endif
return head.contents.index; return head.contents.index;
} }

@ -63,10 +63,11 @@ void gpr_cv_destroy(gpr_cv *cv) { GPR_ASSERT(pthread_cond_destroy(cv) == 0); }
int gpr_cv_wait(gpr_cv *cv, gpr_mu *mu, gpr_timespec abs_deadline) { int gpr_cv_wait(gpr_cv *cv, gpr_mu *mu, gpr_timespec abs_deadline) {
int err = 0; int err = 0;
if (gpr_time_cmp(abs_deadline, gpr_inf_future(GPR_CLOCK_REALTIME)) == 0) { if (gpr_time_cmp(abs_deadline, gpr_inf_future(abs_deadline.clock_type)) == 0) {
err = pthread_cond_wait(cv, mu); err = pthread_cond_wait(cv, mu);
} else { } else {
struct timespec abs_deadline_ts; struct timespec abs_deadline_ts;
abs_deadline = gpr_convert_clock_type(abs_deadline, GPR_CLOCK_REALTIME);
abs_deadline_ts.tv_sec = abs_deadline.tv_sec; abs_deadline_ts.tv_sec = abs_deadline.tv_sec;
abs_deadline_ts.tv_nsec = abs_deadline.tv_nsec; abs_deadline_ts.tv_nsec = abs_deadline.tv_nsec;
err = pthread_cond_timedwait(cv, mu, &abs_deadline_ts); err = pthread_cond_timedwait(cv, mu, &abs_deadline_ts);

@ -83,10 +83,10 @@ int gpr_cv_wait(gpr_cv *cv, gpr_mu *mu, gpr_timespec abs_deadline) {
int timeout = 0; int timeout = 0;
DWORD timeout_max_ms; DWORD timeout_max_ms;
mu->locked = 0; mu->locked = 0;
if (gpr_time_cmp(abs_deadline, gpr_inf_future(GPR_CLOCK_REALTIME)) == 0) { if (gpr_time_cmp(abs_deadline, gpr_inf_future(abs_deadline.clock_type)) == 0) {
SleepConditionVariableCS(cv, &mu->cs, INFINITE); SleepConditionVariableCS(cv, &mu->cs, INFINITE);
} else { } else {
gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); gpr_timespec now = gpr_now(abs_deadline.clock_type);
gpr_int64 now_ms = now.tv_sec * 1000 + now.tv_nsec / 1000000; gpr_int64 now_ms = now.tv_sec * 1000 + now.tv_nsec / 1000000;
gpr_int64 deadline_ms = gpr_int64 deadline_ms =
abs_deadline.tv_sec * 1000 + abs_deadline.tv_nsec / 1000000; abs_deadline.tv_sec * 1000 + abs_deadline.tv_nsec / 1000000;

@ -290,3 +290,30 @@ gpr_int32 gpr_time_to_millis(gpr_timespec t) {
double gpr_timespec_to_micros(gpr_timespec t) { double gpr_timespec_to_micros(gpr_timespec t) {
return (double)t.tv_sec * GPR_US_PER_SEC + t.tv_nsec * 1e-3; return (double)t.tv_sec * GPR_US_PER_SEC + t.tv_nsec * 1e-3;
} }
gpr_timespec gpr_convert_clock_type(gpr_timespec t, gpr_clock_type clock_type) {
if (t.clock_type == clock_type) {
return t;
}
if (t.tv_nsec == 0) {
if (t.tv_sec == TYPE_MAX(time_t)) {
t.clock_type = clock_type;
return t;
}
if (t.tv_sec == TYPE_MIN(time_t)) {
t.clock_type = clock_type;
return t;
}
}
if (clock_type == GPR_TIMESPAN) {
return gpr_time_sub(t, gpr_now(t.clock_type));
}
if (t.clock_type == GPR_TIMESPAN) {
return gpr_time_add(gpr_now(clock_type), t);
}
return gpr_time_add(gpr_now(clock_type), gpr_time_sub(t, gpr_now(t.clock_type)));
}

@ -120,7 +120,7 @@ void gpr_sleep_until(gpr_timespec until) {
for (;;) { for (;;) {
/* We could simplify by using clock_nanosleep instead, but it might be /* We could simplify by using clock_nanosleep instead, but it might be
* slightly less portable. */ * slightly less portable. */
now = gpr_now(GPR_CLOCK_REALTIME); now = gpr_now(until.clock_type);
if (gpr_time_cmp(until, now) <= 0) { if (gpr_time_cmp(until, now) <= 0) {
return; return;
} }

@ -80,7 +80,7 @@ void gpr_sleep_until(gpr_timespec until) {
for (;;) { for (;;) {
/* We could simplify by using clock_nanosleep instead, but it might be /* We could simplify by using clock_nanosleep instead, but it might be
* slightly less portable. */ * slightly less portable. */
now = gpr_now(GPR_CLOCK_REALTIME); now = gpr_now(until.clock_type);
if (gpr_time_cmp(until, now) <= 0) { if (gpr_time_cmp(until, now) <= 0) {
return; return;
} }

@ -348,7 +348,7 @@ grpc_call *grpc_call_create(grpc_channel *channel, grpc_completion_queue *cq,
} }
grpc_call_stack_init(channel_stack, server_transport_data, initial_op_ptr, grpc_call_stack_init(channel_stack, server_transport_data, initial_op_ptr,
CALL_STACK_FROM_CALL(call)); CALL_STACK_FROM_CALL(call));
if (gpr_time_cmp(send_deadline, gpr_inf_future(GPR_CLOCK_REALTIME)) != 0) { if (gpr_time_cmp(send_deadline, gpr_inf_future(send_deadline.clock_type)) != 0) {
set_deadline_alarm(call, send_deadline); set_deadline_alarm(call, send_deadline);
} }
return call; return call;
@ -932,7 +932,7 @@ static int prepare_application_metadata(grpc_call *call, size_t count,
GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data)); GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data));
l->md = grpc_mdelem_from_string_and_buffer(call->metadata_context, md->key, l->md = grpc_mdelem_from_string_and_buffer(call->metadata_context, md->key,
(const gpr_uint8 *)md->value, (const gpr_uint8 *)md->value,
md->value_length); md->value_length, 1);
if (!grpc_mdstr_is_legal_header(l->md->key)) { if (!grpc_mdstr_is_legal_header(l->md->key)) {
gpr_log(GPR_ERROR, "attempt to send invalid metadata key"); gpr_log(GPR_ERROR, "attempt to send invalid metadata key");
return 0; return 0;
@ -1203,7 +1203,7 @@ grpc_call_error grpc_call_cancel_with_status(grpc_call *c,
static grpc_call_error cancel_with_status(grpc_call *c, grpc_status_code status, static grpc_call_error cancel_with_status(grpc_call *c, grpc_status_code status,
const char *description) { const char *description) {
grpc_mdstr *details = grpc_mdstr *details =
description ? grpc_mdstr_from_string(c->metadata_context, description) description ? grpc_mdstr_from_string(c->metadata_context, description, 0)
: NULL; : NULL;
GPR_ASSERT(status != GRPC_STATUS_OK); GPR_ASSERT(status != GRPC_STATUS_OK);
@ -1253,6 +1253,11 @@ static void execute_op(grpc_call *call, grpc_transport_stream_op *op) {
elem->filter->start_transport_stream_op(elem, op); elem->filter->start_transport_stream_op(elem, op);
} }
char *grpc_call_get_peer(grpc_call *call) {
grpc_call_element *elem = CALL_ELEM_FROM_CALL(call, 0);
return elem->filter->get_peer(elem);
}
grpc_call *grpc_call_from_top_element(grpc_call_element *elem) { grpc_call *grpc_call_from_top_element(grpc_call_element *elem) {
return CALL_FROM_TOP_ELEM(elem); return CALL_FROM_TOP_ELEM(elem);
} }
@ -1278,8 +1283,8 @@ static void set_deadline_alarm(grpc_call *call, gpr_timespec deadline) {
} }
GRPC_CALL_INTERNAL_REF(call, "alarm"); GRPC_CALL_INTERNAL_REF(call, "alarm");
call->have_alarm = 1; call->have_alarm = 1;
grpc_alarm_init(&call->alarm, deadline, call_alarm, call, grpc_alarm_init(&call->alarm, gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC), call_alarm, call,
gpr_now(GPR_CLOCK_REALTIME)); gpr_now(GPR_CLOCK_MONOTONIC));
} }
/* we offset status by a small amount when storing it into transport metadata /* we offset status by a small amount when storing it into transport metadata
@ -1368,7 +1373,8 @@ static void recv_metadata(grpc_call *call, grpc_metadata_batch *md) {
l->md = 0; l->md = 0;
} }
} }
if (gpr_time_cmp(md->deadline, gpr_inf_future(GPR_CLOCK_REALTIME)) != 0) { if (gpr_time_cmp(md->deadline, gpr_inf_future(md->deadline.clock_type)) !=
0) {
set_deadline_alarm(call, md->deadline); set_deadline_alarm(call, md->deadline);
} }
if (!is_trailing) { if (!is_trailing) {
@ -1491,7 +1497,7 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
op->data.send_status_from_server.status_details != NULL op->data.send_status_from_server.status_details != NULL
? grpc_mdstr_from_string( ? grpc_mdstr_from_string(
call->metadata_context, call->metadata_context,
op->data.send_status_from_server.status_details) op->data.send_status_from_server.status_details, 0)
: NULL; : NULL;
req = &reqs[out++]; req = &reqs[out++];
req->op = GRPC_IOREQ_SEND_CLOSE; req->op = GRPC_IOREQ_SEND_CLOSE;

@ -134,6 +134,10 @@ void grpc_server_log_request_call(char *file, int line,
grpc_completion_queue *cq_for_notification, grpc_completion_queue *cq_for_notification,
void *tag); void *tag);
void grpc_server_log_shutdown(char *file, int line, gpr_log_severity severity,
grpc_server *server, grpc_completion_queue *cq,
void *tag);
/* Set a context pointer. /* Set a context pointer.
No thread safety guarantees are made wrt this value. */ No thread safety guarantees are made wrt this value. */
void grpc_call_context_set(grpc_call *call, grpc_context_index elem, void grpc_call_context_set(grpc_call *call, grpc_context_index elem,
@ -151,6 +155,9 @@ void *grpc_call_context_get(grpc_call *call, grpc_context_index elem);
grpc_server_log_request_call(sev, server, call, details, initial_metadata, \ grpc_server_log_request_call(sev, server, call, details, initial_metadata, \
cq_bound_to_call, cq_for_notifications, tag) cq_bound_to_call, cq_for_notifications, tag)
#define GRPC_SERVER_LOG_SHUTDOWN(sev, server, cq, tag) \
if (grpc_trace_batch) grpc_server_log_shutdown(sev, server, cq, tag)
gpr_uint8 grpc_call_is_client(grpc_call *call); gpr_uint8 grpc_call_is_client(grpc_call *call);
#endif /* GRPC_INTERNAL_CORE_SURFACE_CALL_H */ #endif /* GRPC_INTERNAL_CORE_SURFACE_CALL_H */

@ -136,3 +136,11 @@ void grpc_server_log_request_call(char *file, int line,
"tag=%p)", server, call, details, initial_metadata, "tag=%p)", server, call, details, initial_metadata,
cq_bound_to_call, cq_for_notification, tag); cq_bound_to_call, cq_for_notification, tag);
} }
void grpc_server_log_shutdown(char *file, int line, gpr_log_severity severity,
grpc_server *server, grpc_completion_queue *cq,
void *tag) {
gpr_log(file, line, severity,
"grpc_server_shutdown_and_notify(server=%p, cq=%p, tag=%p)", server,
cq, tag);
}

@ -36,12 +36,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/iomgr/iomgr.h" #include "src/core/iomgr/iomgr.h"
#include "src/core/support/string.h" #include "src/core/support/string.h"
#include "src/core/surface/call.h" #include "src/core/surface/call.h"
#include "src/core/surface/init.h" #include "src/core/surface/init.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
/** Cache grpc-status: X mdelems for X = 0..NUM_CACHED_STATUS_ELEMS. /** Cache grpc-status: X mdelems for X = 0..NUM_CACHED_STATUS_ELEMS.
* Avoids needing to take a metadata context lock for sending status * Avoids needing to take a metadata context lock for sending status
@ -73,6 +75,7 @@ struct grpc_channel {
gpr_mu registered_call_mu; gpr_mu registered_call_mu;
registered_call *registered_calls; registered_call *registered_calls;
grpc_iomgr_closure destroy_closure; grpc_iomgr_closure destroy_closure;
char *target;
}; };
#define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c) + 1)) #define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c) + 1))
@ -85,31 +88,32 @@ struct grpc_channel {
#define DEFAULT_MAX_MESSAGE_LENGTH (100 * 1024 * 1024) #define DEFAULT_MAX_MESSAGE_LENGTH (100 * 1024 * 1024)
grpc_channel *grpc_channel_create_from_filters( grpc_channel *grpc_channel_create_from_filters(
const grpc_channel_filter **filters, size_t num_filters, const char *target, const grpc_channel_filter **filters, size_t num_filters,
const grpc_channel_args *args, grpc_mdctx *mdctx, int is_client) { const grpc_channel_args *args, grpc_mdctx *mdctx, int is_client) {
size_t i; size_t i;
size_t size = size_t size =
sizeof(grpc_channel) + grpc_channel_stack_size(filters, num_filters); sizeof(grpc_channel) + grpc_channel_stack_size(filters, num_filters);
grpc_channel *channel = gpr_malloc(size); grpc_channel *channel = gpr_malloc(size);
memset(channel, 0, sizeof(*channel)); memset(channel, 0, sizeof(*channel));
channel->target = gpr_strdup(target);
GPR_ASSERT(grpc_is_initialized() && "call grpc_init()"); GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
channel->is_client = is_client; channel->is_client = is_client;
/* decremented by grpc_channel_destroy */ /* decremented by grpc_channel_destroy */
gpr_ref_init(&channel->refs, 1); gpr_ref_init(&channel->refs, 1);
channel->metadata_context = mdctx; channel->metadata_context = mdctx;
channel->grpc_status_string = grpc_mdstr_from_string(mdctx, "grpc-status"); channel->grpc_status_string = grpc_mdstr_from_string(mdctx, "grpc-status", 0);
channel->grpc_compression_algorithm_string = channel->grpc_compression_algorithm_string =
grpc_mdstr_from_string(mdctx, "grpc-encoding"); grpc_mdstr_from_string(mdctx, "grpc-encoding", 0);
channel->grpc_message_string = grpc_mdstr_from_string(mdctx, "grpc-message"); channel->grpc_message_string = grpc_mdstr_from_string(mdctx, "grpc-message", 0);
for (i = 0; i < NUM_CACHED_STATUS_ELEMS; i++) { for (i = 0; i < NUM_CACHED_STATUS_ELEMS; i++) {
char buf[GPR_LTOA_MIN_BUFSIZE]; char buf[GPR_LTOA_MIN_BUFSIZE];
gpr_ltoa(i, buf); gpr_ltoa(i, buf);
channel->grpc_status_elem[i] = grpc_mdelem_from_metadata_strings( channel->grpc_status_elem[i] = grpc_mdelem_from_metadata_strings(
mdctx, GRPC_MDSTR_REF(channel->grpc_status_string), mdctx, GRPC_MDSTR_REF(channel->grpc_status_string),
grpc_mdstr_from_string(mdctx, buf)); grpc_mdstr_from_string(mdctx, buf, 0));
} }
channel->path_string = grpc_mdstr_from_string(mdctx, ":path"); channel->path_string = grpc_mdstr_from_string(mdctx, ":path", 0);
channel->authority_string = grpc_mdstr_from_string(mdctx, ":authority"); channel->authority_string = grpc_mdstr_from_string(mdctx, ":authority", 0);
gpr_mu_init(&channel->registered_call_mu); gpr_mu_init(&channel->registered_call_mu);
channel->registered_calls = NULL; channel->registered_calls = NULL;
@ -137,6 +141,10 @@ grpc_channel *grpc_channel_create_from_filters(
return channel; return channel;
} }
char *grpc_channel_get_target(grpc_channel *channel) {
return gpr_strdup(channel->target);
}
static grpc_call *grpc_channel_create_call_internal( static grpc_call *grpc_channel_create_call_internal(
grpc_channel *channel, grpc_completion_queue *cq, grpc_mdelem *path_mdelem, grpc_channel *channel, grpc_completion_queue *cq, grpc_mdelem *path_mdelem,
grpc_mdelem *authority_mdelem, gpr_timespec deadline) { grpc_mdelem *authority_mdelem, gpr_timespec deadline) {
@ -159,10 +167,10 @@ grpc_call *grpc_channel_create_call(grpc_channel *channel,
channel, cq, channel, cq,
grpc_mdelem_from_metadata_strings( grpc_mdelem_from_metadata_strings(
channel->metadata_context, GRPC_MDSTR_REF(channel->path_string), channel->metadata_context, GRPC_MDSTR_REF(channel->path_string),
grpc_mdstr_from_string(channel->metadata_context, method)), grpc_mdstr_from_string(channel->metadata_context, method, 0)),
grpc_mdelem_from_metadata_strings( grpc_mdelem_from_metadata_strings(
channel->metadata_context, GRPC_MDSTR_REF(channel->authority_string), channel->metadata_context, GRPC_MDSTR_REF(channel->authority_string),
grpc_mdstr_from_string(channel->metadata_context, host)), grpc_mdstr_from_string(channel->metadata_context, host, 0)),
deadline); deadline);
} }
@ -171,10 +179,10 @@ void *grpc_channel_register_call(grpc_channel *channel, const char *method,
registered_call *rc = gpr_malloc(sizeof(registered_call)); registered_call *rc = gpr_malloc(sizeof(registered_call));
rc->path = grpc_mdelem_from_metadata_strings( rc->path = grpc_mdelem_from_metadata_strings(
channel->metadata_context, GRPC_MDSTR_REF(channel->path_string), channel->metadata_context, GRPC_MDSTR_REF(channel->path_string),
grpc_mdstr_from_string(channel->metadata_context, method)); grpc_mdstr_from_string(channel->metadata_context, method, 0));
rc->authority = grpc_mdelem_from_metadata_strings( rc->authority = grpc_mdelem_from_metadata_strings(
channel->metadata_context, GRPC_MDSTR_REF(channel->authority_string), channel->metadata_context, GRPC_MDSTR_REF(channel->authority_string),
grpc_mdstr_from_string(channel->metadata_context, host)); grpc_mdstr_from_string(channel->metadata_context, host, 0));
gpr_mu_lock(&channel->registered_call_mu); gpr_mu_lock(&channel->registered_call_mu);
rc->next = channel->registered_calls; rc->next = channel->registered_calls;
channel->registered_calls = rc; channel->registered_calls = rc;
@ -222,6 +230,7 @@ static void destroy_channel(void *p, int ok) {
} }
grpc_mdctx_unref(channel->metadata_context); grpc_mdctx_unref(channel->metadata_context);
gpr_mu_destroy(&channel->registered_call_mu); gpr_mu_destroy(&channel->registered_call_mu);
gpr_free(channel->target);
gpr_free(channel); gpr_free(channel);
} }
@ -275,7 +284,7 @@ grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel, int i) {
gpr_ltoa(i, tmp); gpr_ltoa(i, tmp);
return grpc_mdelem_from_metadata_strings( return grpc_mdelem_from_metadata_strings(
channel->metadata_context, GRPC_MDSTR_REF(channel->grpc_status_string), channel->metadata_context, GRPC_MDSTR_REF(channel->grpc_status_string),
grpc_mdstr_from_string(channel->metadata_context, tmp)); grpc_mdstr_from_string(channel->metadata_context, tmp, 0));
} }
} }

@ -38,7 +38,7 @@
#include "src/core/client_config/subchannel_factory.h" #include "src/core/client_config/subchannel_factory.h"
grpc_channel *grpc_channel_create_from_filters( grpc_channel *grpc_channel_create_from_filters(
const grpc_channel_filter **filters, size_t count, const char *target, const grpc_channel_filter **filters, size_t count,
const grpc_channel_args *args, grpc_mdctx *mdctx, int is_client); const grpc_channel_args *args, grpc_mdctx *mdctx, int is_client);
/** Get a (borrowed) pointer to this channels underlying channel stack */ /** Get a (borrowed) pointer to this channels underlying channel stack */

@ -0,0 +1,191 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/surface/channel.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/channel/client_channel.h"
#include "src/core/iomgr/alarm.h"
#include "src/core/surface/completion_queue.h"
grpc_connectivity_state grpc_channel_check_connectivity_state(
grpc_channel *channel, int try_to_connect) {
/* forward through to the underlying client channel */
grpc_channel_element *client_channel_elem =
grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel));
if (client_channel_elem->filter != &grpc_client_channel_filter) {
gpr_log(GPR_ERROR,
"grpc_channel_check_connectivity_state called on something that is "
"not a client channel, but '%s'",
client_channel_elem->filter->name);
return GRPC_CHANNEL_FATAL_FAILURE;
}
return grpc_client_channel_check_connectivity_state(client_channel_elem,
try_to_connect);
}
typedef enum {
WAITING,
CALLING_BACK,
CALLING_BACK_AND_FINISHED,
CALLED_BACK
} callback_phase;
typedef struct {
gpr_mu mu;
callback_phase phase;
int success;
grpc_iomgr_closure on_complete;
grpc_alarm alarm;
grpc_connectivity_state state;
grpc_connectivity_state *optional_new_state;
grpc_completion_queue *cq;
grpc_cq_completion completion_storage;
grpc_channel *channel;
void *tag;
} state_watcher;
static void delete_state_watcher(state_watcher *w) {
grpc_channel_element *client_channel_elem =
grpc_channel_stack_last_element(grpc_channel_get_channel_stack(w->channel));
grpc_client_channel_del_interested_party(client_channel_elem, grpc_cq_pollset(w->cq));
GRPC_CHANNEL_INTERNAL_UNREF(w->channel, "watch_connectivity");
gpr_mu_destroy(&w->mu);
gpr_free(w);
}
static void finished_completion(void *pw, grpc_cq_completion *ignored) {
int delete = 0;
state_watcher *w = pw;
gpr_mu_lock(&w->mu);
switch (w->phase) {
case WAITING:
case CALLED_BACK:
gpr_log(GPR_ERROR, "should never reach here");
abort();
break;
case CALLING_BACK:
w->phase = CALLED_BACK;
break;
case CALLING_BACK_AND_FINISHED:
delete = 1;
break;
}
gpr_mu_unlock(&w->mu);
if (delete) {
delete_state_watcher(w);
}
}
static void partly_done(state_watcher *w, int due_to_completion) {
int delete = 0;
if (due_to_completion) {
gpr_mu_lock(&w->mu);
w->success = 1;
gpr_mu_unlock(&w->mu);
grpc_alarm_cancel(&w->alarm);
}
gpr_mu_lock(&w->mu);
switch (w->phase) {
case WAITING:
w->phase = CALLING_BACK;
if (w->optional_new_state) {
*w->optional_new_state = w->state;
}
grpc_cq_end_op(w->cq, w->tag, w->success, finished_completion, w,
&w->completion_storage);
break;
case CALLING_BACK:
w->phase = CALLING_BACK_AND_FINISHED;
break;
case CALLING_BACK_AND_FINISHED:
gpr_log(GPR_ERROR, "should never reach here");
abort();
break;
case CALLED_BACK:
delete = 1;
break;
}
gpr_mu_unlock(&w->mu);
if (delete) {
delete_state_watcher(w);
}
}
static void watch_complete(void *pw, int success) { partly_done(pw, 1); }
static void timeout_complete(void *pw, int success) { partly_done(pw, 0); }
void grpc_channel_watch_connectivity_state(
grpc_channel *channel, grpc_connectivity_state last_observed_state,
grpc_connectivity_state *optional_new_state, gpr_timespec deadline,
grpc_completion_queue *cq, void *tag) {
grpc_channel_element *client_channel_elem =
grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel));
state_watcher *w = gpr_malloc(sizeof(*w));
grpc_cq_begin_op(cq);
gpr_mu_init(&w->mu);
grpc_iomgr_closure_init(&w->on_complete, watch_complete, w);
w->phase = WAITING;
w->state = last_observed_state;
w->success = 0;
w->optional_new_state = optional_new_state;
w->cq = cq;
w->tag = tag;
w->channel = channel;
grpc_alarm_init(
&w->alarm, gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
timeout_complete, w, gpr_now(GPR_CLOCK_MONOTONIC));
if (client_channel_elem->filter != &grpc_client_channel_filter) {
gpr_log(GPR_ERROR,
"grpc_channel_watch_connectivity_state called on something that is "
"not a client channel, but '%s'",
client_channel_elem->filter->name);
grpc_iomgr_add_delayed_callback(&w->on_complete, 1);
} else {
GRPC_CHANNEL_INTERNAL_REF(channel, "watch_connectivity");
grpc_client_channel_add_interested_party(client_channel_elem, grpc_cq_pollset(cq));
grpc_client_channel_watch_connectivity_state(client_channel_elem, &w->state,
&w->on_complete);
}
}

@ -109,6 +109,7 @@ typedef struct {
gpr_refcount refs; gpr_refcount refs;
grpc_mdctx *mdctx; grpc_mdctx *mdctx;
grpc_channel_args *merge_args; grpc_channel_args *merge_args;
grpc_channel *master;
} subchannel_factory; } subchannel_factory;
static void subchannel_factory_ref(grpc_subchannel_factory *scf) { static void subchannel_factory_ref(grpc_subchannel_factory *scf) {
@ -119,6 +120,7 @@ static void subchannel_factory_ref(grpc_subchannel_factory *scf) {
static void subchannel_factory_unref(grpc_subchannel_factory *scf) { static void subchannel_factory_unref(grpc_subchannel_factory *scf) {
subchannel_factory *f = (subchannel_factory *)scf; subchannel_factory *f = (subchannel_factory *)scf;
if (gpr_unref(&f->refs)) { if (gpr_unref(&f->refs)) {
GRPC_CHANNEL_INTERNAL_UNREF(f->master, "subchannel_factory");
grpc_channel_args_destroy(f->merge_args); grpc_channel_args_destroy(f->merge_args);
grpc_mdctx_unref(f->mdctx); grpc_mdctx_unref(f->mdctx);
gpr_free(f); gpr_free(f);
@ -137,6 +139,7 @@ static grpc_subchannel *subchannel_factory_create_subchannel(
gpr_ref_init(&c->refs, 1); gpr_ref_init(&c->refs, 1);
args->mdctx = f->mdctx; args->mdctx = f->mdctx;
args->args = final_args; args->args = final_args;
args->master = f->master;
s = grpc_subchannel_create(&c->base, args); s = grpc_subchannel_create(&c->base, args);
grpc_connector_unref(&c->base); grpc_connector_unref(&c->base);
grpc_channel_args_destroy(final_args); grpc_channel_args_destroy(final_args);
@ -151,7 +154,7 @@ static const grpc_subchannel_factory_vtable subchannel_factory_vtable = {
Asynchronously: - resolve target Asynchronously: - resolve target
- connect to it (trying alternatives as presented) - connect to it (trying alternatives as presented)
- perform handshakes */ - perform handshakes */
grpc_channel *grpc_channel_create(const char *target, grpc_channel *grpc_insecure_channel_create(const char *target,
const grpc_channel_args *args) { const grpc_channel_args *args) {
grpc_channel *channel = NULL; grpc_channel *channel = NULL;
#define MAX_FILTERS 3 #define MAX_FILTERS 3
@ -168,18 +171,22 @@ grpc_channel *grpc_channel_create(const char *target,
filters[n++] = &grpc_client_channel_filter; filters[n++] = &grpc_client_channel_filter;
GPR_ASSERT(n <= MAX_FILTERS); GPR_ASSERT(n <= MAX_FILTERS);
channel =
grpc_channel_create_from_filters(target, filters, n, args, mdctx, 1);
f = gpr_malloc(sizeof(*f)); f = gpr_malloc(sizeof(*f));
f->base.vtable = &subchannel_factory_vtable; f->base.vtable = &subchannel_factory_vtable;
gpr_ref_init(&f->refs, 1); gpr_ref_init(&f->refs, 1);
grpc_mdctx_ref(mdctx); grpc_mdctx_ref(mdctx);
f->mdctx = mdctx; f->mdctx = mdctx;
f->merge_args = grpc_channel_args_copy(args); f->merge_args = grpc_channel_args_copy(args);
f->master = channel;
GRPC_CHANNEL_INTERNAL_REF(f->master, "subchannel_factory");
resolver = grpc_resolver_create(target, &f->base); resolver = grpc_resolver_create(target, &f->base);
if (!resolver) { if (!resolver) {
return NULL; return NULL;
} }
channel = grpc_channel_create_from_filters(filters, n, args, mdctx, 1);
grpc_client_channel_set_resolver(grpc_channel_get_channel_stack(channel), grpc_client_channel_set_resolver(grpc_channel_get_channel_stack(channel),
resolver); resolver);
GRPC_RESOLVER_UNREF(resolver, "create"); GRPC_RESOLVER_UNREF(resolver, "create");

@ -148,6 +148,8 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
gpr_timespec deadline) { gpr_timespec deadline) {
grpc_event ret; grpc_event ret;
deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
GRPC_CQ_INTERNAL_REF(cc, "next"); GRPC_CQ_INTERNAL_REF(cc, "next");
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
for (;;) { for (;;) {
@ -188,6 +190,8 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
grpc_cq_completion *c; grpc_cq_completion *c;
grpc_cq_completion *prev; grpc_cq_completion *prev;
deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
GRPC_CQ_INTERNAL_REF(cc, "pluck"); GRPC_CQ_INTERNAL_REF(cc, "pluck");
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
for (;;) { for (;;) {

@ -39,6 +39,7 @@
#include "src/core/channel/channel_stack.h" #include "src/core/channel/channel_stack.h"
#include "src/core/client_config/resolver_registry.h" #include "src/core/client_config/resolver_registry.h"
#include "src/core/client_config/resolvers/dns_resolver.h" #include "src/core/client_config/resolvers/dns_resolver.h"
#include "src/core/client_config/resolvers/sockaddr_resolver.h"
#include "src/core/debug/trace.h" #include "src/core/debug/trace.h"
#include "src/core/iomgr/iomgr.h" #include "src/core/iomgr/iomgr.h"
#include "src/core/profiling/timers.h" #include "src/core/profiling/timers.h"
@ -46,10 +47,7 @@
#include "src/core/surface/init.h" #include "src/core/surface/init.h"
#include "src/core/surface/surface_trace.h" #include "src/core/surface/surface_trace.h"
#include "src/core/transport/chttp2_transport.h" #include "src/core/transport/chttp2_transport.h"
#include "src/core/transport/connectivity_state.h"
#ifdef GPR_POSIX_SOCKET
#include "src/core/client_config/resolvers/unix_resolver_posix.h"
#endif
static gpr_once g_basic_init = GPR_ONCE_INIT; static gpr_once g_basic_init = GPR_ONCE_INIT;
static gpr_mu g_init_mu; static gpr_mu g_init_mu;
@ -68,6 +66,8 @@ void grpc_init(void) {
gpr_time_init(); gpr_time_init();
grpc_resolver_registry_init("dns:///"); grpc_resolver_registry_init("dns:///");
grpc_register_resolver_type("dns", grpc_dns_resolver_factory_create()); grpc_register_resolver_type("dns", grpc_dns_resolver_factory_create());
grpc_register_resolver_type("ipv4", grpc_ipv4_resolver_factory_create());
grpc_register_resolver_type("ipv6", grpc_ipv6_resolver_factory_create());
#ifdef GPR_POSIX_SOCKET #ifdef GPR_POSIX_SOCKET
grpc_register_resolver_type("unix", grpc_unix_resolver_factory_create()); grpc_register_resolver_type("unix", grpc_unix_resolver_factory_create());
#endif #endif
@ -76,12 +76,16 @@ void grpc_init(void) {
grpc_register_tracer("http", &grpc_http_trace); grpc_register_tracer("http", &grpc_http_trace);
grpc_register_tracer("flowctl", &grpc_flowctl_trace); grpc_register_tracer("flowctl", &grpc_flowctl_trace);
grpc_register_tracer("batch", &grpc_trace_batch); grpc_register_tracer("batch", &grpc_trace_batch);
grpc_register_tracer("connectivity_state", &grpc_connectivity_state_trace);
grpc_security_pre_init(); grpc_security_pre_init();
grpc_iomgr_init(); grpc_iomgr_init();
grpc_tracer_init("GRPC_TRACE"); grpc_tracer_init("GRPC_TRACE");
if (census_initialize(CENSUS_NONE)) { /* Only initialize census if noone else has. */
if (census_enabled() == CENSUS_FEATURE_NONE) {
if (census_initialize(census_supported())) { /* enable all features. */
gpr_log(GPR_ERROR, "Could not initialize census."); gpr_log(GPR_ERROR, "Could not initialize census.");
} }
}
grpc_timers_global_init(); grpc_timers_global_init();
} }
gpr_mu_unlock(&g_init_mu); gpr_mu_unlock(&g_init_mu);

@ -47,7 +47,10 @@ typedef struct {
grpc_linked_mdelem details; grpc_linked_mdelem details;
} call_data; } call_data;
typedef struct { grpc_mdctx *mdctx; } channel_data; typedef struct {
grpc_mdctx *mdctx;
grpc_channel *master;
} channel_data;
static void lame_start_transport_stream_op(grpc_call_element *elem, static void lame_start_transport_stream_op(grpc_call_element *elem,
grpc_transport_stream_op *op) { grpc_transport_stream_op *op) {
@ -82,6 +85,11 @@ static void lame_start_transport_stream_op(grpc_call_element *elem,
} }
} }
static char *lame_get_peer(grpc_call_element *elem) {
channel_data *chand = elem->channel_data;
return grpc_channel_get_target(chand->master);
}
static void lame_start_transport_op(grpc_channel_element *elem, static void lame_start_transport_op(grpc_channel_element *elem,
grpc_transport_op *op) { grpc_transport_op *op) {
if (op->on_connectivity_state_change) { if (op->on_connectivity_state_change) {
@ -112,6 +120,7 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
GPR_ASSERT(is_first); GPR_ASSERT(is_first);
GPR_ASSERT(is_last); GPR_ASSERT(is_last);
chand->mdctx = mdctx; chand->mdctx = mdctx;
chand->master = master;
} }
static void destroy_channel_elem(grpc_channel_element *elem) {} static void destroy_channel_elem(grpc_channel_element *elem) {}
@ -125,11 +134,12 @@ static const grpc_channel_filter lame_filter = {
sizeof(channel_data), sizeof(channel_data),
init_channel_elem, init_channel_elem,
destroy_channel_elem, destroy_channel_elem,
lame_get_peer,
"lame-client", "lame-client",
}; };
grpc_channel *grpc_lame_client_channel_create(void) { grpc_channel *grpc_lame_client_channel_create(const char *target) {
static const grpc_channel_filter *filters[] = {&lame_filter}; static const grpc_channel_filter *filters[] = {&lame_filter};
return grpc_channel_create_from_filters(filters, 1, NULL, grpc_mdctx_create(), return grpc_channel_create_from_filters(target, filters, 1, NULL,
1); grpc_mdctx_create(), 1);
} }

@ -134,6 +134,7 @@ typedef struct {
grpc_mdctx *mdctx; grpc_mdctx *mdctx;
grpc_channel_args *merge_args; grpc_channel_args *merge_args;
grpc_channel_security_connector *security_connector; grpc_channel_security_connector *security_connector;
grpc_channel *master;
} subchannel_factory; } subchannel_factory;
static void subchannel_factory_ref(grpc_subchannel_factory *scf) { static void subchannel_factory_ref(grpc_subchannel_factory *scf) {
@ -146,6 +147,7 @@ static void subchannel_factory_unref(grpc_subchannel_factory *scf) {
if (gpr_unref(&f->refs)) { if (gpr_unref(&f->refs)) {
GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base, GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
"subchannel_factory"); "subchannel_factory");
GRPC_CHANNEL_INTERNAL_UNREF(f->master, "subchannel_factory");
grpc_channel_args_destroy(f->merge_args); grpc_channel_args_destroy(f->merge_args);
grpc_mdctx_unref(f->mdctx); grpc_mdctx_unref(f->mdctx);
gpr_free(f); gpr_free(f);
@ -165,6 +167,7 @@ static grpc_subchannel *subchannel_factory_create_subchannel(
gpr_ref_init(&c->refs, 1); gpr_ref_init(&c->refs, 1);
args->mdctx = f->mdctx; args->mdctx = f->mdctx;
args->args = final_args; args->args = final_args;
args->master = f->master;
s = grpc_subchannel_create(&c->base, args); s = grpc_subchannel_create(&c->base, args);
grpc_connector_unref(&c->base); grpc_connector_unref(&c->base);
grpc_channel_args_destroy(final_args); grpc_channel_args_destroy(final_args);
@ -196,13 +199,13 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
if (grpc_find_security_connector_in_args(args) != NULL) { if (grpc_find_security_connector_in_args(args) != NULL) {
gpr_log(GPR_ERROR, "Cannot set security context in channel args."); gpr_log(GPR_ERROR, "Cannot set security context in channel args.");
return grpc_lame_client_channel_create(); return grpc_lame_client_channel_create(target);
} }
if (grpc_credentials_create_security_connector( if (grpc_credentials_create_security_connector(
creds, target, args, NULL, &connector, &new_args_from_connector) != creds, target, args, NULL, &connector, &new_args_from_connector) !=
GRPC_SECURITY_OK) { GRPC_SECURITY_OK) {
return grpc_lame_client_channel_create(); return grpc_lame_client_channel_create(target);
} }
mdctx = grpc_mdctx_create(); mdctx = grpc_mdctx_create();
@ -218,6 +221,9 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
filters[n++] = &grpc_client_channel_filter; filters[n++] = &grpc_client_channel_filter;
GPR_ASSERT(n <= MAX_FILTERS); GPR_ASSERT(n <= MAX_FILTERS);
channel =
grpc_channel_create_from_filters(target, filters, n, args_copy, mdctx, 1);
f = gpr_malloc(sizeof(*f)); f = gpr_malloc(sizeof(*f));
f->base.vtable = &subchannel_factory_vtable; f->base.vtable = &subchannel_factory_vtable;
gpr_ref_init(&f->refs, 1); gpr_ref_init(&f->refs, 1);
@ -226,12 +232,13 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
GRPC_SECURITY_CONNECTOR_REF(&connector->base, "subchannel_factory"); GRPC_SECURITY_CONNECTOR_REF(&connector->base, "subchannel_factory");
f->security_connector = connector; f->security_connector = connector;
f->merge_args = grpc_channel_args_copy(args_copy); f->merge_args = grpc_channel_args_copy(args_copy);
f->master = channel;
GRPC_CHANNEL_INTERNAL_REF(channel, "subchannel_factory");
resolver = grpc_resolver_create(target, &f->base); resolver = grpc_resolver_create(target, &f->base);
if (!resolver) { if (!resolver) {
return NULL; return NULL;
} }
channel = grpc_channel_create_from_filters(filters, n, args_copy, mdctx, 1);
grpc_client_channel_set_resolver(grpc_channel_get_channel_stack(channel), grpc_client_channel_set_resolver(grpc_channel_get_channel_stack(channel),
resolver); resolver);
GRPC_RESOLVER_UNREF(resolver, "create"); GRPC_RESOLVER_UNREF(resolver, "create");

@ -400,6 +400,15 @@ static void finish_start_new_rpc(grpc_server *server, grpc_call_element *elem,
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
int request_id; int request_id;
if (gpr_atm_acq_load(&server->shutdown_flag)) {
gpr_mu_lock(&calld->mu_state);
calld->state = ZOMBIED;
gpr_mu_unlock(&calld->mu_state);
grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
grpc_iomgr_add_callback(&calld->kill_zombie_closure);
return;
}
request_id = gpr_stack_lockfree_pop(request_matcher->requests); request_id = gpr_stack_lockfree_pop(request_matcher->requests);
if (request_id == -1) { if (request_id == -1) {
gpr_mu_lock(&server->mu_call); gpr_mu_lock(&server->mu_call);
@ -530,6 +539,7 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
static void server_on_recv(void *ptr, int success) { static void server_on_recv(void *ptr, int success) {
grpc_call_element *elem = ptr; grpc_call_element *elem = ptr;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
gpr_timespec op_deadline;
if (success && !calld->got_initial_metadata) { if (success && !calld->got_initial_metadata) {
size_t i; size_t i;
@ -539,8 +549,9 @@ static void server_on_recv(void *ptr, int success) {
grpc_stream_op *op = &ops[i]; grpc_stream_op *op = &ops[i];
if (op->type != GRPC_OP_METADATA) continue; if (op->type != GRPC_OP_METADATA) continue;
grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem); grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem);
if (0 != gpr_time_cmp(op->data.metadata.deadline, op_deadline = op->data.metadata.deadline;
gpr_inf_future(GPR_CLOCK_REALTIME))) { if (0 !=
gpr_time_cmp(op_deadline, gpr_inf_future(op_deadline.clock_type))) {
calld->deadline = op->data.metadata.deadline; calld->deadline = op->data.metadata.deadline;
} }
calld->got_initial_metadata = 1; calld->got_initial_metadata = 1;
@ -677,8 +688,8 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
GPR_ASSERT(!is_last); GPR_ASSERT(!is_last);
chand->server = NULL; chand->server = NULL;
chand->channel = NULL; chand->channel = NULL;
chand->path_key = grpc_mdstr_from_string(metadata_context, ":path"); chand->path_key = grpc_mdstr_from_string(metadata_context, ":path", 0);
chand->authority_key = grpc_mdstr_from_string(metadata_context, ":authority"); chand->authority_key = grpc_mdstr_from_string(metadata_context, ":authority", 0);
chand->next = chand->prev = chand; chand->next = chand->prev = chand;
chand->registered_methods = NULL; chand->registered_methods = NULL;
chand->connectivity_state = GRPC_CHANNEL_IDLE; chand->connectivity_state = GRPC_CHANNEL_IDLE;
@ -722,6 +733,7 @@ static const grpc_channel_filter server_surface_filter = {
sizeof(channel_data), sizeof(channel_data),
init_channel_elem, init_channel_elem,
destroy_channel_elem, destroy_channel_elem,
grpc_call_next_get_peer,
"server", "server",
}; };
@ -878,8 +890,8 @@ void grpc_server_setup_transport(grpc_server *s, grpc_transport *transport,
grpc_transport_perform_op(transport, &op); grpc_transport_perform_op(transport, &op);
} }
channel = channel = grpc_channel_create_from_filters(NULL, filters, num_filters, args,
grpc_channel_create_from_filters(filters, num_filters, args, mdctx, 0); mdctx, 0);
chand = (channel_data *)grpc_channel_stack_element( chand = (channel_data *)grpc_channel_stack_element(
grpc_channel_get_channel_stack(channel), 0) grpc_channel_get_channel_stack(channel), 0)
->channel_data; ->channel_data;
@ -899,8 +911,8 @@ void grpc_server_setup_transport(grpc_server *s, grpc_transport *transport,
chand->registered_methods = gpr_malloc(alloc); chand->registered_methods = gpr_malloc(alloc);
memset(chand->registered_methods, 0, alloc); memset(chand->registered_methods, 0, alloc);
for (rm = s->registered_methods; rm; rm = rm->next) { for (rm = s->registered_methods; rm; rm = rm->next) {
host = rm->host ? grpc_mdstr_from_string(mdctx, rm->host) : NULL; host = rm->host ? grpc_mdstr_from_string(mdctx, rm->host, 0) : NULL;
method = grpc_mdstr_from_string(mdctx, rm->method); method = grpc_mdstr_from_string(mdctx, rm->method, 0);
hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash); hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
for (probes = 0; chand->registered_methods[(hash + probes) % slots] for (probes = 0; chand->registered_methods[(hash + probes) % slots]
.server_registered_method != NULL; .server_registered_method != NULL;
@ -980,6 +992,8 @@ void grpc_server_shutdown_and_notify(grpc_server *server,
channel_broadcaster broadcaster; channel_broadcaster broadcaster;
request_killer reqkill; request_killer reqkill;
GRPC_SERVER_LOG_SHUTDOWN(GPR_INFO, server, cq, tag);
/* lock, and gather up some stuff to do */ /* lock, and gather up some stuff to do */
gpr_mu_lock(&server->mu_global); gpr_mu_lock(&server->mu_global);
grpc_cq_begin_op(cq); grpc_cq_begin_op(cq);

@ -92,7 +92,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
p->frame_type = *cur; p->frame_type = *cur;
switch (p->frame_type) { switch (p->frame_type) {
case 0: case 0:
/* noop */ p->is_frame_compressed = 0; /* GPR_FALSE */
break; break;
case 1: case 1:
p->is_frame_compressed = 1; /* GPR_TRUE */ p->is_frame_compressed = 1; /* GPR_TRUE */

@ -60,7 +60,6 @@ typedef enum {
GRPC_CHTTP2_LIST_WRITABLE, GRPC_CHTTP2_LIST_WRITABLE,
GRPC_CHTTP2_LIST_WRITING, GRPC_CHTTP2_LIST_WRITING,
GRPC_CHTTP2_LIST_WRITTEN, GRPC_CHTTP2_LIST_WRITTEN,
GRPC_CHTTP2_LIST_WRITABLE_WINDOW_UPDATE,
GRPC_CHTTP2_LIST_PARSING_SEEN, GRPC_CHTTP2_LIST_PARSING_SEEN,
GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING, GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING,
GRPC_CHTTP2_LIST_CANCELLED_WAITING_FOR_WRITING, GRPC_CHTTP2_LIST_CANCELLED_WAITING_FOR_WRITING,
@ -286,6 +285,7 @@ struct grpc_chttp2_transport {
grpc_endpoint *ep; grpc_endpoint *ep;
grpc_mdctx *metadata_context; grpc_mdctx *metadata_context;
gpr_refcount refs; gpr_refcount refs;
char *peer_string;
gpr_mu mu; gpr_mu mu;
@ -382,6 +382,8 @@ typedef struct {
gpr_uint8 published_cancelled; gpr_uint8 published_cancelled;
/** is this stream in the stream map? (boolean) */ /** is this stream in the stream map? (boolean) */
gpr_uint8 in_stream_map; gpr_uint8 in_stream_map;
/** is this stream actively being written? */
gpr_uint8 writing_now;
/** stream state already published to the upper layer */ /** stream state already published to the upper layer */
grpc_stream_state published_state; grpc_stream_state published_state;
@ -474,11 +476,17 @@ void grpc_chttp2_publish_reads(grpc_chttp2_transport_global *global,
void grpc_chttp2_list_add_writable_stream( void grpc_chttp2_list_add_writable_stream(
grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global); grpc_chttp2_stream_global *stream_global);
void grpc_chttp2_list_add_first_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
int grpc_chttp2_list_pop_writable_stream( int grpc_chttp2_list_pop_writable_stream(
grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_writing *transport_writing, grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_global **stream_global, grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_writing **stream_writing); grpc_chttp2_stream_writing **stream_writing);
void grpc_chttp2_list_remove_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
void grpc_chttp2_list_add_incoming_window_updated( void grpc_chttp2_list_add_incoming_window_updated(
grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_global *transport_global,
@ -510,18 +518,6 @@ int grpc_chttp2_list_pop_written_stream(
grpc_chttp2_stream_global **stream_global, grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_writing **stream_writing); grpc_chttp2_stream_writing **stream_writing);
void grpc_chttp2_list_add_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
int grpc_chttp2_list_pop_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_writing **stream_writing);
void grpc_chttp2_list_remove_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
void grpc_chttp2_list_add_parsing_seen_stream( void grpc_chttp2_list_add_parsing_seen_stream(
grpc_chttp2_transport_parsing *transport_parsing, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing); grpc_chttp2_stream_parsing *stream_parsing);

@ -182,8 +182,7 @@ void grpc_chttp2_publish_reads(
stream_global->max_recv_bytes -= stream_global->max_recv_bytes -=
stream_parsing->incoming_window_delta; stream_parsing->incoming_window_delta;
stream_parsing->incoming_window_delta = 0; stream_parsing->incoming_window_delta = 0;
grpc_chttp2_list_add_writable_window_update_stream(transport_global, grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
stream_global);
} }
/* update outgoing flow control window */ /* update outgoing flow control window */
@ -588,7 +587,7 @@ static void on_header(void *tp, grpc_mdelem *md) {
GPR_ASSERT(stream_parsing); GPR_ASSERT(stream_parsing);
GRPC_CHTTP2_IF_TRACING(gpr_log( GRPC_CHTTP2_IF_TRACING(gpr_log(
GPR_INFO, "HTTP:%d:HDR: %s: %s", stream_parsing->id, GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", stream_parsing->id,
transport_parsing->is_client ? "CLI" : "SVR", transport_parsing->is_client ? "CLI" : "SVR",
grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value))); grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));
@ -607,7 +606,7 @@ static void on_header(void *tp, grpc_mdelem *md) {
} }
grpc_chttp2_incoming_metadata_buffer_set_deadline( grpc_chttp2_incoming_metadata_buffer_set_deadline(
&stream_parsing->incoming_metadata, &stream_parsing->incoming_metadata,
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), *cached_timeout)); gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout));
GRPC_MDELEM_UNREF(md); GRPC_MDELEM_UNREF(md);
} else { } else {
grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->incoming_metadata, grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->incoming_metadata,

@ -438,10 +438,10 @@ static void deadline_enc(grpc_chttp2_hpack_compressor *c, gpr_timespec deadline,
char timeout_str[GRPC_CHTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE]; char timeout_str[GRPC_CHTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE];
grpc_mdelem *mdelem; grpc_mdelem *mdelem;
grpc_chttp2_encode_timeout( grpc_chttp2_encode_timeout(
gpr_time_sub(deadline, gpr_now(GPR_CLOCK_REALTIME)), timeout_str); gpr_time_sub(deadline, gpr_now(deadline.clock_type)), timeout_str);
mdelem = grpc_mdelem_from_metadata_strings( mdelem = grpc_mdelem_from_metadata_strings(
c->mdctx, GRPC_MDSTR_REF(c->timeout_key_str), c->mdctx, GRPC_MDSTR_REF(c->timeout_key_str),
grpc_mdstr_from_string(c->mdctx, timeout_str)); grpc_mdstr_from_string(c->mdctx, timeout_str, 0));
mdelem = hpack_enc(c, mdelem, st); mdelem = hpack_enc(c, mdelem, st);
if (mdelem) GRPC_MDELEM_UNREF(mdelem); if (mdelem) GRPC_MDELEM_UNREF(mdelem);
} }
@ -456,7 +456,7 @@ void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c,
grpc_mdctx *ctx) { grpc_mdctx *ctx) {
memset(c, 0, sizeof(*c)); memset(c, 0, sizeof(*c));
c->mdctx = ctx; c->mdctx = ctx;
c->timeout_key_str = grpc_mdstr_from_string(ctx, "grpc-timeout"); c->timeout_key_str = grpc_mdstr_from_string(ctx, "grpc-timeout", 0);
} }
void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) { void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) {
@ -560,6 +560,7 @@ void grpc_chttp2_encode(grpc_stream_op *ops, size_t ops_count, int eof,
grpc_mdctx *mdctx = compressor->mdctx; grpc_mdctx *mdctx = compressor->mdctx;
grpc_linked_mdelem *l; grpc_linked_mdelem *l;
int need_unref = 0; int need_unref = 0;
gpr_timespec deadline;
GPR_ASSERT(stream_id != 0); GPR_ASSERT(stream_id != 0);
@ -589,9 +590,9 @@ void grpc_chttp2_encode(grpc_stream_op *ops, size_t ops_count, int eof,
l->md = hpack_enc(compressor, l->md, &st); l->md = hpack_enc(compressor, l->md, &st);
need_unref |= l->md != NULL; need_unref |= l->md != NULL;
} }
if (gpr_time_cmp(op->data.metadata.deadline, deadline = op->data.metadata.deadline;
gpr_inf_future(GPR_CLOCK_REALTIME)) != 0) { if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) != 0) {
deadline_enc(compressor, op->data.metadata.deadline, &st); deadline_enc(compressor, deadline, &st);
} }
curop++; curop++;
break; break;

@ -108,6 +108,23 @@ static void stream_list_maybe_remove(grpc_chttp2_transport *t,
} }
} }
static void stream_list_add_head(grpc_chttp2_transport *t,
grpc_chttp2_stream *s,
grpc_chttp2_stream_list_id id) {
grpc_chttp2_stream *old_head;
GPR_ASSERT(!s->included[id]);
old_head = t->lists[id].head;
s->links[id].next = old_head;
s->links[id].prev = NULL;
if (old_head) {
old_head->links[id].prev = s;
} else {
t->lists[id].tail = s;
}
t->lists[id].head = s;
s->included[id] = 1;
}
static void stream_list_add_tail(grpc_chttp2_transport *t, static void stream_list_add_tail(grpc_chttp2_transport *t,
grpc_chttp2_stream *s, grpc_chttp2_stream *s,
grpc_chttp2_stream_list_id id) { grpc_chttp2_stream_list_id id) {
@ -119,7 +136,6 @@ static void stream_list_add_tail(grpc_chttp2_transport *t,
if (old_tail) { if (old_tail) {
old_tail->links[id].next = s; old_tail->links[id].next = s;
} else { } else {
s->links[id].prev = NULL;
t->lists[id].head = s; t->lists[id].head = s;
} }
t->lists[id].tail = s; t->lists[id].tail = s;
@ -144,6 +160,18 @@ void grpc_chttp2_list_add_writable_stream(
STREAM_FROM_GLOBAL(stream_global), GRPC_CHTTP2_LIST_WRITABLE); STREAM_FROM_GLOBAL(stream_global), GRPC_CHTTP2_LIST_WRITABLE);
} }
void grpc_chttp2_list_add_first_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
GPR_ASSERT(stream_global->id != 0);
gpr_log(GPR_DEBUG, "add:%d:%d:%d:%d", stream_global->id,
stream_global->write_state, stream_global->in_stream_map,
stream_global->read_closed);
stream_list_add_head(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_WRITABLE);
}
int grpc_chttp2_list_pop_writable_stream( int grpc_chttp2_list_pop_writable_stream(
grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_writing *transport_writing, grpc_chttp2_transport_writing *transport_writing,
@ -157,6 +185,14 @@ int grpc_chttp2_list_pop_writable_stream(
return r; return r;
} }
void grpc_chttp2_list_remove_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_WRITABLE);
}
void grpc_chttp2_list_add_writing_stream( void grpc_chttp2_list_add_writing_stream(
grpc_chttp2_transport_writing *transport_writing, grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_writing *stream_writing) { grpc_chttp2_stream_writing *stream_writing) {
@ -202,36 +238,6 @@ int grpc_chttp2_list_pop_written_stream(
return r; return r;
} }
void grpc_chttp2_list_add_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
GPR_ASSERT(stream_global->id != 0);
stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_WRITABLE_WINDOW_UPDATE);
}
int grpc_chttp2_list_pop_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_writing **stream_writing) {
grpc_chttp2_stream *stream;
int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
GRPC_CHTTP2_LIST_WRITABLE_WINDOW_UPDATE);
*stream_global = &stream->global;
*stream_writing = &stream->writing;
return r;
}
void grpc_chttp2_list_remove_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_WRITABLE_WINDOW_UPDATE);
}
void grpc_chttp2_list_add_parsing_seen_stream( void grpc_chttp2_list_add_parsing_seen_stream(
grpc_chttp2_transport_parsing *transport_parsing, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing) { grpc_chttp2_stream_parsing *stream_parsing) {

@ -44,6 +44,7 @@ int grpc_chttp2_unlocking_check_writes(
grpc_chttp2_transport_writing *transport_writing) { grpc_chttp2_transport_writing *transport_writing) {
grpc_chttp2_stream_global *stream_global; grpc_chttp2_stream_global *stream_global;
grpc_chttp2_stream_writing *stream_writing; grpc_chttp2_stream_writing *stream_writing;
grpc_chttp2_stream_global *first_reinserted_stream = NULL;
gpr_uint32 window_delta; gpr_uint32 window_delta;
/* simple writes are queued to qbuf, and flushed here */ /* simple writes are queued to qbuf, and flushed here */
@ -64,21 +65,32 @@ int grpc_chttp2_unlocking_check_writes(
} }
/* for each grpc_chttp2_stream that's become writable, frame it's data /* for each grpc_chttp2_stream that's become writable, frame it's data
(according to (according to available window sizes) and add to the output buffer */
available window sizes) and add to the output buffer */ while (grpc_chttp2_list_pop_writable_stream(
while (grpc_chttp2_list_pop_writable_stream(transport_global, transport_global, transport_writing, &stream_global, &stream_writing)) {
transport_writing, &stream_global, if (stream_global == first_reinserted_stream) {
&stream_writing)) { /* prevent infinite loop */
grpc_chttp2_list_add_first_writable_stream(transport_global,
stream_global);
break;
}
stream_writing->id = stream_global->id; stream_writing->id = stream_global->id;
window_delta = grpc_chttp2_preencode( stream_writing->send_closed = GRPC_DONT_SEND_CLOSED;
stream_global->outgoing_sopb->ops, &stream_global->outgoing_sopb->nops, GPR_ASSERT(!stream_global->writing_now);
if (stream_global->outgoing_sopb) {
window_delta =
grpc_chttp2_preencode(stream_global->outgoing_sopb->ops,
&stream_global->outgoing_sopb->nops,
GPR_MIN(transport_global->outgoing_window, GPR_MIN(transport_global->outgoing_window,
stream_global->outgoing_window), stream_global->outgoing_window),
&stream_writing->sopb); &stream_writing->sopb);
GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT( GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
"write", transport_global, outgoing_window, -(gpr_int64)window_delta); "write", transport_global, outgoing_window, -(gpr_int64)window_delta);
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("write", transport_global, stream_global, GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("write", transport_global, stream_global,
outgoing_window, -(gpr_int64)window_delta); outgoing_window,
-(gpr_int64)window_delta);
transport_global->outgoing_window -= window_delta; transport_global->outgoing_window -= window_delta;
stream_global->outgoing_window -= window_delta; stream_global->outgoing_window -= window_delta;
@ -90,24 +102,17 @@ int grpc_chttp2_unlocking_check_writes(
stream_writing->send_closed = GRPC_SEND_CLOSED; stream_writing->send_closed = GRPC_SEND_CLOSED;
} }
} }
if (stream_writing->sopb.nops > 0 ||
stream_writing->send_closed != GRPC_DONT_SEND_CLOSED) {
grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
}
if (stream_global->outgoing_window > 0 && if (stream_global->outgoing_window > 0 &&
stream_global->outgoing_sopb->nops != 0) { stream_global->outgoing_sopb->nops != 0) {
grpc_chttp2_list_add_writable_stream(transport_global, stream_global); grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
if (first_reinserted_stream == NULL &&
transport_global->outgoing_window == 0) {
first_reinserted_stream = stream_global;
}
} }
} }
/* for each grpc_chttp2_stream that wants to update its window, add that
* window here */
while (grpc_chttp2_list_pop_writable_window_update_stream(transport_global,
transport_writing,
&stream_global,
&stream_writing)) {
stream_writing->id = stream_global->id;
if (!stream_global->read_closed && stream_global->unannounced_incoming_window > 0) { if (!stream_global->read_closed && stream_global->unannounced_incoming_window > 0) {
stream_writing->announce_window = stream_global->unannounced_incoming_window; stream_writing->announce_window = stream_global->unannounced_incoming_window;
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("write", transport_global, stream_global, GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("write", transport_global, stream_global,
@ -118,6 +123,11 @@ int grpc_chttp2_unlocking_check_writes(
stream_global->unannounced_incoming_window = 0; stream_global->unannounced_incoming_window = 0;
grpc_chttp2_list_add_incoming_window_updated(transport_global, grpc_chttp2_list_add_incoming_window_updated(transport_global,
stream_global); stream_global);
stream_global->writing_now = 1;
grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
} else if (stream_writing->sopb.nops > 0 ||
stream_writing->send_closed != GRPC_DONT_SEND_CLOSED) {
stream_global->writing_now = 1;
grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing); grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
} }
} }
@ -205,6 +215,8 @@ void grpc_chttp2_cleanup_writing(
while (grpc_chttp2_list_pop_written_stream( while (grpc_chttp2_list_pop_written_stream(
transport_global, transport_writing, &stream_global, &stream_writing)) { transport_global, transport_writing, &stream_global, &stream_writing)) {
GPR_ASSERT(stream_global->writing_now);
stream_global->writing_now = 0;
if (stream_global->outgoing_sopb != NULL && if (stream_global->outgoing_sopb != NULL &&
stream_global->outgoing_sopb->nops == 0) { stream_global->outgoing_sopb->nops == 0) {
stream_global->outgoing_sopb = NULL; stream_global->outgoing_sopb = NULL;
@ -216,10 +228,10 @@ void grpc_chttp2_cleanup_writing(
if (!transport_global->is_client) { if (!transport_global->is_client) {
stream_global->read_closed = 1; stream_global->read_closed = 1;
} }
}
grpc_chttp2_list_add_read_write_state_changed(transport_global, grpc_chttp2_list_add_read_write_state_changed(transport_global,
stream_global); stream_global);
} }
}
transport_writing->outbuf.count = 0; transport_writing->outbuf.count = 0;
transport_writing->outbuf.length = 0; transport_writing->outbuf.length = 0;
} }

@ -110,6 +110,8 @@ static void cancel_from_api(grpc_chttp2_transport_global *transport_global,
/** Add endpoint from this transport to pollset */ /** Add endpoint from this transport to pollset */
static void add_to_pollset_locked(grpc_chttp2_transport *t, static void add_to_pollset_locked(grpc_chttp2_transport *t,
grpc_pollset *pollset); grpc_pollset *pollset);
static void add_to_pollset_set_locked(grpc_chttp2_transport *t,
grpc_pollset_set *pollset_set);
/** Start new streams that have been created if we can */ /** Start new streams that have been created if we can */
static void maybe_start_some_streams( static void maybe_start_some_streams(
@ -117,7 +119,7 @@ static void maybe_start_some_streams(
static void connectivity_state_set( static void connectivity_state_set(
grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_global *transport_global,
grpc_connectivity_state state); grpc_connectivity_state state, const char *reason);
/* /*
* CONSTRUCTION/DESTRUCTION/REFCOUNTING * CONSTRUCTION/DESTRUCTION/REFCOUNTING
@ -168,6 +170,7 @@ static void destruct_transport(grpc_chttp2_transport *t) {
grpc_mdctx_unref(t->metadata_context); grpc_mdctx_unref(t->metadata_context);
gpr_free(t->peer_string);
gpr_free(t); gpr_free(t);
} }
@ -217,6 +220,7 @@ static void init_transport(grpc_chttp2_transport *t,
gpr_ref_init(&t->refs, 2); gpr_ref_init(&t->refs, 2);
gpr_mu_init(&t->mu); gpr_mu_init(&t->mu);
grpc_mdctx_ref(mdctx); grpc_mdctx_ref(mdctx);
t->peer_string = grpc_endpoint_get_peer(ep);
t->metadata_context = mdctx; t->metadata_context = mdctx;
t->endpoint_reading = 1; t->endpoint_reading = 1;
t->global.next_stream_id = is_client ? 1 : 2; t->global.next_stream_id = is_client ? 1 : 2;
@ -228,12 +232,12 @@ static void init_transport(grpc_chttp2_transport *t,
t->global.pings.next = t->global.pings.prev = &t->global.pings; t->global.pings.next = t->global.pings.prev = &t->global.pings;
t->parsing.is_client = is_client; t->parsing.is_client = is_client;
t->parsing.str_grpc_timeout = t->parsing.str_grpc_timeout =
grpc_mdstr_from_string(t->metadata_context, "grpc-timeout"); grpc_mdstr_from_string(t->metadata_context, "grpc-timeout", 0);
t->parsing.deframe_state = t->parsing.deframe_state =
is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0; is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0;
t->writing.is_client = is_client; t->writing.is_client = is_client;
grpc_connectivity_state_init(&t->channel_callback.state_tracker, grpc_connectivity_state_init(&t->channel_callback.state_tracker,
GRPC_CHANNEL_READY); GRPC_CHANNEL_READY, "transport");
gpr_slice_buffer_init(&t->global.qbuf); gpr_slice_buffer_init(&t->global.qbuf);
@ -327,7 +331,8 @@ static void destroy_transport(grpc_transport *gt) {
static void close_transport_locked(grpc_chttp2_transport *t) { static void close_transport_locked(grpc_chttp2_transport *t) {
if (!t->closed) { if (!t->closed) {
t->closed = 1; t->closed = 1;
connectivity_state_set(&t->global, GRPC_CHANNEL_FATAL_FAILURE); connectivity_state_set(&t->global, GRPC_CHANNEL_FATAL_FAILURE,
"close_transport");
if (t->ep) { if (t->ep) {
grpc_endpoint_shutdown(t->ep); grpc_endpoint_shutdown(t->ep);
} }
@ -393,12 +398,16 @@ static void destroy_stream(grpc_transport *gt, grpc_stream *gs) {
} }
grpc_chttp2_list_remove_incoming_window_updated(&t->global, &s->global); grpc_chttp2_list_remove_incoming_window_updated(&t->global, &s->global);
grpc_chttp2_list_remove_writable_window_update_stream(&t->global, &s->global); grpc_chttp2_list_remove_writable_stream(&t->global, &s->global);
gpr_mu_unlock(&t->mu); gpr_mu_unlock(&t->mu);
for (i = 0; i < STREAM_LIST_COUNT; i++) { for (i = 0; i < STREAM_LIST_COUNT; i++) {
GPR_ASSERT(!s->included[i]); if (s->included[i]) {
gpr_log(GPR_ERROR, "%s stream %d still included in list %d",
t->global.is_client ? "client" : "server", s->global.id, i);
abort();
}
} }
GPR_ASSERT(s->global.outgoing_sopb == NULL); GPR_ASSERT(s->global.outgoing_sopb == NULL);
@ -530,7 +539,8 @@ void grpc_chttp2_add_incoming_goaway(
gpr_free(msg); gpr_free(msg);
gpr_slice_unref(goaway_text); gpr_slice_unref(goaway_text);
transport_global->seen_goaway = 1; transport_global->seen_goaway = 1;
connectivity_state_set(transport_global, GRPC_CHANNEL_FATAL_FAILURE); connectivity_state_set(transport_global, GRPC_CHANNEL_FATAL_FAILURE,
"got_goaway");
} }
static void maybe_start_some_streams( static void maybe_start_some_streams(
@ -555,7 +565,8 @@ static void maybe_start_some_streams(
transport_global->next_stream_id += 2; transport_global->next_stream_id += 2;
if (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID) { if (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID) {
connectivity_state_set(transport_global, GRPC_CHANNEL_TRANSIENT_FAILURE); connectivity_state_set(transport_global, GRPC_CHANNEL_TRANSIENT_FAILURE,
"no_more_stream_ids");
} }
stream_global->outgoing_window = stream_global->outgoing_window =
@ -574,8 +585,6 @@ static void maybe_start_some_streams(
grpc_chttp2_list_add_incoming_window_updated(transport_global, grpc_chttp2_list_add_incoming_window_updated(transport_global,
stream_global); stream_global);
grpc_chttp2_list_add_writable_stream(transport_global, stream_global); grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
grpc_chttp2_list_add_writable_window_update_stream(transport_global,
stream_global);
} }
/* cancel out streams that will never be started */ /* cancel out streams that will never be started */
@ -641,8 +650,7 @@ static void perform_stream_op_locked(
if (stream_global->id != 0) { if (stream_global->id != 0) {
grpc_chttp2_list_add_read_write_state_changed(transport_global, grpc_chttp2_list_add_read_write_state_changed(transport_global,
stream_global); stream_global);
grpc_chttp2_list_add_writable_window_update_stream(transport_global, grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
stream_global);
} }
} }
@ -686,6 +694,7 @@ static void send_ping_locked(grpc_chttp2_transport *t,
static void perform_transport_op(grpc_transport *gt, grpc_transport_op *op) { static void perform_transport_op(grpc_transport *gt, grpc_transport_op *op) {
grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
int close_transport = 0;
lock(t); lock(t);
@ -705,9 +714,7 @@ static void perform_transport_op(grpc_transport *gt, grpc_transport_op *op) {
t->global.last_incoming_stream_id, t->global.last_incoming_stream_id,
grpc_chttp2_grpc_status_to_http2_error(op->goaway_status), grpc_chttp2_grpc_status_to_http2_error(op->goaway_status),
gpr_slice_ref(*op->goaway_message), &t->global.qbuf); gpr_slice_ref(*op->goaway_message), &t->global.qbuf);
if (!grpc_chttp2_has_streams(t)) { close_transport = !grpc_chttp2_has_streams(t);
close_transport_locked(t);
}
} }
if (op->set_accept_stream != NULL) { if (op->set_accept_stream != NULL) {
@ -720,6 +727,10 @@ static void perform_transport_op(grpc_transport *gt, grpc_transport_op *op) {
add_to_pollset_locked(t, op->bind_pollset); add_to_pollset_locked(t, op->bind_pollset);
} }
if (op->bind_pollset_set) {
add_to_pollset_set_locked(t, op->bind_pollset_set);
}
if (op->send_ping) { if (op->send_ping) {
send_ping_locked(t, op->send_ping); send_ping_locked(t, op->send_ping);
} }
@ -729,6 +740,12 @@ static void perform_transport_op(grpc_transport *gt, grpc_transport_op *op) {
} }
unlock(t); unlock(t);
if (close_transport) {
lock(t);
close_transport_locked(t);
unlock(t);
}
} }
/* /*
@ -750,6 +767,7 @@ static void remove_stream(grpc_chttp2_transport *t, gpr_uint32 id) {
if (!s) { if (!s) {
s = grpc_chttp2_stream_map_delete(&t->new_stream_map, id); s = grpc_chttp2_stream_map_delete(&t->new_stream_map, id);
} }
grpc_chttp2_list_remove_writable_stream(&t->global, &s->global);
GPR_ASSERT(s); GPR_ASSERT(s);
s->global.in_stream_map = 0; s->global.in_stream_map = 0;
if (t->parsing.incoming_stream == &s->parsing) { if (t->parsing.incoming_stream == &s->parsing) {
@ -831,6 +849,9 @@ static void unlock_check_read_write_state(grpc_chttp2_transport *t) {
if (!stream_global->publish_sopb) { if (!stream_global->publish_sopb) {
continue; continue;
} }
if (stream_global->writing_now) {
continue;
}
/* FIXME(ctiller): we include in_stream_map in our computation of /* FIXME(ctiller): we include in_stream_map in our computation of
whether the stream is write-closed. This is completely bogus, whether the stream is write-closed. This is completely bogus,
but has the effect of delaying stream-closed until the stream but has the effect of delaying stream-closed until the stream
@ -1001,12 +1022,12 @@ static void schedule_closure_for_connectivity(void *a,
static void connectivity_state_set( static void connectivity_state_set(
grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_global *transport_global,
grpc_connectivity_state state) { grpc_connectivity_state state, const char *reason) {
GRPC_CHTTP2_IF_TRACING( GRPC_CHTTP2_IF_TRACING(
gpr_log(GPR_DEBUG, "set connectivity_state=%d", state)); gpr_log(GPR_DEBUG, "set connectivity_state=%d", state));
grpc_connectivity_state_set_with_scheduler( grpc_connectivity_state_set_with_scheduler(
&TRANSPORT_FROM_GLOBAL(transport_global)->channel_callback.state_tracker, &TRANSPORT_FROM_GLOBAL(transport_global)->channel_callback.state_tracker,
state, schedule_closure_for_connectivity, transport_global); state, schedule_closure_for_connectivity, transport_global, reason);
} }
void grpc_chttp2_schedule_closure( void grpc_chttp2_schedule_closure(
@ -1034,6 +1055,13 @@ static void add_to_pollset_locked(grpc_chttp2_transport *t,
} }
} }
static void add_to_pollset_set_locked(grpc_chttp2_transport *t,
grpc_pollset_set *pollset_set) {
if (t->ep) {
grpc_endpoint_add_to_pollset_set(t->ep, pollset_set);
}
}
/* /*
* TRACING * TRACING
*/ */
@ -1069,9 +1097,17 @@ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *reason,
* INTEGRATION GLUE * INTEGRATION GLUE
*/ */
static const grpc_transport_vtable vtable = { static char *chttp2_get_peer(grpc_transport *t) {
sizeof(grpc_chttp2_stream), init_stream, perform_stream_op, return gpr_strdup(((grpc_chttp2_transport *)t)->peer_string);
perform_transport_op, destroy_stream, destroy_transport}; }
static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream),
init_stream,
perform_stream_op,
perform_transport_op,
destroy_stream,
destroy_transport,
chttp2_get_peer};
grpc_transport *grpc_create_chttp2_transport( grpc_transport *grpc_create_chttp2_transport(
const grpc_channel_args *channel_args, grpc_endpoint *ep, grpc_mdctx *mdctx, const grpc_channel_args *channel_args, grpc_endpoint *ep, grpc_mdctx *mdctx,

@ -34,11 +34,33 @@
#include "src/core/transport/connectivity_state.h" #include "src/core/transport/connectivity_state.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h>
int grpc_connectivity_state_trace = 0;
const char *grpc_connectivity_state_name(grpc_connectivity_state state) {
switch (state) {
case GRPC_CHANNEL_IDLE:
return "IDLE";
case GRPC_CHANNEL_CONNECTING:
return "CONNECTING";
case GRPC_CHANNEL_READY:
return "READY";
case GRPC_CHANNEL_TRANSIENT_FAILURE:
return "TRANSIENT_FAILURE";
case GRPC_CHANNEL_FATAL_FAILURE:
return "FATAL_FAILURE";
}
abort();
return "UNKNOWN";
}
void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker, void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker,
grpc_connectivity_state init_state) { grpc_connectivity_state init_state,
const char *name) {
tracker->current_state = init_state; tracker->current_state = init_state;
tracker->watchers = NULL; tracker->watchers = NULL;
tracker->name = gpr_strdup(name);
} }
void grpc_connectivity_state_destroy(grpc_connectivity_state_tracker *tracker) { void grpc_connectivity_state_destroy(grpc_connectivity_state_tracker *tracker) {
@ -54,6 +76,7 @@ void grpc_connectivity_state_destroy(grpc_connectivity_state_tracker *tracker) {
} }
gpr_free(w); gpr_free(w);
} }
gpr_free(tracker->name);
} }
grpc_connectivity_state grpc_connectivity_state_check( grpc_connectivity_state grpc_connectivity_state_check(
@ -64,6 +87,11 @@ grpc_connectivity_state grpc_connectivity_state_check(
int grpc_connectivity_state_notify_on_state_change( int grpc_connectivity_state_notify_on_state_change(
grpc_connectivity_state_tracker *tracker, grpc_connectivity_state *current, grpc_connectivity_state_tracker *tracker, grpc_connectivity_state *current,
grpc_iomgr_closure *notify) { grpc_iomgr_closure *notify) {
if (grpc_connectivity_state_trace) {
gpr_log(GPR_DEBUG, "CONWATCH: %s: from %s [cur=%s]", tracker->name,
grpc_connectivity_state_name(*current),
grpc_connectivity_state_name(tracker->current_state));
}
if (tracker->current_state != *current) { if (tracker->current_state != *current) {
*current = tracker->current_state; *current = tracker->current_state;
grpc_iomgr_add_callback(notify); grpc_iomgr_add_callback(notify);
@ -79,12 +107,19 @@ int grpc_connectivity_state_notify_on_state_change(
void grpc_connectivity_state_set_with_scheduler( void grpc_connectivity_state_set_with_scheduler(
grpc_connectivity_state_tracker *tracker, grpc_connectivity_state state, grpc_connectivity_state_tracker *tracker, grpc_connectivity_state state,
void (*scheduler)(void *arg, grpc_iomgr_closure *closure), void *arg) { void (*scheduler)(void *arg, grpc_iomgr_closure *closure), void *arg,
const char *reason) {
grpc_connectivity_state_watcher *new = NULL; grpc_connectivity_state_watcher *new = NULL;
grpc_connectivity_state_watcher *w; grpc_connectivity_state_watcher *w;
if (grpc_connectivity_state_trace) {
gpr_log(GPR_DEBUG, "SET: %s: %s --> %s [%s]", tracker->name,
grpc_connectivity_state_name(tracker->current_state),
grpc_connectivity_state_name(state), reason);
}
if (tracker->current_state == state) { if (tracker->current_state == state) {
return; return;
} }
GPR_ASSERT(tracker->current_state != GRPC_CHANNEL_FATAL_FAILURE);
tracker->current_state = state; tracker->current_state = state;
while ((w = tracker->watchers)) { while ((w = tracker->watchers)) {
tracker->watchers = w->next; tracker->watchers = w->next;
@ -106,7 +141,8 @@ static void default_scheduler(void *ignored, grpc_iomgr_closure *closure) {
} }
void grpc_connectivity_state_set(grpc_connectivity_state_tracker *tracker, void grpc_connectivity_state_set(grpc_connectivity_state_tracker *tracker,
grpc_connectivity_state state) { grpc_connectivity_state state,
const char *reason) {
grpc_connectivity_state_set_with_scheduler(tracker, state, default_scheduler, grpc_connectivity_state_set_with_scheduler(tracker, state, default_scheduler,
NULL); NULL, reason);
} }

@ -51,17 +51,24 @@ typedef struct {
grpc_connectivity_state current_state; grpc_connectivity_state current_state;
/** all our watchers */ /** all our watchers */
grpc_connectivity_state_watcher *watchers; grpc_connectivity_state_watcher *watchers;
/** a name to help debugging */
char *name;
} grpc_connectivity_state_tracker; } grpc_connectivity_state_tracker;
extern int grpc_connectivity_state_trace;
void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker, void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker,
grpc_connectivity_state init_state); grpc_connectivity_state init_state,
const char *name);
void grpc_connectivity_state_destroy(grpc_connectivity_state_tracker *tracker); void grpc_connectivity_state_destroy(grpc_connectivity_state_tracker *tracker);
void grpc_connectivity_state_set(grpc_connectivity_state_tracker *tracker, void grpc_connectivity_state_set(grpc_connectivity_state_tracker *tracker,
grpc_connectivity_state state); grpc_connectivity_state state,
const char *reason);
void grpc_connectivity_state_set_with_scheduler( void grpc_connectivity_state_set_with_scheduler(
grpc_connectivity_state_tracker *tracker, grpc_connectivity_state state, grpc_connectivity_state_tracker *tracker, grpc_connectivity_state state,
void (*scheduler)(void *arg, grpc_iomgr_closure *closure), void *arg); void (*scheduler)(void *arg, grpc_iomgr_closure *closure), void *arg,
const char *reason);
grpc_connectivity_state grpc_connectivity_state_check( grpc_connectivity_state grpc_connectivity_state_check(
grpc_connectivity_state_tracker *tracker); grpc_connectivity_state_tracker *tracker);

@ -309,7 +309,37 @@ static void slice_unref(void *p) {
unlock(ctx); unlock(ctx);
} }
grpc_mdstr *grpc_mdstr_from_string(grpc_mdctx *ctx, const char *str) { grpc_mdstr *grpc_mdstr_from_string(grpc_mdctx *ctx, const char *str, int canonicalize_key) {
if (canonicalize_key) {
size_t len;
size_t i;
int canonical = 1;
for (i = 0; str[i]; i++) {
if (str[i] >= 'A' && str[i] <= 'Z') {
canonical = 0;
/* Keep going in loop just to get string length */
}
}
len = i;
if (canonical) {
return grpc_mdstr_from_buffer(ctx, (const gpr_uint8 *)str, len);
} else {
char *copy = gpr_malloc(len);
grpc_mdstr *ret;
for (i = 0; i < len; i++) {
if (str[i] >= 'A' && str[i] <= 'Z') {
copy[i] = str[i] - 'A' + 'a';
} else {
copy[i] = str[i];
}
}
ret = grpc_mdstr_from_buffer(ctx, (const gpr_uint8 *)copy, len);
gpr_free(copy);
return ret;
}
}
return grpc_mdstr_from_buffer(ctx, (const gpr_uint8 *)str, strlen(str)); return grpc_mdstr_from_buffer(ctx, (const gpr_uint8 *)str, strlen(str));
} }
@ -491,8 +521,8 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdctx *ctx,
grpc_mdelem *grpc_mdelem_from_strings(grpc_mdctx *ctx, const char *key, grpc_mdelem *grpc_mdelem_from_strings(grpc_mdctx *ctx, const char *key,
const char *value) { const char *value) {
return grpc_mdelem_from_metadata_strings(ctx, return grpc_mdelem_from_metadata_strings(ctx,
grpc_mdstr_from_string(ctx, key), grpc_mdstr_from_string(ctx, key, 0),
grpc_mdstr_from_string(ctx, value)); grpc_mdstr_from_string(ctx, value, 0));
} }
grpc_mdelem *grpc_mdelem_from_slices(grpc_mdctx *ctx, gpr_slice key, grpc_mdelem *grpc_mdelem_from_slices(grpc_mdctx *ctx, gpr_slice key,
@ -504,9 +534,10 @@ grpc_mdelem *grpc_mdelem_from_slices(grpc_mdctx *ctx, gpr_slice key,
grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_mdctx *ctx, grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_mdctx *ctx,
const char *key, const char *key,
const gpr_uint8 *value, const gpr_uint8 *value,
size_t value_length) { size_t value_length,
int canonicalize_key) {
return grpc_mdelem_from_metadata_strings( return grpc_mdelem_from_metadata_strings(
ctx, grpc_mdstr_from_string(ctx, key), ctx, grpc_mdstr_from_string(ctx, key, canonicalize_key),
grpc_mdstr_from_buffer(ctx, value, value_length)); grpc_mdstr_from_buffer(ctx, value, value_length));
} }

@ -95,7 +95,7 @@ size_t grpc_mdctx_get_mdtab_free_test_only(grpc_mdctx *mdctx);
/* Constructors for grpc_mdstr instances; take a variety of data types that /* Constructors for grpc_mdstr instances; take a variety of data types that
clients may have handy */ clients may have handy */
grpc_mdstr *grpc_mdstr_from_string(grpc_mdctx *ctx, const char *str); grpc_mdstr *grpc_mdstr_from_string(grpc_mdctx *ctx, const char *str, int perform_key_canonicalization);
/* Unrefs the slice. */ /* Unrefs the slice. */
grpc_mdstr *grpc_mdstr_from_slice(grpc_mdctx *ctx, gpr_slice slice); grpc_mdstr *grpc_mdstr_from_slice(grpc_mdctx *ctx, gpr_slice slice);
grpc_mdstr *grpc_mdstr_from_buffer(grpc_mdctx *ctx, const gpr_uint8 *str, grpc_mdstr *grpc_mdstr_from_buffer(grpc_mdctx *ctx, const gpr_uint8 *str,
@ -117,7 +117,8 @@ grpc_mdelem *grpc_mdelem_from_slices(grpc_mdctx *ctx, gpr_slice key,
grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_mdctx *ctx, grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_mdctx *ctx,
const char *key, const char *key,
const gpr_uint8 *value, const gpr_uint8 *value,
size_t value_length); size_t value_length,
int canonicalize_key);
/* Mutator and accessor for grpc_mdelem user data. The destructor function /* Mutator and accessor for grpc_mdelem user data. The destructor function
is used as a type tag and is checked during user_data fetch. */ is used as a type tag and is checked during user_data fetch. */

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

Loading…
Cancel
Save