Prechádzať zdrojové kódy

Merge github.com:grpc/grpc into poffy

Craig Tiller 9 rokov pred
rodič
commit
8032828dff
100 zmenil súbory, kde vykonal 1239 pridanie a 1164 odobranie
  1. 8 21
      BUILD
  2. 254 28
      Makefile
  3. 16 22
      README.md
  4. 1 3
      binding.gyp
  5. 174 24
      build.yaml
  6. 1 1
      doc/PROTOCOL-HTTP2.md
  7. 0 289
      doc/grpc-auth-support.md
  8. 14 14
      examples/cpp/helloworld/README.md
  9. 1 1
      examples/objective-c/auth_sample/AuthTestService.podspec
  10. 1 0
      examples/objective-c/auth_sample/Podfile
  11. 1 1
      examples/objective-c/helloworld/HelloWorld.podspec
  12. 1 0
      examples/objective-c/helloworld/Podfile
  13. 1 0
      examples/objective-c/route_guide/Podfile
  14. 1 1
      examples/objective-c/route_guide/RouteGuide.podspec
  15. 3 11
      gRPC.podspec
  16. 12 1
      include/grpc++/client_context.h
  17. 6 1
      include/grpc++/impl/rpc_service_method.h
  18. 15 10
      include/grpc++/impl/server_builder_option.h
  19. 10 1
      include/grpc++/security/credentials.h
  20. 21 2
      include/grpc++/server.h
  21. 5 1
      include/grpc++/server_builder.h
  22. 5 0
      include/grpc++/support/channel_arguments.h
  23. 0 6
      include/grpc/compression.h
  24. 5 0
      include/grpc/grpc.h
  25. 99 78
      include/grpc/grpc_security.h
  26. 14 0
      include/grpc/support/alloc.h
  27. 6 2
      include/grpc/support/cmdline.h
  28. 7 2
      include/grpc/support/port_platform.h
  29. 2 2
      include/grpc/support/time.h
  30. 3 2
      package.json
  31. 3 5
      src/core/census/context.h
  32. 4 2
      src/core/census/grpc_filter.c
  33. 16 1
      src/core/channel/client_channel.c
  34. 2 2
      src/core/channel/compress_filter.c
  35. 2 2
      src/core/channel/http_client_filter.c
  36. 1 2
      src/core/channel/http_server_filter.c
  37. 0 118
      src/core/channel/noop_filter.c
  38. 2 2
      src/core/channel/subchannel_call_holder.c
  39. 13 1
      src/core/client_config/lb_policies/pick_first.c
  40. 17 1
      src/core/client_config/lb_policies/round_robin.c
  41. 5 0
      src/core/client_config/lb_policy.c
  42. 6 0
      src/core/client_config/lb_policy.h
  43. 0 1
      src/core/client_config/resolvers/dns_resolver.c
  44. 3 0
      src/core/client_config/resolvers/sockaddr_resolver.c
  45. 2 5
      src/core/client_config/resolvers/zookeeper_resolver.c
  46. 11 0
      src/core/client_config/subchannel.c
  47. 3 0
      src/core/client_config/subchannel.h
  48. 0 86
      src/core/client_config/subchannel_factory_decorators/merge_channel_args.c
  49. 0 46
      src/core/client_config/subchannel_factory_decorators/merge_channel_args.h
  50. 4 20
      src/core/compression/algorithm.c
  51. 16 12
      src/core/compression/message_compress.c
  52. 7 2
      src/core/httpcli/httpcli.c
  53. 2 0
      src/core/httpcli/httpcli.h
  54. 2 3
      src/core/httpcli/httpcli_security_connector.c
  55. 3 0
      src/core/iomgr/endpoint_pair_posix.c
  56. 13 4
      src/core/iomgr/fd_posix.c
  57. 3 1
      src/core/iomgr/fd_posix.h
  58. 0 1
      src/core/iomgr/iomgr.c
  59. 1 21
      src/core/iomgr/pollset_multipoller_with_epoll.c
  60. 1 18
      src/core/iomgr/pollset_multipoller_with_poll_posix.c
  61. 6 32
      src/core/iomgr/pollset_posix.c
  62. 0 6
      src/core/iomgr/pollset_posix.h
  63. 2 2
      src/core/iomgr/tcp_client_posix.c
  64. 15 1
      src/core/iomgr/tcp_posix.c
  65. 6 0
      src/core/iomgr/tcp_posix.h
  66. 11 9
      src/core/iomgr/tcp_server_posix.c
  67. 6 2
      src/core/iomgr/tcp_server_windows.c
  68. 9 5
      src/core/iomgr/tcp_windows.c
  69. 2 10
      src/core/iomgr/timer.c
  70. 0 2
      src/core/iomgr/timer_internal.h
  71. 3 1
      src/core/iomgr/udp_server.c
  72. 3 5
      src/core/iomgr/wakeup_fd_posix.c
  73. 2 0
      src/core/iomgr/wakeup_fd_posix.h
  74. 4 1
      src/core/iomgr/workqueue_posix.c
  75. 8 7
      src/core/json/json_reader.c
  76. 1 1
      src/core/json/json_string.c
  77. 4 3
      src/core/profiling/basic_timers.c
  78. 36 18
      src/core/security/client_auth_filter.c
  79. 47 56
      src/core/security/credentials.c
  80. 14 8
      src/core/security/credentials.h
  81. 1 1
      src/core/security/credentials_posix.c
  82. 1 1
      src/core/security/credentials_win32.c
  83. 15 0
      src/core/security/google_default_credentials.c
  84. 45 4
      src/core/security/handshake.c
  85. 2 0
      src/core/security/handshake.h
  86. 2 2
      src/core/security/json_token.c
  87. 24 3
      src/core/security/security_connector.c
  88. 13 1
      src/core/security/security_connector.h
  89. 17 61
      src/core/security/server_secure_chttp2.c
  90. 1 1
      src/core/statistics/window_stats.c
  91. 17 3
      src/core/support/alloc.c
  92. 43 19
      src/core/support/cmdline.c
  93. 2 1
      src/core/support/log.c
  94. 3 1
      src/core/support/log_linux.c
  95. 3 1
      src/core/support/log_posix.c
  96. 3 1
      src/core/support/log_win32.c
  97. 0 7
      src/core/support/slice.c
  98. 4 4
      src/core/support/stack_lockfree.c
  99. 25 4
      src/core/support/string.c
  100. 10 0
      src/core/support/string.h

+ 8 - 21
BUILD

@@ -161,7 +161,6 @@ cc_library(
     "src/core/channel/context.h",
     "src/core/channel/http_client_filter.h",
     "src/core/channel/http_server_filter.h",
-    "src/core/channel/noop_filter.h",
     "src/core/channel/subchannel_call_holder.h",
     "src/core/client_config/client_config.h",
     "src/core/client_config/connector.h",
@@ -178,8 +177,6 @@ cc_library(
     "src/core/client_config/resolvers/sockaddr_resolver.h",
     "src/core/client_config/subchannel.h",
     "src/core/client_config/subchannel_factory.h",
-    "src/core/client_config/subchannel_factory_decorators/add_channel_arg.h",
-    "src/core/client_config/subchannel_factory_decorators/merge_channel_args.h",
     "src/core/client_config/uri_parser.h",
     "src/core/compression/algorithm_metadata.h",
     "src/core/compression/message_compress.h",
@@ -301,7 +298,6 @@ cc_library(
     "src/core/channel/connected_channel.c",
     "src/core/channel/http_client_filter.c",
     "src/core/channel/http_server_filter.c",
-    "src/core/channel/noop_filter.c",
     "src/core/channel/subchannel_call_holder.c",
     "src/core/client_config/client_config.c",
     "src/core/client_config/connector.c",
@@ -319,8 +315,6 @@ cc_library(
     "src/core/client_config/resolvers/sockaddr_resolver.c",
     "src/core/client_config/subchannel.c",
     "src/core/client_config/subchannel_factory.c",
-    "src/core/client_config/subchannel_factory_decorators/add_channel_arg.c",
-    "src/core/client_config/subchannel_factory_decorators/merge_channel_args.c",
     "src/core/client_config/uri_parser.c",
     "src/core/compression/algorithm.c",
     "src/core/compression/message_compress.c",
@@ -381,6 +375,7 @@ cc_library(
     "src/core/surface/channel.c",
     "src/core/surface/channel_connectivity.c",
     "src/core/surface/channel_create.c",
+    "src/core/surface/channel_ping.c",
     "src/core/surface/completion_queue.c",
     "src/core/surface/event_string.c",
     "src/core/surface/init.c",
@@ -457,7 +452,6 @@ cc_library(
     "src/core/channel/context.h",
     "src/core/channel/http_client_filter.h",
     "src/core/channel/http_server_filter.h",
-    "src/core/channel/noop_filter.h",
     "src/core/channel/subchannel_call_holder.h",
     "src/core/client_config/client_config.h",
     "src/core/client_config/connector.h",
@@ -474,8 +468,6 @@ cc_library(
     "src/core/client_config/resolvers/sockaddr_resolver.h",
     "src/core/client_config/subchannel.h",
     "src/core/client_config/subchannel_factory.h",
-    "src/core/client_config/subchannel_factory_decorators/add_channel_arg.h",
-    "src/core/client_config/subchannel_factory_decorators/merge_channel_args.h",
     "src/core/client_config/uri_parser.h",
     "src/core/compression/algorithm_metadata.h",
     "src/core/compression/message_compress.h",
@@ -577,7 +569,6 @@ cc_library(
     "src/core/channel/connected_channel.c",
     "src/core/channel/http_client_filter.c",
     "src/core/channel/http_server_filter.c",
-    "src/core/channel/noop_filter.c",
     "src/core/channel/subchannel_call_holder.c",
     "src/core/client_config/client_config.c",
     "src/core/client_config/connector.c",
@@ -595,8 +586,6 @@ cc_library(
     "src/core/client_config/resolvers/sockaddr_resolver.c",
     "src/core/client_config/subchannel.c",
     "src/core/client_config/subchannel_factory.c",
-    "src/core/client_config/subchannel_factory_decorators/add_channel_arg.c",
-    "src/core/client_config/subchannel_factory_decorators/merge_channel_args.c",
     "src/core/client_config/uri_parser.c",
     "src/core/compression/algorithm.c",
     "src/core/compression/message_compress.c",
@@ -657,6 +646,7 @@ cc_library(
     "src/core/surface/channel.c",
     "src/core/surface/channel_connectivity.c",
     "src/core/surface/channel_create.c",
+    "src/core/surface/channel_ping.c",
     "src/core/surface/completion_queue.c",
     "src/core/surface/event_string.c",
     "src/core/surface/init.c",
@@ -748,14 +738,13 @@ cc_library(
     "src/cpp/server/dynamic_thread_pool.h",
     "src/cpp/server/fixed_size_thread_pool.h",
     "src/cpp/server/thread_pool_interface.h",
-    "src/cpp/client/secure_channel_arguments.cc",
     "src/cpp/client/secure_credentials.cc",
     "src/cpp/common/auth_property_iterator.cc",
     "src/cpp/common/secure_auth_context.cc",
+    "src/cpp/common/secure_channel_arguments.cc",
     "src/cpp/common/secure_create_auth_context.cc",
     "src/cpp/server/secure_server_credentials.cc",
     "src/cpp/client/channel.cc",
-    "src/cpp/client/channel_arguments.cc",
     "src/cpp/client/client_context.cc",
     "src/cpp/client/create_channel.cc",
     "src/cpp/client/create_channel_internal.cc",
@@ -763,6 +752,7 @@ cc_library(
     "src/cpp/client/generic_stub.cc",
     "src/cpp/client/insecure_credentials.cc",
     "src/cpp/common/call.cc",
+    "src/cpp/common/channel_arguments.cc",
     "src/cpp/common/completion_queue.cc",
     "src/cpp/common/rpc_method.cc",
     "src/cpp/proto/proto_utils.cc",
@@ -796,6 +786,7 @@ cc_library(
     "include/grpc++/impl/rpc_method.h",
     "include/grpc++/impl/rpc_service_method.h",
     "include/grpc++/impl/serialization_traits.h",
+    "include/grpc++/impl/server_builder_option.h",
     "include/grpc++/impl/service_type.h",
     "include/grpc++/impl/sync.h",
     "include/grpc++/impl/sync_cxx11.h",
@@ -847,7 +838,6 @@ cc_library(
     "src/cpp/server/thread_pool_interface.h",
     "src/cpp/common/insecure_create_auth_context.cc",
     "src/cpp/client/channel.cc",
-    "src/cpp/client/channel_arguments.cc",
     "src/cpp/client/client_context.cc",
     "src/cpp/client/create_channel.cc",
     "src/cpp/client/create_channel_internal.cc",
@@ -855,6 +845,7 @@ cc_library(
     "src/cpp/client/generic_stub.cc",
     "src/cpp/client/insecure_credentials.cc",
     "src/cpp/common/call.cc",
+    "src/cpp/common/channel_arguments.cc",
     "src/cpp/common/completion_queue.cc",
     "src/cpp/common/rpc_method.cc",
     "src/cpp/proto/proto_utils.cc",
@@ -888,6 +879,7 @@ cc_library(
     "include/grpc++/impl/rpc_method.h",
     "include/grpc++/impl/rpc_service_method.h",
     "include/grpc++/impl/serialization_traits.h",
+    "include/grpc++/impl/server_builder_option.h",
     "include/grpc++/impl/service_type.h",
     "include/grpc++/impl/sync.h",
     "include/grpc++/impl/sync_cxx11.h",
@@ -1111,7 +1103,6 @@ objc_library(
     "src/core/channel/connected_channel.c",
     "src/core/channel/http_client_filter.c",
     "src/core/channel/http_server_filter.c",
-    "src/core/channel/noop_filter.c",
     "src/core/channel/subchannel_call_holder.c",
     "src/core/client_config/client_config.c",
     "src/core/client_config/connector.c",
@@ -1129,8 +1120,6 @@ objc_library(
     "src/core/client_config/resolvers/sockaddr_resolver.c",
     "src/core/client_config/subchannel.c",
     "src/core/client_config/subchannel_factory.c",
-    "src/core/client_config/subchannel_factory_decorators/add_channel_arg.c",
-    "src/core/client_config/subchannel_factory_decorators/merge_channel_args.c",
     "src/core/client_config/uri_parser.c",
     "src/core/compression/algorithm.c",
     "src/core/compression/message_compress.c",
@@ -1191,6 +1180,7 @@ objc_library(
     "src/core/surface/channel.c",
     "src/core/surface/channel_connectivity.c",
     "src/core/surface/channel_create.c",
+    "src/core/surface/channel_ping.c",
     "src/core/surface/completion_queue.c",
     "src/core/surface/event_string.c",
     "src/core/surface/init.c",
@@ -1264,7 +1254,6 @@ objc_library(
     "src/core/channel/context.h",
     "src/core/channel/http_client_filter.h",
     "src/core/channel/http_server_filter.h",
-    "src/core/channel/noop_filter.h",
     "src/core/channel/subchannel_call_holder.h",
     "src/core/client_config/client_config.h",
     "src/core/client_config/connector.h",
@@ -1281,8 +1270,6 @@ objc_library(
     "src/core/client_config/resolvers/sockaddr_resolver.h",
     "src/core/client_config/subchannel.h",
     "src/core/client_config/subchannel_factory.h",
-    "src/core/client_config/subchannel_factory_decorators/add_channel_arg.h",
-    "src/core/client_config/subchannel_factory_decorators/merge_channel_args.h",
     "src/core/client_config/uri_parser.h",
     "src/core/compression/algorithm_metadata.h",
     "src/core/compression/message_compress.h",

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 254 - 28
Makefile


+ 16 - 22
README.md

@@ -13,34 +13,28 @@ You can find more detailed documentation and examples in the [doc](doc) and [exa
 
 See grpc/INSTALL for installation instructions for various platforms.
 
-#Repository Structure
+#Repository Structure & Status
 
-This repository contains source code for gRPC libraries for multiple languages written on top
-of shared C core library [src/core] (src/core).
+This repository contains source code for gRPC libraries for multiple languages written on top of shared C core library [src/core] (src/core).
 
-   * C++ source code: [src/cpp] (src/cpp)
-   * Ruby source code: [src/ruby] (src/ruby)
-   * NodeJS source code: [src/node] (src/node)
-   * Python source code: [src/python] (src/python)
-   * PHP source code: [src/php] (src/php)
-   * C# source code: [src/csharp] (src/csharp)
-   * Objective-C source code: [src/objective-c] (src/objective-c)
+Libraries in different languages are in different state of development. We are seeking contributions for all of these libraries.
 
+| Language                | Source                              | Status                          |
+|-------------------------|-------------------------------------|---------------------------------|
+| Shared C [core library] | [src/core] (src/core)               | Beta - the surface API is stable |
+| C++                     | [src/cpp] (src/cpp)                 | Beta - the surface API is stable |
+| Ruby                    | [src/ruby] (src/ruby)               | Beta - the surface API is stable |
+| NodeJS                  | [src/node] (src/node)               | Beta - the surface API is stable |
+| Python                  | [src/python] (src/python)           | Beta - the surface API is stable |
+| PHP                     | [src/php] (src/php)                 | Beta - the surface API is stable |
+| C#                      | [src/csharp] (src/csharp)           | Beta - the surface API is stable |
+| Objective-C             | [src/objective-c] (src/objective-c) | Beta - the surface API is stable |
+
+<small>
 Java source code is in [grpc-java] (http://github.com/grpc/grpc-java) repository.
 Go source code is in [grpc-go] (http://github.com/grpc/grpc-go) repository.
+</small>
 
-#Current Status of libraries
-
-Libraries in different languages are in different state of development. We are seeking contributions for all of these libraries.
-
-   * shared C core library [src/core] (src/core) : Beta - the surface API is stable
-   * C++ Library: [src/cpp] (src/cpp) : Beta - the surface API is stable
-   * Ruby Library: [src/ruby] (src/ruby) : Beta - the surface API is stable
-   * NodeJS Library: [src/node] (src/node) : Beta - the surface API is stable
-   * Python Library: [src/python] (src/python) : Beta - the surface API is stable
-   * C# Library: [src/csharp] (src/csharp) : Beta - the surface API is stable
-   * Objective-C Library: [src/objective-c] (src/objective-c): Beta - the surface API is stable
-   * PHP Library: [src/php] (src/php) : Beta - the surface API is stable
 
 #Overview
 

+ 1 - 3
binding.gyp

@@ -183,7 +183,6 @@
         'src/core/channel/connected_channel.c',
         'src/core/channel/http_client_filter.c',
         'src/core/channel/http_server_filter.c',
-        'src/core/channel/noop_filter.c',
         'src/core/channel/subchannel_call_holder.c',
         'src/core/client_config/client_config.c',
         'src/core/client_config/connector.c',
@@ -201,8 +200,6 @@
         'src/core/client_config/resolvers/sockaddr_resolver.c',
         'src/core/client_config/subchannel.c',
         'src/core/client_config/subchannel_factory.c',
-        'src/core/client_config/subchannel_factory_decorators/add_channel_arg.c',
-        'src/core/client_config/subchannel_factory_decorators/merge_channel_args.c',
         'src/core/client_config/uri_parser.c',
         'src/core/compression/algorithm.c',
         'src/core/compression/message_compress.c',
@@ -263,6 +260,7 @@
         'src/core/surface/channel.c',
         'src/core/surface/channel_connectivity.c',
         'src/core/surface/channel_create.c',
+        'src/core/surface/channel_ping.c',
         'src/core/surface/completion_queue.c',
         'src/core/surface/event_string.c',
         'src/core/surface/init.c',

+ 174 - 24
build.yaml

@@ -37,6 +37,7 @@ filegroups:
   - include/grpc++/impl/rpc_method.h
   - include/grpc++/impl/rpc_service_method.h
   - include/grpc++/impl/serialization_traits.h
+  - include/grpc++/impl/server_builder_option.h
   - include/grpc++/impl/service_type.h
   - include/grpc++/impl/sync.h
   - include/grpc++/impl/sync_cxx11.h
@@ -72,7 +73,6 @@ filegroups:
   - src/cpp/server/thread_pool_interface.h
   src:
   - src/cpp/client/channel.cc
-  - src/cpp/client/channel_arguments.cc
   - src/cpp/client/client_context.cc
   - src/cpp/client/create_channel.cc
   - src/cpp/client/create_channel_internal.cc
@@ -80,6 +80,7 @@ filegroups:
   - src/cpp/client/generic_stub.cc
   - src/cpp/client/insecure_credentials.cc
   - src/cpp/common/call.cc
+  - src/cpp/common/channel_arguments.cc
   - src/cpp/common/completion_queue.cc
   - src/cpp/common/rpc_method.cc
   - src/cpp/proto/proto_utils.cc
@@ -115,7 +116,6 @@ filegroups:
   - src/core/channel/context.h
   - src/core/channel/http_client_filter.h
   - src/core/channel/http_server_filter.h
-  - src/core/channel/noop_filter.h
   - src/core/channel/subchannel_call_holder.h
   - src/core/client_config/client_config.h
   - src/core/client_config/connector.h
@@ -132,8 +132,6 @@ filegroups:
   - src/core/client_config/resolvers/sockaddr_resolver.h
   - src/core/client_config/subchannel.h
   - src/core/client_config/subchannel_factory.h
-  - src/core/client_config/subchannel_factory_decorators/add_channel_arg.h
-  - src/core/client_config/subchannel_factory_decorators/merge_channel_args.h
   - src/core/client_config/uri_parser.h
   - src/core/compression/algorithm_metadata.h
   - src/core/compression/message_compress.h
@@ -232,7 +230,6 @@ filegroups:
   - src/core/channel/connected_channel.c
   - src/core/channel/http_client_filter.c
   - src/core/channel/http_server_filter.c
-  - src/core/channel/noop_filter.c
   - src/core/channel/subchannel_call_holder.c
   - src/core/client_config/client_config.c
   - src/core/client_config/connector.c
@@ -250,8 +247,6 @@ filegroups:
   - src/core/client_config/resolvers/sockaddr_resolver.c
   - src/core/client_config/subchannel.c
   - src/core/client_config/subchannel_factory.c
-  - src/core/client_config/subchannel_factory_decorators/add_channel_arg.c
-  - src/core/client_config/subchannel_factory_decorators/merge_channel_args.c
   - src/core/client_config/uri_parser.c
   - src/core/compression/algorithm.c
   - src/core/compression/message_compress.c
@@ -312,6 +307,7 @@ filegroups:
   - src/core/surface/channel.c
   - src/core/surface/channel_connectivity.c
   - src/core/surface/channel_create.c
+  - src/core/surface/channel_ping.c
   - src/core/surface/completion_queue.c
   - src/core/surface/event_string.c
   - src/core/surface/init.c
@@ -354,7 +350,6 @@ filegroups:
   - test/core/end2end/cq_verifier.h
   - test/core/end2end/fixtures/proxy.h
   - test/core/iomgr/endpoint_tests.h
-  - test/core/security/oauth2_utils.h
   - test/core/util/grpc_profiler.h
   - test/core/util/parse_hexstring.h
   - test/core/util/port.h
@@ -363,7 +358,6 @@ filegroups:
   - test/core/end2end/cq_verifier.c
   - test/core/end2end/fixtures/proxy.c
   - test/core/iomgr/endpoint_tests.c
-  - test/core/security/oauth2_utils.c
   - test/core/util/grpc_profiler.c
   - test/core/util/parse_hexstring.c
   - test/core/util/port_posix.c
@@ -526,10 +520,12 @@ libs:
   language: c
   headers:
   - test/core/end2end/data/ssl_test_data.h
+  - test/core/security/oauth2_utils.h
   src:
   - test/core/end2end/data/server1_cert.c
   - test/core/end2end/data/server1_key.c
   - test/core/end2end/data/test_root_cert.c
+  - test/core/security/oauth2_utils.c
   deps:
   - gpr
   - gpr_test_util
@@ -543,7 +539,7 @@ libs:
   deps:
   - gpr
   - gpr_test_util
-  - grpc
+  - grpc_unsecure
   filegroups:
   - grpc_test_util_base
   secure: false
@@ -612,10 +608,10 @@ libs:
   - src/cpp/common/secure_auth_context.h
   - src/cpp/server/secure_server_credentials.h
   src:
-  - src/cpp/client/secure_channel_arguments.cc
   - src/cpp/client/secure_credentials.cc
   - src/cpp/common/auth_property_iterator.cc
   - src/cpp/common/secure_auth_context.cc
+  - src/cpp/common/secure_channel_arguments.cc
   - src/cpp/common/secure_create_auth_context.cc
   - src/cpp/server/secure_server_credentials.cc
   deps:
@@ -814,6 +810,24 @@ libs:
   - winsock
   - global
 targets:
+- name: algorithm_test
+  build: test
+  language: c
+  src:
+  - test/core/compression/algorithm_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+- name: alloc_test
+  build: test
+  language: c
+  src:
+  - test/core/support/alloc_test.c
+  deps:
+  - gpr_test_util
+  - gpr
 - name: alpn_test
   build: test
   language: c
@@ -834,6 +848,16 @@ targets:
   - grpc
   - gpr_test_util
   - gpr
+- name: channel_create_test
+  build: test
+  language: c
+  src:
+  - test/core/surface/channel_create_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: chttp2_hpack_encoder_test
   build: test
   language: c
@@ -864,6 +888,16 @@ targets:
   - grpc
   - gpr_test_util
   - gpr
+- name: chttp2_varint_test
+  build: test
+  language: c
+  src:
+  - test/core/transport/chttp2/varint_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: compression_test
   build: test
   language: c
@@ -874,6 +908,16 @@ targets:
   - grpc
   - gpr_test_util
   - gpr
+- name: dns_resolver_test
+  build: test
+  language: c
+  src:
+  - test/core/client_config/resolvers/dns_resolver_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: dualstack_socket_test
   build: test
   language: c
@@ -1216,6 +1260,16 @@ targets:
   - grpc
   - gpr_test_util
   - gpr
+- name: grpc_invalid_channel_args_test
+  build: test
+  language: c
+  src:
+  - test/core/surface/invalid_channel_args_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: grpc_json_token_test
   build: test
   language: c
@@ -1324,6 +1378,38 @@ targets:
   - mac
   - linux
   - posix
+- name: httpscli_test
+  build: test
+  language: c
+  src:
+  - test/core/httpcli/httpscli_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  platforms:
+  - linux
+- name: init_test
+  build: test
+  language: c
+  src:
+  - test/core/surface/init_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+- name: invalid_call_argument_test
+  build: test
+  language: c
+  src:
+  - test/core/end2end/invalid_call_argument_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: json_rewrite
   build: test
   run: false
@@ -1343,6 +1429,16 @@ targets:
   - grpc
   - gpr_test_util
   - gpr
+- name: json_stream_error_test
+  build: test
+  language: c
+  src:
+  - test/core/json/json_stream_error_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: json_test
   build: test
   language: c
@@ -1397,16 +1493,6 @@ targets:
   - grpc
   - gpr_test_util
   - gpr
-- name: multi_init_test
-  build: test
-  language: c
-  src:
-  - test/core/surface/multi_init_test.c
-  deps:
-  - grpc_test_util
-  - grpc
-  - gpr_test_util
-  - gpr
 - name: multiple_server_queues_test
   build: test
   language: c
@@ -1445,6 +1531,16 @@ targets:
   - grpc
   - gpr_test_util
   - gpr
+- name: secure_channel_create_test
+  build: test
+  language: c
+  src:
+  - test/core/surface/secure_channel_create_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: secure_endpoint_test
   build: test
   language: c
@@ -1455,6 +1551,26 @@ targets:
   - grpc
   - gpr_test_util
   - gpr
+- name: server_chttp2_test
+  build: test
+  language: c
+  src:
+  - test/core/surface/server_chttp2_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+- name: server_test
+  build: test
+  language: c
+  src:
+  - test/core/surface/server_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: set_initial_connect_string_test
   build: test
   language: c
@@ -1466,6 +1582,16 @@ targets:
   - grpc
   - gpr_test_util
   - gpr
+- name: sockaddr_resolver_test
+  build: test
+  language: c
+  src:
+  - test/core/client_config/resolvers/sockaddr_resolver_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: sockaddr_utils_test
   build: test
   language: c
@@ -1476,6 +1602,20 @@ targets:
   - grpc
   - gpr_test_util
   - gpr
+- name: socket_utils_test
+  build: test
+  language: c
+  src:
+  - test/core/iomgr/socket_utils_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  platforms:
+  - mac
+  - linux
+  - posix
 - name: tcp_client_posix_test
   build: test
   language: c
@@ -1568,6 +1708,16 @@ targets:
   - grpc
   - gpr_test_util
   - gpr
+- name: transport_connectivity_state_test
+  build: test
+  language: c
+  src:
+  - test/core/transport/connectivity_state_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: transport_metadata_test
   build: test
   language: c
@@ -1692,7 +1842,7 @@ targets:
   build: test
   language: c++
   src:
-  - test/cpp/client/channel_arguments_test.cc
+  - test/cpp/common/channel_arguments_test.cc
   deps:
   - grpc++
   - grpc
@@ -2269,11 +2419,11 @@ vspackages:
   name: grpc.dependencies.zlib
   props: false
   redist: true
-  version: 1.2.8.9
+  version: 1.2.8.10
 - name: grpc.dependencies.openssl
   props: true
   redist: true
-  version: 1.0.2.3
+  version: 1.0.204.1
 - name: gflags
   props: false
   redist: false

+ 1 - 1
doc/PROTOCOL-HTTP2.md

@@ -45,7 +45,7 @@ Request-Headers are delivered as HTTP2 headers in HEADERS + CONTINUATION frames.
 * **Custom-Metadata** → Binary-Header / ASCII-Header
 * **Binary-Header** → {Header-Name "-bin" } {_base64 encoded value_}
 * **ASCII-Header** → Header-Name ASCII-Value
-* **Header-Name** → 1\*( %x30-39 / %x61-7A / "\_" / "-") ; 0-9 a-z \_ -
+* **Header-Name** → 1\*( %x30-39 / %x61-7A / "\_" / "-" / ".") ; 0-9 a-z \_ - .
 * **ASCII-Value** → 1\*( %x20-%x7E ) ; space and printable ASCII
 
 

+ 0 - 289
doc/grpc-auth-support.md

@@ -1,289 +0,0 @@
-#gRPC Authentication support
-
-gRPC is designed to plug-in a number of authentication mechanisms. This document
-provides a quick overview of the various auth mechanisms supported, discusses
-the API with some examples, and concludes with a discussion of extensibility.
-More documentation and examples are coming soon!
-
-## Supported auth mechanisms
-
-###SSL/TLS
-gRPC has SSL/TLS integration and promotes the use of SSL/TLS to authenticate the
-server, and encrypt all the data exchanged between the client and the server.
-Optional mechanisms are available for clients to provide certificates to
-accomplish mutual authentication.
-
-###OAuth 2.0
-gRPC provides a generic mechanism (described below) to attach metadata to
-requests and responses. This mechanism can be used to attach OAuth 2.0 Access
-Tokens to RPCs being made at a client. Additional support for acquiring Access
-Tokens while accessing Google APIs through gRPC is provided for certain auth
-flows, demonstrated through code examples below.
-
-## API
-To reduce complexity and minimize API clutter, gRPC works with a unified concept
-of a Credentials object. Users construct gRPC credentials using corresponding
-bootstrap credentials (e.g., SSL client certs or Service Account Keys), and use
-the credentials while creating a gRPC channel to any server. Depending on the
-type of credential supplied, the channel uses the credentials during the initial
-SSL/TLS handshake with the server, or uses  the credential to generate and
-attach Access Tokens to each request being made on the channel.
-
-###SSL/TLS for server authentication and encryption
-This is the simplest authentication scenario, where a client just wants to
-authenticate the server and encrypt all data.
-
-```cpp
-SslCredentialsOptions ssl_opts;  // Options to override SSL params, empty by default
-// Create the credentials object by providing service account key in constructor
-std::shared_ptr<ChannelCredentials> creds = SslCredentials(ssl_opts);
-// Create a channel using the credentials created in the previous step
-std::shared_ptr<Channel> channel = CreateChannel(server_name, creds);
-// Create a stub on the channel
-std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
-// Make actual RPC calls on the stub.
-grpc::Status s = stub->sayHello(&context, *request, response);
-```
-
-For advanced use cases such as modifying the root CA or using client certs,
-the corresponding options can be set in the SslCredentialsOptions parameter
-passed to the factory method.
-
-
-###Authenticating with Google
-
-gRPC applications can use a simple API to create a credential that works in various deployment scenarios.
-
-```cpp
-std::shared_ptr<ChannelCredentials> creds = GoogleDefaultCredentials();
-// Create a channel, stub and make RPC calls (same as in the previous example)
-std::shared_ptr<Channel> channel = CreateChannel(server_name, creds);
-std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
-grpc::Status s = stub->sayHello(&context, *request, response);
-```
-
-This credential works for applications using Service Accounts as well as for
-applications running in [Google Compute Engine (GCE)](https://cloud.google.com/compute/). In the former case, the
-service account’s private keys are loaded from the file named in the environment
-variable `GOOGLE_APPLICATION_CREDENTIALS`. The
-keys are used to generate bearer tokens that are attached to each outgoing RPC
-on the corresponding channel.
-
-For applications running in GCE, a default service account and corresponding
-OAuth scopes can be configured during VM setup. At run-time, this credential
-handles communication with the authentication systems to obtain OAuth2 access
-tokens and attaches them to each outgoing RPC on the corresponding channel.
-Extending gRPC to support other authentication mechanisms
-The gRPC protocol is designed with a general mechanism for sending metadata
-associated with RPC. Clients can send metadata at the beginning of an RPC and
-servers can send back metadata at the beginning and end of the RPC. This
-provides a natural mechanism to support OAuth2 and other authentication
-mechanisms that need attach bearer tokens to individual request.
-
-In the simplest case, there is a single line of code required on the client
-to add a specific token as metadata to an RPC and a corresponding access on
-the server to retrieve this piece of metadata. The generation of the token
-on the client side and its verification at the server can be done separately.
-
-A deeper integration can be achieved by plugging in a gRPC credentials implementation for any custom authentication mechanism that needs to attach per-request tokens. gRPC internals also allow switching out SSL/TLS with other encryption mechanisms.
-
-## Examples
-
-These authentication mechanisms will be available in all gRPC's supported languages.
-The following sections demonstrate how authentication and authorization features described above appear in each language: more languages are coming soon.
-
-###SSL/TLS for server authentication and encryption (Ruby)
-```ruby
-# Base case - No encryption
-stub = Helloworld::Greeter::Stub.new('localhost:50051')
-...
-
-# With server authentication SSL/TLS
-creds = GRPC::Core::Credentials.new(load_certs)  # load_certs typically loads a CA roots file
-stub = Helloworld::Greeter::Stub.new('localhost:50051', creds: creds)
-```
-
-###SSL/TLS for server authentication and encryption (C#)
-```csharp
-// Base case - No encryption
-var channel = new Channel("localhost:50051");
-var client = new Greeter.GreeterClient(channel);
-...
-
-// With server authentication SSL/TLS
-var credentials = new SslCredentials(File.ReadAllText("ca.pem"));  // Load a CA file
-var channel = new Channel("localhost:50051", credentials);
-var client = new Greeter.GreeterClient(channel);
-```
-
-###SSL/TLS for server authentication and encryption (Objective-C)
-
-The default for Objective-C is to use SSL/TLS, as that's the most common use case when accessing
-remote APIs.
-
-```objective-c
-// Base case - With server authentication SSL/TLS
-HLWGreeter *client = [[HLWGreeter alloc] initWithHost:@"localhost:50051"];
-// Same as using @"https://localhost:50051".
-...
-
-// No encryption
-HLWGreeter *client = [[HLWGreeter alloc] initWithHost:@"http://localhost:50051"];
-// Specifying the HTTP scheme explicitly forces no encryption.
-```
-
-###SSL/TLS for server authentication and encryption (Python)
-```python
-# Base case - No encryption
-stub = early_adopter_create_GreeterService_stub('localhost', 50051)
-...
-
-# With server authentication SSL/TLS
-stub = early_adopter_create_GreeterService_stub(
-  'localhost', 50051, secure=True, root_certificates=open('ca.pem').read())
-...
-```
-n.b.: the beta API will look different
-
-###Authenticating with Google (Ruby)
-```ruby
-# Base case - No encryption/authorization
-stub = Helloworld::Greeter::Stub.new('localhost:50051')
-...
-
-# Authenticating with Google
-require 'googleauth'  # from http://www.rubydoc.info/gems/googleauth/0.1.0
-...
-creds = GRPC::Core::Credentials.new(load_certs)  # load_certs typically loads a CA roots file
-scope = 'https://www.googleapis.com/auth/grpc-testing'
-authorization = Google::Auth.get_application_default(scope)
-stub = Helloworld::Greeter::Stub.new('localhost:50051',
-                                     creds: creds,
-                                     update_metadata: authorization.updater_proc)
-```
-
-###Authenticating with Google (Node.js)
-
-```node
-// Base case - No encryption/authorization
-var stub = new helloworld.Greeter('localhost:50051');
-...
-// Authenticating with Google
-var GoogleAuth = require('google-auth-library'); // from https://www.npmjs.com/package/google-auth-library
-...
-var creds = grpc.Credentials.createSsl(load_certs); // load_certs typically loads a CA roots file
-var scope = 'https://www.googleapis.com/auth/grpc-testing';
-(new GoogleAuth()).getApplicationDefault(function(err, auth) {
-  if (auth.createScopeRequired()) {
-    auth = auth.createScoped(scope);
-  }
-  var stub = new helloworld.Greeter('localhost:50051',
-                                    {credentials: creds},
-                                    grpc.getGoogleAuthDelegate(auth));
-});
-```
-
-###Authenticating with Google (C#)
-```csharp
-// Base case - No encryption/authorization
-var channel = new Channel("localhost:50051");
-var client = new Greeter.GreeterClient(channel);
-...
-
-// Authenticating with Google
-using Grpc.Auth;  // from Grpc.Auth NuGet package
-...
-var credentials = new SslCredentials(File.ReadAllText("ca.pem"));  // Load a CA file
-var channel = new Channel("localhost:50051", credentials);
-
-string scope = "https://www.googleapis.com/auth/grpc-testing";
-var authorization = GoogleCredential.GetApplicationDefault();
-if (authorization.IsCreateScopedRequired)
-{
-    authorization = credential.CreateScoped(new[] { scope });
-}
-var client = new Greeter.GreeterClient(channel,
-        new StubConfiguration(OAuth2InterceptorFactory.Create(credential)));
-```
-
-###Authenticating with Google (PHP)
-```php
-// Base case - No encryption/authorization
-$client = new helloworld\GreeterClient(
-  new Grpc\BaseStub('localhost:50051', []));
-...
-
-// Authenticating with Google
-// the environment variable "GOOGLE_APPLICATION_CREDENTIALS" needs to be set
-$scope = "https://www.googleapis.com/auth/grpc-testing";
-$auth = Google\Auth\ApplicationDefaultCredentials::getCredentials($scope);
-$opts = [
-  'credentials' => Grpc\Credentials::createSsl(file_get_contents('ca.pem'));
-  'update_metadata' => $auth->getUpdateMetadataFunc(),
-];
-
-$client = new helloworld\GreeterClient(
-  new Grpc\BaseStub('localhost:50051', $opts));
-
-```
-
-###Authenticating with Google (Objective-C)
-
-This example uses the [Google iOS Sign-In library](https://developers.google.com/identity/sign-in/ios/),
-but it's easily extrapolated to any other OAuth2 library.
-
-```objective-c
-// Base case - No authentication
-[client sayHelloWithRequest:request handler:^(HLWHelloReply *response, NSError *error) {
-  ...
-}];
-
-...
-
-// Authenticating with Google
-
-// When signing the user in, ask her for the relevant scopes.
-GIDSignIn.sharedInstance.scopes = @[@"https://www.googleapis.com/auth/grpc-testing"];
-
-...
-
-#import <ProtoRPC/ProtoRPC.h>
-
-// Create a not-yet-started RPC. We want to set the request headers on this object before starting
-// it.
-ProtoRPC *call =
-    [client RPCToSayHelloWithRequest:request handler:^(HLWHelloReply *response, NSError *error) {
-      ...
-    }];
-
-// Set the access token to be used.
-NSString *accessToken = GIDSignIn.sharedInstance.currentUser.authentication.accessToken;
-call.requestMetadata[@"Authorization"] = [@"Bearer " stringByAppendingString:accessToken]}];
-
-// Start the RPC.
-[call start];
-```
-
-You can see a working example app, with a more detailed explanation, [here](examples/objective-c/auth_sample).
-
-### Authenticating with Google (Python)
-```python
-# Base case - No encryption
-stub = early_adopter_create_GreeterService_stub('localhost', 50051)
-...
-
-# With server authentication SSL/TLS
-import oauth2client.client
-credentials = oauth2client.GoogleCredentials.get_application_default()
-scope = 'https://www.googleapis.com/auth/grpc-testing'
-scoped_credentials = credentials.create_scoped([scope])
-access_token = scoped_credentials.get_access_token().access_token
-metadata_transformer = (
-    lambda x: [('Authorization', 'Bearer {}'.format(access_token))])
-
-stub = early_adopter_create_GreeterService_stub(
-  'localhost', 50051, secure=True, root_certificates=open('ca.pem').read(),
-  metadata_transformer=metadata_transformer)
-...
-```
-n.b.: the beta API will look different

+ 14 - 14
examples/cpp/helloworld/README.md

@@ -41,7 +41,7 @@ message from the remote client containing the user's name, then send back
 a greeting in a single `HelloReply`. This is the simplest type of RPC you
 can specify in gRPC - we'll look at some other types later in this document.
 
-```
+```protobuf
 syntax = "proto3";
 
 option java_package = "ex.grpc";
@@ -93,20 +93,20 @@ $ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto
   channel can be created with the target address, credentials to use and
   arguments as follows
 
-    ```
+    ```cpp
     auto channel = CreateChannel("localhost:50051", InsecureChannelCredentials());
     ```
 
 - Create a stub. A stub implements the rpc methods of a service and in the
   generated code, a method is provided to created a stub with a channel:
 
-    ```
+    ```cpp
     auto stub = helloworld::Greeter::NewStub(channel);
     ```
 
 - Make a unary rpc, with `ClientContext` and request/response proto messages.
 
-    ```
+    ```cpp
     ClientContext context;
     HelloRequest request;
     request.set_name("hello");
@@ -116,7 +116,7 @@ $ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto
 
 - Check returned status and response.
 
-    ```
+    ```cpp
     if (status.ok()) {
       // check reply.message()
     } else {
@@ -130,7 +130,7 @@ For a working example, refer to [greeter_client.cc](greeter_client.cc).
 
 - Implement the service interface
 
-    ```
+    ```cpp
     class GreeterServiceImpl final : public Greeter::Service {
       Status SayHello(ServerContext* context, const HelloRequest* request,
           HelloReply* reply) override {
@@ -144,7 +144,7 @@ For a working example, refer to [greeter_client.cc](greeter_client.cc).
 
 - Build a server exporting the service
 
-    ```
+    ```cpp
     GreeterServiceImpl service;
     ServerBuilder builder;
     builder.AddListeningPort("0.0.0.0:50051", grpc::InsecureServerCredentials());
@@ -170,14 +170,14 @@ The channel and stub creation code is the same as the sync client.
 - Initiate the rpc and create a handle for the rpc. Bind the rpc to a
   `CompletionQueue`.
 
-    ```
+    ```cpp
     CompletionQueue cq;
     auto rpc = stub->AsyncSayHello(&context, request, &cq);
     ```
 
 - Ask for reply and final status, with a unique tag
 
-    ```
+    ```cpp
     Status status;
     rpc->Finish(&reply, &status, (void*)1);
     ```
@@ -185,7 +185,7 @@ The channel and stub creation code is the same as the sync client.
 - Wait for the completion queue to return the next tag. The reply and status are
   ready once the tag passed into the corresponding `Finish()` call is returned.
 
-    ```
+    ```cpp
     void* got_tag;
     bool ok = false;
     cq.Next(&got_tag, &ok);
@@ -203,7 +203,7 @@ completion queue to return the tag. The basic flow is
 
 - Build a server exporting the async service
 
-    ```
+    ```cpp
     helloworld::Greeter::AsyncService service;
     ServerBuilder builder;
     builder.AddListeningPort("0.0.0.0:50051", InsecureServerCredentials());
@@ -214,7 +214,7 @@ completion queue to return the tag. The basic flow is
 
 - Request one rpc
 
-    ```
+    ```cpp
     ServerContext context;
     HelloRequest request;
     ServerAsyncResponseWriter<HelloReply> responder;
@@ -224,7 +224,7 @@ completion queue to return the tag. The basic flow is
 - Wait for the completion queue to return the tag. The context, request and
   responder are ready once the tag is retrieved.
 
-    ```
+    ```cpp
     HelloReply reply;
     Status status;
     void* got_tag;
@@ -239,7 +239,7 @@ completion queue to return the tag. The basic flow is
 - Wait for the completion queue to return the tag. The rpc is finished when the
   tag is back.
 
-    ```
+    ```cpp
     void* got_tag;
     bool ok = false;
     cq.Next(&got_tag, &ok);

+ 1 - 1
examples/objective-c/auth_sample/AuthTestService.podspec

@@ -29,7 +29,7 @@ Pod::Spec.new do |s|
     ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}"
     ss.header_mappings_dir = dir
     ss.requires_arc = true
-    ss.dependency "gRPC", "~> 0.11"
+    ss.dependency "gRPC", "~> 0.12"
     ss.dependency "#{s.name}/Messages"
   end
 end

+ 1 - 0
examples/objective-c/auth_sample/Podfile

@@ -2,6 +2,7 @@ source 'https://github.com/CocoaPods/Specs.git'
 platform :ios, '8.0'
 
 pod 'Protobuf', :path => "../../../third_party/protobuf"
+pod 'BoringSSL', :podspec => "../../../src/objective-c"
 pod 'gRPC', :path => "../../.."
 
 target 'AuthSample' do

+ 1 - 1
examples/objective-c/helloworld/HelloWorld.podspec

@@ -29,7 +29,7 @@ Pod::Spec.new do |s|
     ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}"
     ss.header_mappings_dir = dir
     ss.requires_arc = true
-    ss.dependency "gRPC", "~> 0.11"
+    ss.dependency "gRPC", "~> 0.12"
     ss.dependency "#{s.name}/Messages"
   end
 end

+ 1 - 0
examples/objective-c/helloworld/Podfile

@@ -2,6 +2,7 @@ source 'https://github.com/CocoaPods/Specs.git'
 platform :ios, '8.0'
 
 pod 'Protobuf', :path => "../../../third_party/protobuf"
+pod 'BoringSSL', :podspec => "../../../src/objective-c"
 pod 'gRPC', :path => "../../.."
 
 target 'HelloWorld' do

+ 1 - 0
examples/objective-c/route_guide/Podfile

@@ -3,6 +3,7 @@ platform :ios, '8.0'
 
 target 'RouteGuideClient' do
   pod 'Protobuf', :path => "../../../third_party/protobuf"
+  pod 'BoringSSL', :podspec => "../../../src/objective-c"
   pod 'gRPC', :path => "../../.."
   # Depend on the generated RouteGuide library.
   pod 'RouteGuide', :path => '.'

+ 1 - 1
examples/objective-c/route_guide/RouteGuide.podspec

@@ -29,7 +29,7 @@ Pod::Spec.new do |s|
     ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}"
     ss.header_mappings_dir = dir
     ss.requires_arc = true
-    ss.dependency "gRPC", "~> 0.11"
+    ss.dependency "gRPC", "~> 0.12"
     ss.dependency "#{s.name}/Messages"
   end
 end

+ 3 - 11
gRPC.podspec

@@ -36,7 +36,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC'
-  version = '0.11.2'
+  version = '0.12.0'
   s.version  = version
   s.summary  = 'gRPC client library for iOS/OSX'
   s.homepage = 'http://www.grpc.io'
@@ -165,7 +165,6 @@ Pod::Spec.new do |s|
                       'src/core/channel/context.h',
                       'src/core/channel/http_client_filter.h',
                       'src/core/channel/http_server_filter.h',
-                      'src/core/channel/noop_filter.h',
                       'src/core/channel/subchannel_call_holder.h',
                       'src/core/client_config/client_config.h',
                       'src/core/client_config/connector.h',
@@ -182,8 +181,6 @@ Pod::Spec.new do |s|
                       'src/core/client_config/resolvers/sockaddr_resolver.h',
                       'src/core/client_config/subchannel.h',
                       'src/core/client_config/subchannel_factory.h',
-                      'src/core/client_config/subchannel_factory_decorators/add_channel_arg.h',
-                      'src/core/client_config/subchannel_factory_decorators/merge_channel_args.h',
                       'src/core/client_config/uri_parser.h',
                       'src/core/compression/algorithm_metadata.h',
                       'src/core/compression/message_compress.h',
@@ -312,7 +309,6 @@ Pod::Spec.new do |s|
                       'src/core/channel/connected_channel.c',
                       'src/core/channel/http_client_filter.c',
                       'src/core/channel/http_server_filter.c',
-                      'src/core/channel/noop_filter.c',
                       'src/core/channel/subchannel_call_holder.c',
                       'src/core/client_config/client_config.c',
                       'src/core/client_config/connector.c',
@@ -330,8 +326,6 @@ Pod::Spec.new do |s|
                       'src/core/client_config/resolvers/sockaddr_resolver.c',
                       'src/core/client_config/subchannel.c',
                       'src/core/client_config/subchannel_factory.c',
-                      'src/core/client_config/subchannel_factory_decorators/add_channel_arg.c',
-                      'src/core/client_config/subchannel_factory_decorators/merge_channel_args.c',
                       'src/core/client_config/uri_parser.c',
                       'src/core/compression/algorithm.c',
                       'src/core/compression/message_compress.c',
@@ -392,6 +386,7 @@ Pod::Spec.new do |s|
                       'src/core/surface/channel.c',
                       'src/core/surface/channel_connectivity.c',
                       'src/core/surface/channel_create.c',
+                      'src/core/surface/channel_ping.c',
                       'src/core/surface/completion_queue.c',
                       'src/core/surface/event_string.c',
                       'src/core/surface/init.c',
@@ -467,7 +462,6 @@ Pod::Spec.new do |s|
                               'src/core/channel/context.h',
                               'src/core/channel/http_client_filter.h',
                               'src/core/channel/http_server_filter.h',
-                              'src/core/channel/noop_filter.h',
                               'src/core/channel/subchannel_call_holder.h',
                               'src/core/client_config/client_config.h',
                               'src/core/client_config/connector.h',
@@ -484,8 +478,6 @@ Pod::Spec.new do |s|
                               'src/core/client_config/resolvers/sockaddr_resolver.h',
                               'src/core/client_config/subchannel.h',
                               'src/core/client_config/subchannel_factory.h',
-                              'src/core/client_config/subchannel_factory_decorators/add_channel_arg.h',
-                              'src/core/client_config/subchannel_factory_decorators/merge_channel_args.h',
                               'src/core/client_config/uri_parser.h',
                               'src/core/compression/algorithm_metadata.h',
                               'src/core/compression/message_compress.h',
@@ -589,7 +581,7 @@ Pod::Spec.new do |s|
 
     ss.requires_arc = false
     ss.libraries = 'z'
-    ss.dependency 'OpenSSL', '~> 1.0.200'
+    ss.dependency 'BoringSSL', '~> 1.0'
 
     # ss.compiler_flags = '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w'
   end

+ 12 - 1
include/grpc++/client_context.h

@@ -268,7 +268,7 @@ class ClientContext {
   /// \return The call's peer URI.
   grpc::string peer() const;
 
-  /// Get and set census context
+  /// Get and set census context.
   void set_census_context(struct census_context* ccp) { census_context_ = ccp; }
   struct census_context* census_context() const {
     return census_context_;
@@ -280,6 +280,17 @@ class ClientContext {
   /// There is no guarantee the call will be cancelled.
   void TryCancel();
 
+  /// Global Callbacks
+  ///
+  /// Can be set exactly once per application to install hooks whenever
+  /// a client context is constructed and destructed.
+  class GlobalCallbacks {
+   public:
+    virtual void DefaultConstructor(ClientContext* context) = 0;
+    virtual void Destructor(ClientContext* context) = 0;
+  };
+  static void SetGlobalCallbacks(GlobalCallbacks* callbacks);
+
  private:
   // Disallow copy and assign.
   ClientContext(const ClientContext&);

+ 6 - 1
include/grpc++/impl/rpc_service_method.h

@@ -34,6 +34,7 @@
 #ifndef GRPCXX_IMPL_RPC_SERVICE_METHOD_H
 #define GRPCXX_IMPL_RPC_SERVICE_METHOD_H
 
+#include <climits>
 #include <functional>
 #include <map>
 #include <memory>
@@ -251,7 +252,11 @@ class RpcService {
   void AddMethod(RpcServiceMethod* method) { methods_.emplace_back(method); }
 
   RpcServiceMethod* GetMethod(int i) { return methods_[i].get(); }
-  int GetMethodCount() const { return methods_.size(); }
+  int GetMethodCount() const {
+    // On win x64, int is only 32bit
+    GPR_ASSERT(methods_.size() <= INT_MAX);
+    return (int)methods_.size();
+  }
 
  private:
   std::vector<std::unique_ptr<RpcServiceMethod>> methods_;

+ 15 - 10
src/core/client_config/subchannel_factory_decorators/add_channel_arg.h → include/grpc++/impl/server_builder_option.h

@@ -31,16 +31,21 @@
  *
  */
 
-#ifndef GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_ADD_CHANNEL_ARG_H
-#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_ADD_CHANNEL_ARG_H
+#ifndef GRPCXX_IMPL_SERVER_BUILDER_OPTION_H
+#define GRPCXX_IMPL_SERVER_BUILDER_OPTION_H
 
-#include "src/core/client_config/subchannel_factory.h"
+#include <grpc++/support/channel_arguments.h>
 
-/** Takes a subchannel factory, returns a new one that mutates incoming
-    channel_args by adding a new argument; ownership of input, arg is retained
-    by the caller. */
-grpc_subchannel_factory *grpc_subchannel_factory_add_channel_arg(
-    grpc_subchannel_factory *input, const grpc_arg *arg);
+namespace grpc {
 
-#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_ADD_CHANNEL_ARG_H \
-        */
+/// Interface to pass an option to a \a ServerBuilder.
+class ServerBuilderOption {
+ public:
+  virtual ~ServerBuilderOption() {}
+  /// Alter the \a ChannelArguments used to create the gRPC server.
+  virtual void UpdateArguments(ChannelArguments* args) = 0;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCXX_IMPL_SERVER_BUILDER_OPTION_H

+ 10 - 1
include/grpc++/security/credentials.h

@@ -38,6 +38,7 @@
 #include <memory>
 
 #include <grpc++/impl/grpc_library.h>
+#include <grpc++/security/auth_context.h>
 #include <grpc++/support/config.h>
 #include <grpc++/support/status.h>
 #include <grpc++/support/string_ref.h>
@@ -206,9 +207,17 @@ class MetadataCredentialsPlugin {
   // a different thread from the one processing the call.
   virtual bool IsBlocking() const { return true; }
 
+  // Type of credentials this plugin is implementing.
+  virtual const char* GetType() const { return ""; }
+
   // Gets the auth metatada produced by this plugin.
+  // The fully qualified method name is:
+  // service_url + "/" + method_name.
+  // The channel_auth_context contains (among other things), the identity of
+  // the server.
   virtual Status GetMetadata(
-      grpc::string_ref service_url,
+      grpc::string_ref service_url, grpc::string_ref method_name,
+      const AuthContext& channel_auth_context,
       std::multimap<grpc::string, grpc::string>* metadata) = 0;
 };
 

+ 21 - 2
include/grpc++/server.h

@@ -37,14 +37,15 @@
 #include <list>
 #include <memory>
 
-#include <grpc/compression.h>
 #include <grpc++/completion_queue.h>
 #include <grpc++/impl/call.h>
 #include <grpc++/impl/grpc_library.h>
 #include <grpc++/impl/sync.h>
 #include <grpc++/security/server_credentials.h>
+#include <grpc++/support/channel_arguments.h>
 #include <grpc++/support/config.h>
 #include <grpc++/support/status.h>
+#include <grpc/compression.h>
 
 struct grpc_server;
 
@@ -56,6 +57,7 @@ class AsyncGenericService;
 class RpcService;
 class RpcServiceMethod;
 class ServerAsyncStreamingInterface;
+class ServerContext;
 class ThreadPoolInterface;
 
 /// Models a gRPC server.
@@ -84,6 +86,23 @@ class Server GRPC_FINAL : public GrpcLibrary, private CallHook {
   /// call \a Shutdown for this function to ever return.
   void Wait();
 
+  /// Global Callbacks
+  ///
+  /// Can be set exactly once per application to install hooks whenever
+  /// a server event occurs
+  class GlobalCallbacks {
+   public:
+    virtual ~GlobalCallbacks() {}
+    /// Called before application callback for each synchronous server request
+    virtual void PreSynchronousRequest(ServerContext* context) = 0;
+    /// Called after application callback for each synchronous server request
+    virtual void PostSynchronousRequest(ServerContext* context) = 0;
+  };
+  /// Set the global callback object. Can only be called once. Does not take
+  /// ownership of callbacks, and expects the pointed to object to be alive
+  /// until all server objects in the process have been destroyed.
+  static void SetGlobalCallbacks(GlobalCallbacks* callbacks);
+
  private:
   friend class AsyncGenericService;
   friend class AsynchronousService;
@@ -100,7 +119,7 @@ class Server GRPC_FINAL : public GrpcLibrary, private CallHook {
   /// \param max_message_size Maximum message length that the channel can
   /// receive.
   Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
-         int max_message_size, grpc_compression_options compression_options);
+         int max_message_size, const ChannelArguments& args);
 
   /// Register a service. This call does not take ownership of the service.
   /// The service must exist for the lifetime of the Server instance.

+ 5 - 1
include/grpc++/server_builder.h

@@ -37,8 +37,9 @@
 #include <memory>
 #include <vector>
 
-#include <grpc/compression.h>
+#include <grpc++/impl/server_builder_option.h>
 #include <grpc++/support/config.h>
+#include <grpc/compression.h>
 
 namespace grpc {
 
@@ -98,6 +99,8 @@ class ServerBuilder {
     compression_options_ = options;
   }
 
+  void SetOption(std::unique_ptr<ServerBuilderOption> option);
+
   /// Tries to bind \a server to the given \a addr.
   ///
   /// It can be invoked multiple times.
@@ -140,6 +143,7 @@ class ServerBuilder {
 
   int max_message_size_;
   grpc_compression_options compression_options_;
+  std::vector<std::unique_ptr<ServerBuilderOption>> options_;
   std::vector<std::unique_ptr<NamedService<RpcService>>> services_;
   std::vector<std::unique_ptr<NamedService<AsynchronousService>>>
       async_services_;

+ 5 - 0
include/grpc++/support/channel_arguments.h

@@ -80,6 +80,11 @@ class ChannelArguments {
   // Generic channel argument setters. Only for advanced use cases.
   /// Set an integer argument \a value under \a key.
   void SetInt(const grpc::string& key, int value);
+
+  // Generic channel argument setter. Only for advanced use cases.
+  /// Set a pointer argument \a value under \a key. Owership is not transferred.
+  void SetPointer(const grpc::string& key, void* value);
+
   /// Set a textual argument \a value under \a key.
   void SetString(const grpc::string& key, const grpc::string& value);
 

+ 0 - 6
include/grpc/compression.h

@@ -79,12 +79,6 @@ int grpc_compression_algorithm_parse(const char *name, size_t name_length,
 int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
                                     char **name);
 
-/** Returns the compression level corresponding to \a algorithm.
- *
- * It abort()s for unknown algorithms. */
-grpc_compression_level grpc_compression_level_for_algorithm(
-    grpc_compression_algorithm algorithm);
-
 /** Returns the compression algorithm corresponding to \a level.
  *
  * It abort()s for unknown levels . */

+ 5 - 0
include/grpc/grpc.h

@@ -531,6 +531,11 @@ grpc_call *grpc_channel_create_call(grpc_channel *channel,
                                     const char *method, const char *host,
                                     gpr_timespec deadline, void *reserved);
 
+/** Ping the channels peer (load balanced channels will select one sub-channel
+    to ping); if the channel is not connected, posts a failed. */
+void grpc_channel_ping(grpc_channel *channel, grpc_completion_queue *cq,
+                       void *tag, void *reserved);
+
 /** Pre-register a method/host pair on a channel. */
 void *grpc_channel_register_call(grpc_channel *channel, const char *method,
                                  const char *host, void *reserved);

+ 99 - 78
include/grpc/grpc_security.h

@@ -41,6 +41,81 @@
 extern "C" {
 #endif
 
+/* --- Authentication Context. --- */
+
+#define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME "transport_security_type"
+#define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl"
+
+#define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"
+#define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
+
+typedef struct grpc_auth_context grpc_auth_context;
+
+typedef struct grpc_auth_property_iterator {
+  const grpc_auth_context *ctx;
+  size_t index;
+  const char *name;
+} grpc_auth_property_iterator;
+
+/* value, if not NULL, is guaranteed to be NULL terminated. */
+typedef struct grpc_auth_property {
+  char *name;
+  char *value;
+  size_t value_length;
+} grpc_auth_property;
+
+/* Returns NULL when the iterator is at the end. */
+const grpc_auth_property *grpc_auth_property_iterator_next(
+    grpc_auth_property_iterator *it);
+
+/* Iterates over the auth context. */
+grpc_auth_property_iterator grpc_auth_context_property_iterator(
+    const grpc_auth_context *ctx);
+
+/* Gets the peer identity. Returns an empty iterator (first _next will return
+   NULL) if the peer is not authenticated. */
+grpc_auth_property_iterator grpc_auth_context_peer_identity(
+    const grpc_auth_context *ctx);
+
+/* Finds a property in the context. May return an empty iterator (first _next
+   will return NULL) if no property with this name was found in the context. */
+grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
+    const grpc_auth_context *ctx, const char *name);
+
+/* Gets the name of the property that indicates the peer identity. Will return
+   NULL if the peer is not authenticated. */
+const char *grpc_auth_context_peer_identity_property_name(
+    const grpc_auth_context *ctx);
+
+/* Returns 1 if the peer is authenticated, 0 otherwise. */
+int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx);
+
+/* Gets the auth context from the call. Caller needs to call
+   grpc_auth_context_release on the returned context. */
+grpc_auth_context *grpc_call_auth_context(grpc_call *call);
+
+/* Releases the auth context returned from grpc_call_auth_context. */
+void grpc_auth_context_release(grpc_auth_context *context);
+
+/* --
+   The following auth context methods should only be called by a server metadata
+   processor to set properties extracted from auth metadata.
+   -- */
+
+/* Add a property. */
+void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name,
+                                    const char *value, size_t value_length);
+
+/* Add a C string property. */
+void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx,
+                                            const char *name,
+                                            const char *value);
+
+/* Sets the property name. Returns 1 if successful or 0 in case of failure
+   (which means that no property with this name exists). */
+int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx,
+                                                      const char *name);
+
 /* --- grpc_channel_credentials object. ---
 
    A channel credentials object represents a way to authenticate a client on a
@@ -165,6 +240,24 @@ typedef void (*grpc_credentials_plugin_metadata_cb)(
     void *user_data, const grpc_metadata *creds_md, size_t num_creds_md,
     grpc_status_code status, const char *error_details);
 
+/* Context that can be used by metadata credentials plugin in order to create
+   auth related metadata. */
+typedef struct {
+  /* The fully qualifed service url. */
+  const char *service_url;
+
+  /* The method name of the RPC being called (not fully qualified).
+     The fully qualified method name can be built from the service_url:
+     full_qualified_method_name = ctx->service_url + '/' + ctx->method_name. */
+  const char *method_name;
+
+  /* The auth_context of the channel which gives the server's identity. */
+  const grpc_auth_context *channel_auth_context;
+
+  /* Reserved for future use. */
+  void *reserved;
+} grpc_auth_metadata_context;
+
 /* grpc_metadata_credentials plugin is an API user provided structure used to
    create grpc_credentials objects that can be set on a channel (composed) or
    a call. See grpc_credentials_metadata_create_from_plugin below.
@@ -172,11 +265,11 @@ typedef void (*grpc_credentials_plugin_metadata_cb)(
    every call in scope for the credentials created from it. */
 typedef struct {
   /* The implementation of this method has to be non-blocking.
-     - service_url is the fully qualified URL that the client stack is
-       connecting to.
+     - context is the information that can be used by the plugin to create auth
+       metadata.
      - cb is the callback that needs to be called when the metadata is ready.
      - user_data needs to be passed as the first parameter of the callback. */
-  void (*get_metadata)(void *state, const char *service_url,
+  void (*get_metadata)(void *state, grpc_auth_metadata_context context,
                        grpc_credentials_plugin_metadata_cb cb, void *user_data);
 
   /* Destroys the plugin state. */
@@ -184,6 +277,9 @@ typedef struct {
 
   /* State that will be set as the first parameter of the methods above. */
   void *state;
+
+  /* Type of credentials that this plugin is implementing. */
+  const char *type;
 } grpc_metadata_credentials_plugin;
 
 /* Creates a credentials object from a plugin. */
@@ -239,81 +335,6 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
 grpc_call_error grpc_call_set_credentials(grpc_call *call,
                                           grpc_call_credentials *creds);
 
-/* --- Authentication Context. --- */
-
-#define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME "transport_security_type"
-#define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl"
-
-#define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"
-#define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
-
-typedef struct grpc_auth_context grpc_auth_context;
-
-typedef struct grpc_auth_property_iterator {
-  const grpc_auth_context *ctx;
-  size_t index;
-  const char *name;
-} grpc_auth_property_iterator;
-
-/* value, if not NULL, is guaranteed to be NULL terminated. */
-typedef struct grpc_auth_property {
-  char *name;
-  char *value;
-  size_t value_length;
-} grpc_auth_property;
-
-/* Returns NULL when the iterator is at the end. */
-const grpc_auth_property *grpc_auth_property_iterator_next(
-    grpc_auth_property_iterator *it);
-
-/* Iterates over the auth context. */
-grpc_auth_property_iterator grpc_auth_context_property_iterator(
-    const grpc_auth_context *ctx);
-
-/* Gets the peer identity. Returns an empty iterator (first _next will return
-   NULL) if the peer is not authenticated. */
-grpc_auth_property_iterator grpc_auth_context_peer_identity(
-    const grpc_auth_context *ctx);
-
-/* Finds a property in the context. May return an empty iterator (first _next
-   will return NULL) if no property with this name was found in the context. */
-grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
-    const grpc_auth_context *ctx, const char *name);
-
-/* Gets the name of the property that indicates the peer identity. Will return
-   NULL if the peer is not authenticated. */
-const char *grpc_auth_context_peer_identity_property_name(
-    const grpc_auth_context *ctx);
-
-/* Returns 1 if the peer is authenticated, 0 otherwise. */
-int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx);
-
-/* Gets the auth context from the call. Caller needs to call
-   grpc_auth_context_release on the returned context. */
-grpc_auth_context *grpc_call_auth_context(grpc_call *call);
-
-/* Releases the auth context returned from grpc_call_auth_context. */
-void grpc_auth_context_release(grpc_auth_context *context);
-
-/* --
-   The following auth context methods should only be called by a server metadata
-   processor to set properties extracted from auth metadata.
-   -- */
-
-/* Add a property. */
-void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name,
-                                    const char *value, size_t value_length);
-
-/* Add a C string property. */
-void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx,
-                                            const char *name,
-                                            const char *value);
-
-/* Sets the property name. Returns 1 if successful or 0 in case of failure
-   (which means that no property with this name exists). */
-int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx,
-                                                      const char *name);
-
 /* --- Auth Metadata Processing --- */
 
 /* Callback function that is called when the metadata processing is done.

+ 14 - 0
include/grpc/support/alloc.h

@@ -40,6 +40,12 @@
 extern "C" {
 #endif
 
+typedef struct gpr_allocation_functions {
+  void *(*malloc_fn)(size_t size);
+  void *(*realloc_fn)(void *ptr, size_t size);
+  void (*free_fn)(void *ptr);
+} gpr_allocation_functions;
+
 /* malloc, never returns NULL */
 void *gpr_malloc(size_t size);
 /* free */
@@ -51,6 +57,14 @@ void *gpr_malloc_aligned(size_t size, size_t alignment_log);
 /* free memory allocated by gpr_malloc_aligned */
 void gpr_free_aligned(void *ptr);
 
+/** Request the family of allocation functions in \a functions be used. NOTE
+ * that this request will be honored in a *best effort* basis and that no
+ * guarantees are made about the default functions (eg, malloc) being called. */
+void gpr_set_allocation_functions(gpr_allocation_functions functions);
+
+/** Return the family of allocation functions currently in effect. */
+gpr_allocation_functions gpr_get_allocation_functions();
+
 #ifdef __cplusplus
 }
 #endif

+ 6 - 2
include/grpc/support/cmdline.h

@@ -83,8 +83,12 @@ void gpr_cmdline_add_string(gpr_cmdline *cl, const char *name, const char *help,
 void gpr_cmdline_on_extra_arg(
     gpr_cmdline *cl, const char *name, const char *help,
     void (*on_extra_arg)(void *user_data, const char *arg), void *user_data);
-/* Parse the command line */
-void gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv);
+/* Enable surviving failure: default behavior is to exit the process */
+void gpr_cmdline_set_survive_failure(gpr_cmdline *cl);
+/* Parse the command line; returns 1 on success, on failure either dies
+   (by default) or returns 0 if gpr_cmdline_set_survive_failure() has been
+   called */
+int gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv);
 /* Destroy the parser */
 void gpr_cmdline_destroy(gpr_cmdline *cl);
 /* Get a string describing usage */

+ 7 - 2
include/grpc/support/port_platform.h

@@ -183,7 +183,7 @@
 #endif
 #define GPR_MSG_IOVLEN_TYPE int
 #if TARGET_OS_IPHONE
-#define GPR_FORBID_UNREACHABLE_CODE
+#define GPR_FORBID_UNREACHABLE_CODE 1
 #define GPR_PLATFORM_STRING "ios"
 #define GPR_CPU_IPHONE 1
 #define GPR_PTHREAD_TLS 1
@@ -252,6 +252,11 @@
 #define GPR_PLATFORM_STRING "unknown"
 #endif
 
+#ifdef GPR_GCOV
+#undef GPR_FORBID_UNREACHABLE_CODE
+#define GPR_FORBID_UNREACHABLE_CODE 1
+#endif
+
 /* For a common case, assume that the platform has a C99-like stdint.h */
 
 #include <stdint.h>
@@ -337,7 +342,7 @@ typedef uintptr_t gpr_uintptr;
 #endif
 #endif
 
-#ifdef GPR_FORBID_UNREACHABLE_CODE
+#if GPR_FORBID_UNREACHABLE_CODE
 #define GPR_UNREACHABLE_CODE(STATEMENT)
 #else
 #define GPR_UNREACHABLE_CODE(STATEMENT)             \

+ 2 - 2
include/grpc/support/time.h

@@ -61,8 +61,8 @@ typedef enum {
 } gpr_clock_type;
 
 typedef struct gpr_timespec {
-  time_t tv_sec;
-  int tv_nsec;
+  gpr_int64 tv_sec;
+  gpr_int32 tv_nsec;
   /** Against which clock was this time measured? (or GPR_TIMESPAN if
       this is a relative time meaure) */
   gpr_clock_type clock_type;

+ 3 - 2
package.json

@@ -1,6 +1,6 @@
 {
   "name": "grpc",
-  "version": "0.11.1",
+  "version": "0.12.0",
   "author": "Google Inc.",
   "description": "gRPC Library for Node",
   "homepage": "http://www.grpc.io/",
@@ -39,7 +39,8 @@
     "minimist": "^1.1.0",
     "mocha": "~1.21.0",
     "mocha-jenkins-reporter": "^0.1.9",
-    "mustache": "^2.0.0"
+    "mustache": "^2.0.0",
+    "poisson-process": "^0.2.1"
   },
   "engines": {
     "node": ">=0.10.13"

+ 3 - 5
src/core/census/context.h

@@ -36,14 +36,12 @@
 
 #include <grpc/census.h>
 
+#define GRPC_CENSUS_MAX_ON_THE_WIRE_TAG_BYTES 2048
+
 /* census_context is the in-memory representation of information needed to
  * maintain tracing, RPC statistics and resource usage information. */
 struct census_context {
-  gpr_uint64 op_id;    /* Operation identifier - unique per-context */
-  gpr_uint64 trace_id; /* Globally unique trace identifier */
-                       /* TODO(aveitch) Add census tags:
-                          const census_tag_set *tags;
-                        */
+  census_tag_set *tags; /* Opaque data structure for census tags. */
 };
 
 #endif /* GRPC_INTERNAL_CORE_CENSUS_CONTEXT_H */

+ 4 - 2
src/core/census/grpc_filter.c

@@ -43,7 +43,6 @@
 #include <grpc/support/time.h>
 
 #include "src/core/channel/channel_stack.h"
-#include "src/core/channel/noop_filter.h"
 #include "src/core/statistics/census_interface.h"
 #include "src/core/statistics/census_rpc_stats.h"
 #include "src/core/transport/static_metadata.h"
@@ -116,8 +115,11 @@ static void server_mutate_op(grpc_call_element *elem,
 static void server_start_transport_op(grpc_exec_ctx *exec_ctx,
                                       grpc_call_element *elem,
                                       grpc_transport_stream_op *op) {
+  /* TODO(ctiller): this code fails. I don't know why. I expect it's
+                    incomplete, and someone should look at it soon.
+
   call_data *calld = elem->call_data;
-  GPR_ASSERT((calld->op_id.upper != 0) || (calld->op_id.lower != 0));
+  GPR_ASSERT((calld->op_id.upper != 0) || (calld->op_id.lower != 0)); */
   server_mutate_op(elem, op);
   grpc_call_next_op(exec_ctx, elem, op);
 }

+ 16 - 1
src/core/channel/client_channel.c

@@ -124,6 +124,8 @@ static void on_lb_policy_state_changed_locked(
       w->chand->resolver != NULL) {
     publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
     grpc_resolver_channel_saw_error(exec_ctx, w->chand->resolver);
+    GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
+    w->chand->lb_policy = NULL;
   }
   grpc_connectivity_state_set(exec_ctx, &w->chand->state_tracker, publish_state,
                               "lb_changed");
@@ -250,7 +252,10 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
   grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, 1);
 
   GPR_ASSERT(op->set_accept_stream == NULL);
-  GPR_ASSERT(op->bind_pollset == NULL);
+  if (op->bind_pollset != NULL) {
+    grpc_pollset_set_add_pollset(exec_ctx, &chand->interested_parties,
+                                 op->bind_pollset);
+  }
 
   gpr_mu_lock(&chand->mu_config);
   if (op->on_connectivity_state_change != NULL) {
@@ -261,6 +266,16 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
     op->connectivity_state = NULL;
   }
 
+  if (op->send_ping != NULL) {
+    if (chand->lb_policy == NULL) {
+      grpc_exec_ctx_enqueue(exec_ctx, op->send_ping, 0);
+    } else {
+      grpc_lb_policy_ping_one(exec_ctx, chand->lb_policy, op->send_ping);
+      op->bind_pollset = NULL;
+    }
+    op->send_ping = NULL;
+  }
+
   if (op->disconnect && chand->resolver != NULL) {
     grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
                                 GRPC_CHANNEL_FATAL_FAILURE, "disconnect");

+ 2 - 2
src/core/channel/compress_filter.c

@@ -39,11 +39,11 @@
 #include <grpc/support/log.h>
 #include <grpc/support/slice_buffer.h>
 
-#include "src/core/channel/compress_filter.h"
 #include "src/core/channel/channel_args.h"
-#include "src/core/profiling/timers.h"
+#include "src/core/channel/compress_filter.h"
 #include "src/core/compression/algorithm_metadata.h"
 #include "src/core/compression/message_compress.h"
+#include "src/core/profiling/timers.h"
 #include "src/core/support/string.h"
 #include "src/core/transport/static_metadata.h"
 

+ 2 - 2
src/core/channel/http_client_filter.c

@@ -31,12 +31,12 @@
  */
 
 #include "src/core/channel/http_client_filter.h"
-#include <string.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
-#include "src/core/support/string.h"
+#include <string.h>
 #include "src/core/profiling/timers.h"
+#include "src/core/support/string.h"
 #include "src/core/transport/static_metadata.h"
 
 typedef struct call_data {

+ 1 - 2
src/core/channel/http_server_filter.c

@@ -33,9 +33,9 @@
 
 #include "src/core/channel/http_server_filter.h"
 
-#include <string.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <string.h>
 #include "src/core/profiling/timers.h"
 #include "src/core/transport/static_metadata.h"
 
@@ -124,7 +124,6 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
        omitted */
     grpc_mdelem *authority = grpc_mdelem_from_metadata_strings(
         GRPC_MDSTR_AUTHORITY, GRPC_MDSTR_REF(md->value));
-    GRPC_MDELEM_UNREF(md);
     calld->seen_authority = 1;
     return authority;
   } else {

+ 0 - 118
src/core/channel/noop_filter.c

@@ -1,118 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "src/core/channel/noop_filter.h"
-#include <grpc/support/log.h>
-
-typedef struct call_data {
-  int unused; /* C89 requires at least one struct element */
-} call_data;
-
-typedef struct channel_data {
-  int unused; /* C89 requires at least one struct element */
-} channel_data;
-
-/* used to silence 'variable not used' warnings */
-static void ignore_unused(void *ignored) {}
-
-static void noop_mutate_op(grpc_call_element *elem,
-                           grpc_transport_stream_op *op) {
-  /* grab pointers to our data from the call element */
-  call_data *calld = elem->call_data;
-  channel_data *channeld = elem->channel_data;
-
-  ignore_unused(calld);
-  ignore_unused(channeld);
-
-  /* do nothing */
-}
-
-/* Called either:
-     - in response to an API call (or similar) from above, to send something
-     - a network event (or similar) from below, to receive something
-   op contains type and call direction information, in addition to the data
-   that is being sent or received. */
-static void noop_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
-                                           grpc_call_element *elem,
-                                           grpc_transport_stream_op *op) {
-  noop_mutate_op(elem, op);
-
-  /* pass control down the stack */
-  grpc_call_next_op(exec_ctx, elem, op);
-}
-
-/* Constructor for call_data */
-static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
-                           grpc_call_element_args *args) {
-  /* grab pointers to our data from the call element */
-  call_data *calld = elem->call_data;
-  channel_data *channeld = elem->channel_data;
-
-  /* initialize members */
-  calld->unused = channeld->unused;
-}
-
-/* Destructor for call_data */
-static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_call_element *elem) {}
-
-/* Constructor for channel_data */
-static void init_channel_elem(grpc_exec_ctx *exec_ctx,
-                              grpc_channel_element *elem,
-                              grpc_channel_element_args *args) {
-  /* grab pointers to our data from the channel element */
-  channel_data *channeld = elem->channel_data;
-
-  /* The last filter tends to be implemented differently to
-     handle the case that there's no 'next' filter to call on the down
-     path */
-  GPR_ASSERT(!args->is_last);
-
-  /* initialize members */
-  channeld->unused = 0;
-}
-
-/* Destructor for channel data */
-static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
-                                 grpc_channel_element *elem) {
-  /* grab pointers to our data from the channel element */
-  channel_data *channeld = elem->channel_data;
-
-  ignore_unused(channeld);
-}
-
-const grpc_channel_filter grpc_no_op_filter = {
-    noop_start_transport_stream_op, grpc_channel_next_op, sizeof(call_data),
-    init_call_elem, grpc_call_stack_ignore_set_pollset, destroy_call_elem,
-    sizeof(channel_data), init_channel_elem, destroy_channel_elem,
-    grpc_call_next_get_peer, "no-op"};

+ 2 - 2
src/core/channel/subchannel_call_holder.c

@@ -155,7 +155,7 @@ retry:
       holder->connected_subchannel != NULL) {
     gpr_atm_rel_store(
         &holder->subchannel_call,
-        grpc_connected_subchannel_create_call(
+        (gpr_atm)(gpr_uintptr)grpc_connected_subchannel_create_call(
             exec_ctx, holder->connected_subchannel, holder->pollset));
     retry_waiting_locked(exec_ctx, holder);
     goto retry;
@@ -180,7 +180,7 @@ static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, int success) {
   } else {
     gpr_atm_rel_store(
         &holder->subchannel_call,
-        grpc_connected_subchannel_create_call(
+        (gpr_atm)(gpr_uintptr)grpc_connected_subchannel_create_call(
             exec_ctx, holder->connected_subchannel, holder->pollset));
     retry_waiting_locked(exec_ctx, holder);
   }

+ 13 - 1
src/core/client_config/lb_policies/pick_first.c

@@ -360,8 +360,20 @@ void pf_notify_on_state_change(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
   gpr_mu_unlock(&p->mu);
 }
 
+void pf_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                 grpc_closure *closure) {
+  pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
+  gpr_mu_lock(&p->mu);
+  if (p->selected) {
+    grpc_connected_subchannel_ping(exec_ctx, p->selected, closure);
+  } else {
+    grpc_exec_ctx_enqueue(exec_ctx, closure, 0);
+  }
+  gpr_mu_unlock(&p->mu);
+}
+
 static const grpc_lb_policy_vtable pick_first_lb_policy_vtable = {
-    pf_destroy, pf_shutdown, pf_pick, pf_cancel_pick, pf_exit_idle,
+    pf_destroy, pf_shutdown, pf_pick, pf_cancel_pick, pf_ping_one, pf_exit_idle,
     pf_check_connectivity, pf_notify_on_state_change};
 
 static void pick_first_factory_ref(grpc_lb_policy_factory *factory) {}

+ 17 - 1
src/core/client_config/lb_policies/round_robin.c

@@ -467,8 +467,24 @@ static void rr_notify_on_state_change(grpc_exec_ctx *exec_ctx,
   gpr_mu_unlock(&p->mu);
 }
 
+static void rr_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+                        grpc_closure *closure) {
+  round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
+  ready_list *selected;
+  grpc_connected_subchannel *target;
+  gpr_mu_lock(&p->mu);
+  if ((selected = peek_next_connected_locked(p))) {
+    gpr_mu_unlock(&p->mu);
+    target = grpc_subchannel_get_connected_subchannel(selected->subchannel);
+    grpc_connected_subchannel_ping(exec_ctx, target, closure);
+  } else {
+    gpr_mu_unlock(&p->mu);
+    grpc_exec_ctx_enqueue(exec_ctx, closure, 0);
+  }
+}
+
 static const grpc_lb_policy_vtable round_robin_lb_policy_vtable = {
-    rr_destroy, rr_shutdown, rr_pick, rr_cancel_pick, rr_exit_idle,
+    rr_destroy, rr_shutdown, rr_pick, rr_cancel_pick, rr_ping_one, rr_exit_idle,
     rr_check_connectivity, rr_notify_on_state_change};
 
 static void round_robin_factory_ref(grpc_lb_policy_factory *factory) {}

+ 5 - 0
src/core/client_config/lb_policy.c

@@ -116,6 +116,11 @@ void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) {
   policy->vtable->exit_idle(exec_ctx, policy);
 }
 
+void grpc_lb_policy_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                             grpc_closure *closure) {
+  policy->vtable->ping_one(exec_ctx, policy, closure);
+}
+
 void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx,
                                            grpc_lb_policy *policy,
                                            grpc_connectivity_state *state,

+ 6 - 0
src/core/client_config/lb_policy.h

@@ -63,6 +63,9 @@ struct grpc_lb_policy_vtable {
   void (*cancel_pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
                       grpc_connected_subchannel **target);
 
+  void (*ping_one)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                   grpc_closure *closure);
+
   /** try to enter a READY connectivity state */
   void (*exit_idle)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
 
@@ -121,6 +124,9 @@ int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
                         grpc_connected_subchannel **target,
                         grpc_closure *on_complete);
 
+void grpc_lb_policy_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+                             grpc_closure *closure);
+
 void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
                                 grpc_connected_subchannel **target);
 

+ 0 - 1
src/core/client_config/resolvers/dns_resolver.c

@@ -40,7 +40,6 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/client_config/lb_policy_registry.h"
-#include "src/core/client_config/subchannel_factory_decorators/add_channel_arg.h"
 #include "src/core/iomgr/resolve_address.h"
 #include "src/core/support/string.h"
 

+ 3 - 0
src/core/client_config/resolvers/sockaddr_resolver.c

@@ -347,6 +347,9 @@ static grpc_resolver *sockaddr_create(
   gpr_slice_buffer_destroy(&path_parts);
   gpr_slice_unref(path_slice);
   if (errors_found) {
+    gpr_free(r->lb_policy_name);
+    gpr_free(r->addrs);
+    gpr_free(r->addrs_len);
     gpr_free(r);
     return NULL;
   }

+ 2 - 5
src/core/client_config/resolvers/zookeeper_resolver.c

@@ -96,9 +96,7 @@ static void zookeeper_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
 
 static void zookeeper_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
 static void zookeeper_channel_saw_error(grpc_exec_ctx *exec_ctx,
-                                        grpc_resolver *r,
-                                        struct sockaddr *failing_address,
-                                        int failing_address_len);
+                                        grpc_resolver *r);
 static void zookeeper_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
                            grpc_client_config **target_config,
                            grpc_closure *on_complete);
@@ -125,8 +123,7 @@ static void zookeeper_shutdown(grpc_exec_ctx *exec_ctx,
 }
 
 static void zookeeper_channel_saw_error(grpc_exec_ctx *exec_ctx,
-                                        grpc_resolver *resolver,
-                                        struct sockaddr *sa, int len) {
+                                        grpc_resolver *resolver) {
   zookeeper_resolver *r = (zookeeper_resolver *)resolver;
   gpr_mu_lock(&r->mu);
   if (r->resolving == 0) {

+ 11 - 0
src/core/client_config/subchannel.c

@@ -461,6 +461,17 @@ void grpc_connected_subchannel_notify_on_state_change(
                                 closure);
 }
 
+void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx,
+                                    grpc_connected_subchannel *con,
+                                    grpc_closure *closure) {
+  grpc_transport_op op;
+  grpc_channel_element *elem;
+  memset(&op, 0, sizeof(op));
+  op.send_ping = closure;
+  elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0);
+  elem->filter->start_transport_op(exec_ctx, elem, &op);
+}
+
 static void publish_transport(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
   size_t channel_stack_size;
   grpc_connected_subchannel *con;

+ 3 - 0
src/core/client_config/subchannel.h

@@ -124,6 +124,9 @@ void grpc_connected_subchannel_notify_on_state_change(
     grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *channel,
     grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
     grpc_closure *notify);
+void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx,
+                                    grpc_connected_subchannel *channel,
+                                    grpc_closure *notify);
 
 /** retrieve the grpc_connected_subchannel - or NULL if called before
     the subchannel becomes connected */

+ 0 - 86
src/core/client_config/subchannel_factory_decorators/merge_channel_args.c

@@ -1,86 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "src/core/client_config/subchannel_factory_decorators/merge_channel_args.h"
-#include <grpc/support/alloc.h>
-#include "src/core/channel/channel_args.h"
-
-typedef struct {
-  grpc_subchannel_factory base;
-  gpr_refcount refs;
-  grpc_subchannel_factory *wrapped;
-  grpc_channel_args *merge_args;
-} merge_args_factory;
-
-static void merge_args_factory_ref(grpc_subchannel_factory *scf) {
-  merge_args_factory *f = (merge_args_factory *)scf;
-  gpr_ref(&f->refs);
-}
-
-static void merge_args_factory_unref(grpc_exec_ctx *exec_ctx,
-                                     grpc_subchannel_factory *scf) {
-  merge_args_factory *f = (merge_args_factory *)scf;
-  if (gpr_unref(&f->refs)) {
-    grpc_subchannel_factory_unref(exec_ctx, f->wrapped);
-    grpc_channel_args_destroy(f->merge_args);
-    gpr_free(f);
-  }
-}
-
-static grpc_subchannel *merge_args_factory_create_subchannel(
-    grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf,
-    grpc_subchannel_args *args) {
-  merge_args_factory *f = (merge_args_factory *)scf;
-  grpc_channel_args *final_args =
-      grpc_channel_args_merge(args->args, f->merge_args);
-  grpc_subchannel *s;
-  args->args = final_args;
-  s = grpc_subchannel_factory_create_subchannel(exec_ctx, f->wrapped, args);
-  grpc_channel_args_destroy(final_args);
-  return s;
-}
-
-static const grpc_subchannel_factory_vtable merge_args_factory_vtable = {
-    merge_args_factory_ref, merge_args_factory_unref,
-    merge_args_factory_create_subchannel};
-
-grpc_subchannel_factory *grpc_subchannel_factory_merge_channel_args(
-    grpc_subchannel_factory *input, const grpc_channel_args *args) {
-  merge_args_factory *f = gpr_malloc(sizeof(*f));
-  f->base.vtable = &merge_args_factory_vtable;
-  gpr_ref_init(&f->refs, 1);
-  grpc_subchannel_factory_ref(input);
-  f->wrapped = input;
-  f->merge_args = grpc_channel_args_copy(args);
-  return &f->base;
-}

+ 0 - 46
src/core/client_config/subchannel_factory_decorators/merge_channel_args.h

@@ -1,46 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_MERGE_CHANNEL_ARGS_H
-#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_MERGE_CHANNEL_ARGS_H
-
-#include "src/core/client_config/subchannel_factory.h"
-
-/** Takes a subchannel factory, returns a new one that mutates incoming
-    channel_args by adding a new argument; ownership of input, args is retained
-    by the caller. */
-grpc_subchannel_factory *grpc_subchannel_factory_merge_channel_args(
-    grpc_subchannel_factory *input, const grpc_channel_args *args);
-
-#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_MERGE_CHANNEL_ARGS_H \
-        */

+ 4 - 20
src/core/compression/algorithm.c

@@ -119,8 +119,8 @@ grpc_mdelem *grpc_compression_encoding_mdelem(
       return GRPC_MDELEM_GRPC_ENCODING_DEFLATE;
     case GRPC_COMPRESS_GZIP:
       return GRPC_MDELEM_GRPC_ENCODING_GZIP;
-    case GRPC_COMPRESS_ALGORITHMS_COUNT:
-      return NULL;
+    default:
+      break;
   }
   return NULL;
 }
@@ -139,25 +139,9 @@ grpc_compression_algorithm grpc_compression_algorithm_for_level(
     case GRPC_COMPRESS_LEVEL_HIGH:
       return GRPC_COMPRESS_DEFLATE;
     default:
-      /* we shouldn't be making it here */
-      abort();
-      return GRPC_COMPRESS_NONE;
-  }
-}
-
-grpc_compression_level grpc_compression_level_for_algorithm(
-    grpc_compression_algorithm algorithm) {
-  grpc_compression_level clevel;
-  GRPC_API_TRACE("grpc_compression_level_for_algorithm(algorithm=%d)", 1,
-                 ((int)algorithm));
-  for (clevel = GRPC_COMPRESS_LEVEL_NONE; clevel < GRPC_COMPRESS_LEVEL_COUNT;
-       ++clevel) {
-    if (grpc_compression_algorithm_for_level(clevel) == algorithm) {
-      return clevel;
-    }
+      break;
   }
-  abort();
-  return GRPC_COMPRESS_LEVEL_NONE;
+  GPR_UNREACHABLE_CODE(return GRPC_COMPRESS_NONE);
 }
 
 void grpc_compression_options_init(grpc_compression_options *opts) {

+ 16 - 12
src/core/compression/message_compress.c

@@ -69,8 +69,8 @@ static int zlib_body(z_stream* zs, gpr_slice_buffer* input,
         zs->next_out = GPR_SLICE_START_PTR(outbuf);
       }
       r = flate(zs, flush);
-      if (r == Z_STREAM_ERROR) {
-        gpr_log(GPR_INFO, "zlib: stream error");
+      if (r < 0 && r != Z_BUF_ERROR /* not fatal */) {
+        gpr_log(GPR_INFO, "zlib error (%d)", r);
         goto error;
       }
     } while (zs->avail_out == 0);
@@ -91,6 +91,12 @@ error:
   return 0;
 }
 
+static void* zalloc_gpr(void* opaque, unsigned int items, unsigned int size) {
+  return gpr_malloc(items * size);
+}
+
+static void zfree_gpr(void* opaque, void* address) { gpr_free(address); }
+
 static int zlib_compress(gpr_slice_buffer* input, gpr_slice_buffer* output,
                          int gzip) {
   z_stream zs;
@@ -99,12 +105,11 @@ static int zlib_compress(gpr_slice_buffer* input, gpr_slice_buffer* output,
   size_t count_before = output->count;
   size_t length_before = output->length;
   memset(&zs, 0, sizeof(zs));
+  zs.zalloc = zalloc_gpr;
+  zs.zfree = zfree_gpr;
   r = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 | (gzip ? 16 : 0),
                    8, Z_DEFAULT_STRATEGY);
-  if (r != Z_OK) {
-    gpr_log(GPR_ERROR, "deflateInit2 returns %d", r);
-    return 0;
-  }
+  GPR_ASSERT(r == Z_OK);
   r = zlib_body(&zs, input, output, deflate) && output->length < input->length;
   if (!r) {
     for (i = count_before; i < output->count; i++) {
@@ -125,11 +130,10 @@ static int zlib_decompress(gpr_slice_buffer* input, gpr_slice_buffer* output,
   size_t count_before = output->count;
   size_t length_before = output->length;
   memset(&zs, 0, sizeof(zs));
+  zs.zalloc = zalloc_gpr;
+  zs.zfree = zfree_gpr;
   r = inflateInit2(&zs, 15 | (gzip ? 16 : 0));
-  if (r != Z_OK) {
-    gpr_log(GPR_ERROR, "inflateInit2 returns %d", r);
-    return 0;
-  }
+  GPR_ASSERT(r == Z_OK);
   r = zlib_body(&zs, input, output, inflate);
   if (!r) {
     for (i = count_before; i < output->count; i++) {
@@ -150,8 +154,8 @@ static int copy(gpr_slice_buffer* input, gpr_slice_buffer* output) {
   return 1;
 }
 
-int compress_inner(grpc_compression_algorithm algorithm,
-                   gpr_slice_buffer* input, gpr_slice_buffer* output) {
+static int compress_inner(grpc_compression_algorithm algorithm,
+                          gpr_slice_buffer* input, gpr_slice_buffer* output) {
   switch (algorithm) {
     case GRPC_COMPRESS_NONE:
       /* the fallback path always needs to be send uncompressed: we simply

+ 7 - 2
src/core/httpcli/httpcli.c

@@ -53,6 +53,7 @@ typedef struct {
   size_t next_address;
   grpc_endpoint *ep;
   char *host;
+  char *ssl_host_override;
   gpr_timespec deadline;
   int have_read_byte;
   const grpc_httpcli_handshaker *handshaker;
@@ -106,6 +107,7 @@ static void finish(grpc_exec_ctx *exec_ctx, internal_request *req,
   }
   gpr_slice_unref(req->request_text);
   gpr_free(req->host);
+  gpr_free(req->ssl_host_override);
   grpc_iomgr_unregister_object(&req->iomgr_obj);
   gpr_slice_buffer_destroy(&req->incoming);
   gpr_slice_buffer_destroy(&req->outgoing);
@@ -180,8 +182,10 @@ static void on_connected(grpc_exec_ctx *exec_ctx, void *arg, int success) {
     next_address(exec_ctx, req);
     return;
   }
-  req->handshaker->handshake(exec_ctx, req, req->ep, req->host,
-                             on_handshake_done);
+  req->handshaker->handshake(
+      exec_ctx, req, req->ep,
+      req->ssl_host_override ? req->ssl_host_override : req->host,
+      on_handshake_done);
 }
 
 static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req) {
@@ -231,6 +235,7 @@ static void internal_request_begin(
   gpr_slice_buffer_init(&req->outgoing);
   grpc_iomgr_register_object(&req->iomgr_obj, name);
   req->host = gpr_strdup(request->host);
+  req->ssl_host_override = gpr_strdup(request->ssl_host_override);
 
   grpc_pollset_set_add_pollset(exec_ctx, &req->context->pollset_set,
                                req->pollset);

+ 2 - 0
src/core/httpcli/httpcli.h

@@ -74,6 +74,8 @@ extern const grpc_httpcli_handshaker grpc_httpcli_ssl;
 typedef struct grpc_httpcli_request {
   /* The host name to connect to */
   char *host;
+  /* The host to verify in the SSL handshake (or NULL) */
+  char *ssl_host_override;
   /* The path of the resource to fetch */
   char *path;
   /* Additional headers: count and key/values; the following are supplied

+ 2 - 3
src/core/httpcli/httpcli_security_connector.c

@@ -68,7 +68,7 @@ static void httpcli_ssl_do_handshake(grpc_exec_ctx *exec_ctx,
   tsi_result result = TSI_OK;
   tsi_handshaker *handshaker;
   if (c->handshaker_factory == NULL) {
-    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, nonsecure_endpoint, NULL);
+    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL);
     return;
   }
   result = tsi_ssl_handshaker_factory_create_handshaker(
@@ -76,7 +76,7 @@ static void httpcli_ssl_do_handshake(grpc_exec_ctx *exec_ctx,
   if (result != TSI_OK) {
     gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
             tsi_result_to_string(result));
-    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, nonsecure_endpoint, NULL);
+    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL);
   } else {
     grpc_do_security_handshake(exec_ctx, handshaker, sc, nonsecure_endpoint, cb,
                                user_data);
@@ -149,7 +149,6 @@ typedef struct {
 
 static void on_secure_transport_setup_done(grpc_exec_ctx *exec_ctx, void *rp,
                                            grpc_security_status status,
-                                           grpc_endpoint *wrapped_endpoint,
                                            grpc_endpoint *secure_endpoint) {
   on_done_closure *c = rp;
   if (status != GRPC_SECURITY_OK) {

+ 3 - 0
src/core/iomgr/endpoint_pair_posix.c

@@ -36,6 +36,7 @@
 #ifdef GPR_POSIX_SOCKET
 
 #include "src/core/iomgr/endpoint_pair.h"
+#include "src/core/iomgr/socket_utils_posix.h"
 
 #include <errno.h>
 #include <fcntl.h>
@@ -56,6 +57,8 @@ static void create_sockets(int sv[2]) {
   GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0);
   flags = fcntl(sv[1], F_GETFL, 0);
   GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0);
+  GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[0]));
+  GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[1]));
 }
 
 grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name,

+ 13 - 4
src/core/iomgr/fd_posix.c

@@ -211,14 +211,21 @@ static int has_watchers(grpc_fd *fd) {
 }
 
 void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
-                    const char *reason) {
+                    int *release_fd, const char *reason) {
   fd->on_done_closure = on_done;
-  shutdown(fd->fd, SHUT_RDWR);
+  fd->released = release_fd != NULL;
+  if (!fd->released) {
+    shutdown(fd->fd, SHUT_RDWR);
+  } else {
+    *release_fd = fd->fd;
+  }
   gpr_mu_lock(&fd->mu);
   REF_BY(fd, 1, reason); /* remove active status, but keep referenced */
   if (!has_watchers(fd)) {
     fd->closed = 1;
-    close(fd->fd);
+    if (!fd->released) {
+      close(fd->fd);
+    }
     grpc_exec_ctx_enqueue(exec_ctx, fd->on_done_closure, 1);
   } else {
     wake_all_watchers_locked(fd);
@@ -410,7 +417,9 @@ void grpc_fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *watcher,
   }
   if (grpc_fd_is_orphaned(fd) && !has_watchers(fd) && !fd->closed) {
     fd->closed = 1;
-    close(fd->fd);
+    if (!fd->released) {
+      close(fd->fd);
+    }
     grpc_exec_ctx_enqueue(exec_ctx, fd->on_done_closure, 1);
   }
   gpr_mu_unlock(&fd->mu);

+ 3 - 1
src/core/iomgr/fd_posix.h

@@ -62,6 +62,7 @@ struct grpc_fd {
   gpr_mu mu;
   int shutdown;
   int closed;
+  int released;
 
   /* The watcher list.
 
@@ -107,11 +108,12 @@ grpc_fd *grpc_fd_create(int fd, const char *name);
 /* Releases fd to be asynchronously destroyed.
    on_done is called when the underlying file descriptor is definitely close()d.
    If on_done is NULL, no callback will be made.
+   If release_fd is not NULL, it's set to fd and fd will not be closed.
    Requires: *fd initialized; no outstanding notify_on_read or
    notify_on_write.
    MUST NOT be called with a pollset lock taken */
 void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
-                    const char *reason);
+                    int *release_fd, const char *reason);
 
 /* Begin polling on an fd.
    Registers that the given pollset is interested in this fd - so that if read

+ 0 - 1
src/core/iomgr/iomgr.c

@@ -116,7 +116,6 @@ void grpc_iomgr_shutdown(void) {
                     "memory leaks are likely",
                     count_objects());
             dump_objects("LEAKED");
-            abort();
           }
           break;
         }

+ 1 - 21
src/core/iomgr/pollset_multipoller_with_epoll.c

@@ -123,26 +123,6 @@ static void multipoll_with_epoll_pollset_add_fd(grpc_exec_ctx *exec_ctx,
   }
 }
 
-static void multipoll_with_epoll_pollset_del_fd(grpc_exec_ctx *exec_ctx,
-                                                grpc_pollset *pollset,
-                                                grpc_fd *fd,
-                                                int and_unlock_pollset) {
-  pollset_hdr *h = pollset->data.ptr;
-  int err;
-
-  if (and_unlock_pollset) {
-    gpr_mu_unlock(&pollset->mu);
-  }
-
-  /* Note that this can race with concurrent poll, but that should be fine since
-   * at worst it creates a spurious read event on a reused grpc_fd object. */
-  err = epoll_ctl(h->epoll_fd, EPOLL_CTL_DEL, fd->fd, NULL);
-  if (err < 0) {
-    gpr_log(GPR_ERROR, "epoll_ctl del for %d failed: %s", fd->fd,
-            strerror(errno));
-  }
-}
-
 /* TODO(klempner): We probably want to turn this down a bit */
 #define GRPC_EPOLL_MAX_EVENTS 1000
 
@@ -235,7 +215,7 @@ static void multipoll_with_epoll_pollset_destroy(grpc_pollset *pollset) {
 }
 
 static const grpc_pollset_vtable multipoll_with_epoll_pollset = {
-    multipoll_with_epoll_pollset_add_fd, multipoll_with_epoll_pollset_del_fd,
+    multipoll_with_epoll_pollset_add_fd,
     multipoll_with_epoll_pollset_maybe_work_and_unlock,
     multipoll_with_epoll_pollset_finish_shutdown,
     multipoll_with_epoll_pollset_destroy};

+ 1 - 18
src/core/iomgr/pollset_multipoller_with_poll_posix.c

@@ -82,23 +82,6 @@ exit:
   }
 }
 
-static void multipoll_with_poll_pollset_del_fd(grpc_exec_ctx *exec_ctx,
-                                               grpc_pollset *pollset,
-                                               grpc_fd *fd,
-                                               int and_unlock_pollset) {
-  /* will get removed next poll cycle */
-  pollset_hdr *h = pollset->data.ptr;
-  if (h->del_count == h->del_capacity) {
-    h->del_capacity = GPR_MAX(h->del_capacity + 8, h->del_count * 3 / 2);
-    h->dels = gpr_realloc(h->dels, sizeof(grpc_fd *) * h->del_capacity);
-  }
-  h->dels[h->del_count++] = fd;
-  GRPC_FD_REF(fd, "multipoller_del");
-  if (and_unlock_pollset) {
-    gpr_mu_unlock(&pollset->mu);
-  }
-}
-
 static void multipoll_with_poll_pollset_maybe_work_and_unlock(
     grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker,
     gpr_timespec deadline, gpr_timespec now) {
@@ -212,7 +195,7 @@ static void multipoll_with_poll_pollset_destroy(grpc_pollset *pollset) {
 }
 
 static const grpc_pollset_vtable multipoll_with_poll_pollset = {
-    multipoll_with_poll_pollset_add_fd, multipoll_with_poll_pollset_del_fd,
+    multipoll_with_poll_pollset_add_fd,
     multipoll_with_poll_pollset_maybe_work_and_unlock,
     multipoll_with_poll_pollset_finish_shutdown,
     multipoll_with_poll_pollset_destroy};

+ 6 - 32
src/core/iomgr/pollset_posix.c

@@ -232,21 +232,7 @@ void grpc_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
   gpr_mu_lock(&pollset->mu);
   pollset->vtable->add_fd(exec_ctx, pollset, fd, 1);
 /* the following (enabled only in debug) will reacquire and then release
-   our lock - meaning that if the unlocking flag passed to del_fd above is
-   not respected, the code will deadlock (in a way that we have a chance of
-   debugging) */
-#ifndef NDEBUG
-  gpr_mu_lock(&pollset->mu);
-  gpr_mu_unlock(&pollset->mu);
-#endif
-}
-
-void grpc_pollset_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                         grpc_fd *fd) {
-  gpr_mu_lock(&pollset->mu);
-  pollset->vtable->del_fd(exec_ctx, pollset, fd, 1);
-/* the following (enabled only in debug) will reacquire and then release
-   our lock - meaning that if the unlocking flag passed to del_fd above is
+   our lock - meaning that if the unlocking flag passed to add_fd above is
    not respected, the code will deadlock (in a way that we have a chance of
    debugging) */
 #ifndef NDEBUG
@@ -547,19 +533,6 @@ exit:
   }
 }
 
-static void basic_pollset_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                                 grpc_fd *fd, int and_unlock_pollset) {
-  GPR_ASSERT(fd);
-  if (fd == pollset->data.ptr) {
-    GRPC_FD_UNREF(pollset->data.ptr, "basicpoll");
-    pollset->data.ptr = NULL;
-  }
-
-  if (and_unlock_pollset) {
-    gpr_mu_unlock(&pollset->mu);
-  }
-}
-
 static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx,
                                                 grpc_pollset *pollset,
                                                 grpc_pollset_worker *worker,
@@ -613,7 +586,9 @@ static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx,
   GPR_TIMER_END("poll", 0);
 
   if (r < 0) {
-    gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
+    if (errno != EINTR) {
+      gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
+    }
     if (fd) {
       grpc_fd_end_poll(exec_ctx, &fd_watcher, 0, 0);
     }
@@ -649,9 +624,8 @@ static void basic_pollset_destroy(grpc_pollset *pollset) {
 }
 
 static const grpc_pollset_vtable basic_pollset = {
-    basic_pollset_add_fd, basic_pollset_del_fd,
-    basic_pollset_maybe_work_and_unlock, basic_pollset_destroy,
-    basic_pollset_destroy};
+    basic_pollset_add_fd, basic_pollset_maybe_work_and_unlock,
+    basic_pollset_destroy, basic_pollset_destroy};
 
 static void become_basic_pollset(grpc_pollset *pollset, grpc_fd *fd_or_null) {
   pollset->vtable = &basic_pollset;

+ 0 - 6
src/core/iomgr/pollset_posix.h

@@ -86,8 +86,6 @@ typedef struct grpc_pollset {
 struct grpc_pollset_vtable {
   void (*add_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                  struct grpc_fd *fd, int and_unlock_pollset);
-  void (*del_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                 struct grpc_fd *fd, int and_unlock_pollset);
   void (*maybe_work_and_unlock)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                                 grpc_pollset_worker *worker,
                                 gpr_timespec deadline, gpr_timespec now);
@@ -100,10 +98,6 @@ struct grpc_pollset_vtable {
 /* Add an fd to a pollset */
 void grpc_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                          struct grpc_fd *fd);
-/* Force remove an fd from a pollset (normally they are removed on the next
-   poll after an fd is orphaned) */
-void grpc_pollset_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                         struct grpc_fd *fd);
 
 /* Returns the fd to listen on for kicks */
 int grpc_kick_read_fd(grpc_pollset *p);

+ 2 - 2
src/core/iomgr/tcp_client_posix.c

@@ -196,7 +196,7 @@ static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, int success) {
 finish:
   if (fd != NULL) {
     grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
-    grpc_fd_orphan(exec_ctx, fd, NULL, "tcp_client_orphan");
+    grpc_fd_orphan(exec_ctx, fd, NULL, NULL, "tcp_client_orphan");
     fd = NULL;
   }
   done = (--ac->refs == 0);
@@ -265,7 +265,7 @@ void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
 
   if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
     gpr_log(GPR_ERROR, "connect error to '%s': %s", addr_str, strerror(errno));
-    grpc_fd_orphan(exec_ctx, fdobj, NULL, "tcp_client_connect_error");
+    grpc_fd_orphan(exec_ctx, fdobj, NULL, NULL, "tcp_client_connect_error");
     grpc_exec_ctx_enqueue(exec_ctx, closure, 0);
     goto done;
   }

+ 15 - 1
src/core/iomgr/tcp_posix.c

@@ -90,6 +90,8 @@ typedef struct {
 
   grpc_closure *read_cb;
   grpc_closure *write_cb;
+  grpc_closure *release_fd_cb;
+  int *release_fd;
 
   grpc_closure read_closure;
   grpc_closure write_closure;
@@ -108,7 +110,8 @@ static void tcp_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
 }
 
 static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
-  grpc_fd_orphan(exec_ctx, tcp->em_fd, NULL, "tcp_unref_orphan");
+  grpc_fd_orphan(exec_ctx, tcp->em_fd, tcp->release_fd_cb, tcp->release_fd,
+                 "tcp_unref_orphan");
   gpr_slice_buffer_destroy(&tcp->last_read_buffer);
   gpr_free(tcp->peer_string);
   gpr_free(tcp);
@@ -452,6 +455,8 @@ grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size,
   tcp->fd = em_fd->fd;
   tcp->read_cb = NULL;
   tcp->write_cb = NULL;
+  tcp->release_fd_cb = NULL;
+  tcp->release_fd = NULL;
   tcp->incoming_buffer = NULL;
   tcp->slice_size = slice_size;
   tcp->iov_size = 1;
@@ -468,4 +473,13 @@ grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size,
   return &tcp->base;
 }
 
+void grpc_tcp_destroy_and_release_fd(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                                     int *fd, grpc_closure *done) {
+  grpc_tcp *tcp = (grpc_tcp *)ep;
+  GPR_ASSERT(ep->vtable == &vtable);
+  tcp->release_fd = fd;
+  tcp->release_fd_cb = done;
+  TCP_UNREF(exec_ctx, tcp, "destroy");
+}
+
 #endif

+ 6 - 0
src/core/iomgr/tcp_posix.h

@@ -56,4 +56,10 @@ extern int grpc_tcp_trace;
 grpc_endpoint *grpc_tcp_create(grpc_fd *fd, size_t read_slice_size,
                                const char *peer_string);
 
+/* Destroy the tcp endpoint without closing its fd. *fd will be set and done
+ * will be called when the endpoint is destroyed.
+ * Requires: ep must be a tcp endpoint and fd must not be NULL. */
+void grpc_tcp_destroy_and_release_fd(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+                                     int *fd, grpc_closure *done);
+
 #endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_POSIX_H */

+ 11 - 9
src/core/iomgr/tcp_server_posix.c

@@ -193,7 +193,7 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
       }
       sp->destroyed_closure.cb = destroyed_port;
       sp->destroyed_closure.cb_arg = s;
-      grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure,
+      grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
                      "tcp_listener_shutdown");
     }
     gpr_mu_unlock(&s->mu);
@@ -411,7 +411,6 @@ static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, int fd,
 
 grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
                                             const void *addr, size_t addr_len) {
-  int allocated_port = -1;
   grpc_tcp_listener *sp;
   grpc_tcp_listener *sp2 = NULL;
   int fd;
@@ -464,14 +463,13 @@ grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
     addr_len = sizeof(wild6);
     fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
     sp = add_socket_to_server(s, fd, addr, addr_len);
-    allocated_port = sp->port;
     if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
       goto done;
     }
 
     /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
-    if (port == 0 && allocated_port > 0) {
-      grpc_sockaddr_set_port((struct sockaddr *)&wild4, allocated_port);
+    if (port == 0 && sp != NULL) {
+      grpc_sockaddr_set_port((struct sockaddr *)&wild4, sp->port);
       sp2 = sp;
     }
     addr = (struct sockaddr *)&wild4;
@@ -488,8 +486,8 @@ grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
     addr_len = sizeof(addr4_copy);
   }
   sp = add_socket_to_server(s, fd, addr, addr_len);
-  sp->sibling = sp2;
-  if (sp2) sp2->is_sibling = 1;
+  if (sp != NULL) sp->sibling = sp2;
+  if (sp2 != NULL) sp2->is_sibling = 1;
 
 done:
   gpr_free(allocated_addr);
@@ -534,8 +532,12 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
 }
 
 int grpc_tcp_listener_get_port(grpc_tcp_listener *listener) {
-  grpc_tcp_listener *sp = listener;
-  return sp->port;
+  if (listener != NULL) {
+    grpc_tcp_listener *sp = listener;
+    return sp->port;
+  } else {
+    return 0;
+  }
 }
 
 void grpc_tcp_listener_ref(grpc_tcp_listener *listener) {

+ 6 - 2
src/core/iomgr/tcp_server_windows.c

@@ -486,8 +486,12 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
 }
 
 int grpc_tcp_listener_get_port(grpc_tcp_listener *listener) {
-  grpc_tcp_listener *sp = listener;
-  return sp->port;
+  if (listener != NULL) {
+    grpc_tcp_listener *sp = listener;
+    return sp->port;
+  } else {
+    return 0;
+  }
 }
 
 void grpc_tcp_listener_ref(grpc_tcp_listener *listener) {

+ 9 - 5
src/core/iomgr/tcp_windows.c

@@ -197,7 +197,8 @@ static void win_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
 
   tcp->read_slice = gpr_slice_malloc(8192);
 
-  buffer.len = GPR_SLICE_LENGTH(tcp->read_slice);
+  buffer.len = (ULONG)GPR_SLICE_LENGTH(
+      tcp->read_slice);  // we know slice size fits in 32bit.
   buffer.buf = (char *)GPR_SLICE_START_PTR(tcp->read_slice);
 
   TCP_REF(tcp, "read");
@@ -273,6 +274,7 @@ static void win_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
   WSABUF local_buffers[16];
   WSABUF *allocated = NULL;
   WSABUF *buffers = local_buffers;
+  size_t len;
 
   if (tcp->shutting_down) {
     grpc_exec_ctx_enqueue(exec_ctx, cb, 0);
@@ -281,19 +283,21 @@ static void win_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
 
   tcp->write_cb = cb;
   tcp->write_slices = slices;
-
+  GPR_ASSERT(tcp->write_slices->count <= UINT_MAX);
   if (tcp->write_slices->count > GPR_ARRAY_SIZE(local_buffers)) {
     buffers = (WSABUF *)gpr_malloc(sizeof(WSABUF) * tcp->write_slices->count);
     allocated = buffers;
   }
 
   for (i = 0; i < tcp->write_slices->count; i++) {
-    buffers[i].len = GPR_SLICE_LENGTH(tcp->write_slices->slices[i]);
+    len = GPR_SLICE_LENGTH(tcp->write_slices->slices[i]);
+    GPR_ASSERT(len <= ULONG_MAX);
+    buffers[i].len = (ULONG)len;
     buffers[i].buf = (char *)GPR_SLICE_START_PTR(tcp->write_slices->slices[i]);
   }
 
   /* First, let's try a synchronous, non-blocking write. */
-  status = WSASend(socket->socket, buffers, tcp->write_slices->count,
+  status = WSASend(socket->socket, buffers, (DWORD)tcp->write_slices->count,
                    &bytes_sent, 0, NULL, NULL);
   info->wsa_error = status == 0 ? 0 : WSAGetLastError();
 
@@ -322,7 +326,7 @@ static void win_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
   /* If we got a WSAEWOULDBLOCK earlier, then we need to re-do the same
      operation, this time asynchronously. */
   memset(&socket->write_info.overlapped, 0, sizeof(OVERLAPPED));
-  status = WSASend(socket->socket, buffers, tcp->write_slices->count,
+  status = WSASend(socket->socket, buffers, (DWORD)tcp->write_slices->count,
                    &bytes_sent, 0, &socket->write_info.overlapped, NULL);
   if (allocated) gpr_free(allocated);
 

+ 2 - 10
src/core/iomgr/timer.c

@@ -126,8 +126,8 @@ static double ts_to_dbl(gpr_timespec ts) {
 
 static gpr_timespec dbl_to_ts(double d) {
   gpr_timespec ts;
-  ts.tv_sec = (time_t)d;
-  ts.tv_nsec = (int)(1e9 * (d - (double)ts.tv_sec));
+  ts.tv_sec = (gpr_int64)d;
+  ts.tv_nsec = (gpr_int32)(1e9 * (d - (double)ts.tv_sec));
   ts.clock_type = GPR_TIMESPAN;
   return ts;
 }
@@ -343,11 +343,3 @@ int grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now,
       exec_ctx, now, next,
       gpr_time_cmp(now, gpr_inf_future(now.clock_type)) != 0);
 }
-
-gpr_timespec grpc_timer_list_next_timeout(void) {
-  gpr_timespec out;
-  gpr_mu_lock(&g_mu);
-  out = g_shard_queue[0]->min_deadline;
-  gpr_mu_unlock(&g_mu);
-  return out;
-}

+ 0 - 2
src/core/iomgr/timer_internal.h

@@ -54,8 +54,6 @@ int grpc_timer_check(grpc_exec_ctx* exec_ctx, gpr_timespec now,
 void grpc_timer_list_init(gpr_timespec now);
 void grpc_timer_list_shutdown(grpc_exec_ctx* exec_ctx);
 
-gpr_timespec grpc_timer_list_next_timeout(void);
-
 /* the following must be implemented by each iomgr implementation */
 
 void grpc_kick_poller(void);

+ 3 - 1
src/core/iomgr/udp_server.c

@@ -38,6 +38,7 @@
 
 #include <grpc/support/port_platform.h>
 
+#ifdef GRPC_NEED_UDP
 #ifdef GPR_POSIX_SOCKET
 
 #include "src/core/iomgr/udp_server.h"
@@ -179,7 +180,7 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
       }
       sp->destroyed_closure.cb = destroyed_port;
       sp->destroyed_closure.cb_arg = s;
-      grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure,
+      grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
                      "udp_listener_shutdown");
     }
     gpr_mu_unlock(&s->mu);
@@ -435,3 +436,4 @@ void grpc_udp_server_write(server_port *sp, const char *buffer, size_t buf_len,
 }
 
 #endif
+#endif

+ 3 - 5
src/core/iomgr/wakeup_fd_posix.c

@@ -40,19 +40,17 @@
 #include <stddef.h>
 
 static const grpc_wakeup_fd_vtable *wakeup_fd_vtable = NULL;
+int grpc_allow_specialized_wakeup_fd = 1;
 
 void grpc_wakeup_fd_global_init(void) {
-  if (grpc_specialized_wakeup_fd_vtable.check_availability()) {
+  if (grpc_allow_specialized_wakeup_fd &&
+      grpc_specialized_wakeup_fd_vtable.check_availability()) {
     wakeup_fd_vtable = &grpc_specialized_wakeup_fd_vtable;
   } else {
     wakeup_fd_vtable = &grpc_pipe_wakeup_fd_vtable;
   }
 }
 
-void grpc_wakeup_fd_global_init_force_fallback(void) {
-  wakeup_fd_vtable = &grpc_pipe_wakeup_fd_vtable;
-}
-
 void grpc_wakeup_fd_global_destroy(void) { wakeup_fd_vtable = NULL; }
 
 void grpc_wakeup_fd_init(grpc_wakeup_fd *fd_info) {

+ 2 - 0
src/core/iomgr/wakeup_fd_posix.h

@@ -85,6 +85,8 @@ struct grpc_wakeup_fd {
   int write_fd;
 };
 
+extern int grpc_allow_specialized_wakeup_fd;
+
 #define GRPC_WAKEUP_FD_GET_READ_FD(fd_info) ((fd_info)->read_fd)
 
 void grpc_wakeup_fd_init(grpc_wakeup_fd* fd_info);

+ 4 - 1
src/core/iomgr/workqueue_posix.c

@@ -103,6 +103,9 @@ void grpc_workqueue_add_to_pollset(grpc_exec_ctx *exec_ctx,
 
 void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {
   gpr_mu_lock(&workqueue->mu);
+  if (grpc_closure_list_empty(workqueue->closure_list)) {
+    grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd);
+  }
   grpc_closure_list_move(&exec_ctx->closure_list, &workqueue->closure_list);
   gpr_mu_unlock(&workqueue->mu);
 }
@@ -115,7 +118,7 @@ static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, int success) {
     /* HACK: let wakeup_fd code know that we stole the fd */
     workqueue->wakeup_fd.read_fd = 0;
     grpc_wakeup_fd_destroy(&workqueue->wakeup_fd);
-    grpc_fd_orphan(exec_ctx, workqueue->wakeup_read_fd, NULL, "destroy");
+    grpc_fd_orphan(exec_ctx, workqueue->wakeup_read_fd, NULL, NULL, "destroy");
     gpr_free(workqueue);
   } else {
     gpr_mu_lock(&workqueue->mu);

+ 8 - 7
src/core/json/json_reader.c

@@ -35,6 +35,8 @@
 
 #include <grpc/support/port_platform.h>
 
+#include <grpc/support/log.h>
+
 #include "src/core/json/json_reader.h"
 
 static void json_reader_string_clear(grpc_json_reader *reader) {
@@ -224,13 +226,13 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
                   reader->in_array = 1;
                   break;
                 case GRPC_JSON_TOP_LEVEL:
-                  if (reader->depth != 0) return GRPC_JSON_INTERNAL_ERROR;
+                  GPR_ASSERT(reader->depth == 0);
                   reader->in_object = 0;
                   reader->in_array = 0;
                   reader->state = GRPC_JSON_STATE_END;
                   break;
                 default:
-                  return GRPC_JSON_INTERNAL_ERROR;
+                  GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
               }
             }
             break;
@@ -279,8 +281,7 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
             break;
 
           case GRPC_JSON_STATE_OBJECT_KEY_STRING:
-            if (reader->unicode_high_surrogate != 0)
-              return GRPC_JSON_PARSE_ERROR;
+            GPR_ASSERT(reader->unicode_high_surrogate == 0);
             if (c == '"') {
               reader->state = GRPC_JSON_STATE_OBJECT_KEY_END;
               json_reader_set_key(reader);
@@ -461,7 +462,7 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
                 }
                 break;
               default:
-                return GRPC_JSON_INTERNAL_ERROR;
+                GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
             }
             break;
 
@@ -641,7 +642,7 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
               case ',':
               case '}':
               case ']':
-                return GRPC_JSON_INTERNAL_ERROR;
+                GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
                 break;
 
               default:
@@ -655,5 +656,5 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
     }
   }
 
-  return GRPC_JSON_INTERNAL_ERROR;
+  GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
 }

+ 1 - 1
src/core/json/json_string.c

@@ -353,7 +353,7 @@ static void json_dump_recursive(grpc_json_writer *writer, grpc_json *json,
         grpc_json_writer_value_raw_with_len(writer, "null", 4);
         break;
       default:
-        abort();
+        GPR_UNREACHABLE_CODE(abort());
     }
     json = json->next;
   }

+ 4 - 3
src/core/profiling/basic_timers.c

@@ -141,10 +141,11 @@ static void write_log(gpr_timer_log *log) {
       entry->tm = gpr_time_0(entry->tm.clock_type);
     }
     fprintf(output_file,
-            "{\"t\": %ld.%09d, \"thd\": \"%d\", \"type\": \"%c\", \"tag\": "
+            "{\"t\": %lld.%09d, \"thd\": \"%d\", \"type\": \"%c\", \"tag\": "
             "\"%s\", \"file\": \"%s\", \"line\": %d, \"imp\": %d}\n",
-            entry->tm.tv_sec, entry->tm.tv_nsec, entry->thd, entry->type,
-            entry->tagstr, entry->file, entry->line, entry->important);
+            (long long)entry->tm.tv_sec, (int)entry->tm.tv_nsec, entry->thd,
+            entry->type, entry->tagstr, entry->file, entry->line,
+            entry->important);
   }
 }
 

+ 36 - 18
src/core/security/client_auth_filter.c

@@ -39,11 +39,11 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
-#include "src/core/support/string.h"
 #include "src/core/channel/channel_stack.h"
-#include "src/core/security/security_context.h"
-#include "src/core/security/security_connector.h"
 #include "src/core/security/credentials.h"
+#include "src/core/security/security_connector.h"
+#include "src/core/security/security_context.h"
+#include "src/core/support/string.h"
 #include "src/core/surface/call.h"
 #include "src/core/transport/static_metadata.h"
 
@@ -62,7 +62,7 @@ typedef struct {
   grpc_transport_stream_op op;
   gpr_uint8 security_context_set;
   grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT];
-  char *service_url;
+  grpc_auth_metadata_context auth_md_context;
 } call_data;
 
 /* We can have a per-channel credentials. */
@@ -70,11 +70,20 @@ typedef struct {
   grpc_channel_security_connector *security_connector;
 } channel_data;
 
-static void reset_service_url(call_data *calld) {
-  if (calld->service_url != NULL) {
-    gpr_free(calld->service_url);
-    calld->service_url = NULL;
+static void reset_auth_metadata_context(
+    grpc_auth_metadata_context *auth_md_context) {
+  if (auth_md_context->service_url != NULL) {
+    gpr_free((char *)auth_md_context->service_url);
+    auth_md_context->service_url = NULL;
+  }
+  if (auth_md_context->method_name != NULL) {
+    gpr_free((char *)auth_md_context->method_name);
+    auth_md_context->method_name = NULL;
   }
+  GRPC_AUTH_CONTEXT_UNREF(
+      (grpc_auth_context *)auth_md_context->channel_auth_context,
+      "grpc_auth_metadata_context");
+  auth_md_context->channel_auth_context = NULL;
 }
 
 static void bubble_up_error(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
@@ -94,7 +103,7 @@ static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
   grpc_transport_stream_op *op = &calld->op;
   grpc_metadata_batch *mdb;
   size_t i;
-  reset_service_url(calld);
+  reset_auth_metadata_context(&calld->auth_md_context);
   if (status != GRPC_CREDENTIALS_OK) {
     bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED,
                     "Credentials failed to get metadata.");
@@ -112,9 +121,13 @@ static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data,
   grpc_call_next_op(exec_ctx, elem, op);
 }
 
-void build_service_url(const char *url_scheme, call_data *calld) {
+void build_auth_metadata_context(grpc_security_connector *sc,
+                                 call_data *calld) {
   char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method));
   char *last_slash = strrchr(service, '/');
+  char *method_name = NULL;
+  char *service_url = NULL;
+  reset_auth_metadata_context(&calld->auth_md_context);
   if (last_slash == NULL) {
     gpr_log(GPR_ERROR, "No '/' found in fully qualified method name");
     service[0] = '\0';
@@ -123,11 +136,16 @@ void build_service_url(const char *url_scheme, call_data *calld) {
     service[1] = '\0';
   } else {
     *last_slash = '\0';
+    method_name = gpr_strdup(last_slash + 1);
   }
-  if (url_scheme == NULL) url_scheme = "";
-  reset_service_url(calld);
-  gpr_asprintf(&calld->service_url, "%s://%s%s", url_scheme,
+  if (method_name == NULL) method_name = gpr_strdup("");
+  gpr_asprintf(&service_url, "%s://%s%s",
+               sc->url_scheme == NULL ? "" : sc->url_scheme,
                grpc_mdstr_as_c_string(calld->host), service);
+  calld->auth_md_context.service_url = service_url;
+  calld->auth_md_context.method_name = method_name;
+  calld->auth_md_context.channel_auth_context =
+      GRPC_AUTH_CONTEXT_REF(sc->auth_context, "grpc_auth_metadata_context");
   gpr_free(service);
 }
 
@@ -161,12 +179,12 @@ static void send_security_metadata(grpc_exec_ctx *exec_ctx,
         call_creds_has_md ? ctx->creds : channel_call_creds);
   }
 
-  build_service_url(chand->security_connector->base.url_scheme, calld);
+  build_auth_metadata_context(&chand->security_connector->base, calld);
   calld->op = *op; /* Copy op (originates from the caller's stack). */
   GPR_ASSERT(calld->pollset);
-  grpc_call_credentials_get_request_metadata(exec_ctx, calld->creds,
-                                             calld->pollset, calld->service_url,
-                                             on_credentials_metadata, elem);
+  grpc_call_credentials_get_request_metadata(
+      exec_ctx, calld->creds, calld->pollset, calld->auth_md_context,
+      on_credentials_metadata, elem);
 }
 
 static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data,
@@ -280,7 +298,7 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
   if (calld->method != NULL) {
     GRPC_MDSTR_UNREF(calld->method);
   }
-  reset_service_url(calld);
+  reset_auth_metadata_context(&calld->auth_md_context);
 }
 
 /* Constructor for channel_data */

+ 47 - 56
src/core/security/credentials.c

@@ -33,22 +33,21 @@
 
 #include "src/core/security/credentials.h"
 
-#include <string.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "src/core/channel/channel_args.h"
 #include "src/core/channel/http_client_filter.h"
-#include "src/core/json/json.h"
 #include "src/core/httpcli/httpcli.h"
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/surface/api_trace.h"
+#include "src/core/iomgr/executor.h"
+#include "src/core/json/json.h"
 #include "src/core/support/string.h"
+#include "src/core/surface/api_trace.h"
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/sync.h>
-#include <grpc/support/thd.h>
 #include <grpc/support/time.h>
 
 /* -- Common. -- */
@@ -116,19 +115,17 @@ void grpc_call_credentials_release(grpc_call_credentials *creds) {
   grpc_call_credentials_unref(creds);
 }
 
-void grpc_call_credentials_get_request_metadata(grpc_exec_ctx *exec_ctx,
-                                                grpc_call_credentials *creds,
-                                                grpc_pollset *pollset,
-                                                const char *service_url,
-                                                grpc_credentials_metadata_cb cb,
-                                                void *user_data) {
+void grpc_call_credentials_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_pollset *pollset, grpc_auth_metadata_context context,
+    grpc_credentials_metadata_cb cb, void *user_data) {
   if (creds == NULL || creds->vtable->get_request_metadata == NULL) {
     if (cb != NULL) {
       cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
     }
     return;
   }
-  creds->vtable->get_request_metadata(exec_ctx, creds, pollset, service_url, cb,
+  creds->vtable->get_request_metadata(exec_ctx, creds, pollset, context, cb,
                                       user_data);
 }
 
@@ -429,7 +426,7 @@ static void jwt_destruct(grpc_call_credentials *creds) {
 static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
                                      grpc_call_credentials *creds,
                                      grpc_pollset *pollset,
-                                     const char *service_url,
+                                     grpc_auth_metadata_context context,
                                      grpc_credentials_metadata_cb cb,
                                      void *user_data) {
   grpc_service_account_jwt_access_credentials *c =
@@ -442,7 +439,7 @@ static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
   {
     gpr_mu_lock(&c->cache_mu);
     if (c->cached.service_url != NULL &&
-        strcmp(c->cached.service_url, service_url) == 0 &&
+        strcmp(c->cached.service_url, context.service_url) == 0 &&
         c->cached.jwt_md != NULL &&
         (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration,
                                    gpr_now(GPR_CLOCK_REALTIME)),
@@ -457,14 +454,15 @@ static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
     /* Generate a new jwt. */
     gpr_mu_lock(&c->cache_mu);
     jwt_reset_cache(c);
-    jwt = grpc_jwt_encode_and_sign(&c->key, service_url, c->jwt_lifetime, NULL);
+    jwt = grpc_jwt_encode_and_sign(&c->key, context.service_url,
+                                   c->jwt_lifetime, NULL);
     if (jwt != NULL) {
       char *md_value;
       gpr_asprintf(&md_value, "Bearer %s", jwt);
       gpr_free(jwt);
       c->cached.jwt_expiration =
           gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime);
-      c->cached.service_url = gpr_strdup(service_url);
+      c->cached.service_url = gpr_strdup(context.service_url);
       c->cached.jwt_md = grpc_credentials_md_store_create(1);
       grpc_credentials_md_store_add_cstrings(
           c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value);
@@ -512,10 +510,11 @@ grpc_call_credentials *grpc_service_account_jwt_access_credentials_create(
       "grpc_service_account_jwt_access_credentials_create("
       "json_key=%s, "
       "token_lifetime="
-      "gpr_timespec { tv_sec: %ld, tv_nsec: %d, clock_type: %d }, "
+      "gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, "
       "reserved=%p)",
-      5, (json_key, (long)token_lifetime.tv_sec, token_lifetime.tv_nsec,
-          (int)token_lifetime.clock_type, reserved));
+      5,
+      (json_key, (long long)token_lifetime.tv_sec, (int)token_lifetime.tv_nsec,
+       (int)token_lifetime.clock_type, reserved));
   GPR_ASSERT(reserved == NULL);
   return grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
       grpc_auth_json_key_create_from_string(json_key), token_lifetime);
@@ -649,7 +648,7 @@ static void on_oauth2_token_fetcher_http_response(
 
 static void oauth2_token_fetcher_get_request_metadata(
     grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
-    grpc_pollset *pollset, const char *service_url,
+    grpc_pollset *pollset, grpc_auth_metadata_context context,
     grpc_credentials_metadata_cb cb, void *user_data) {
   grpc_oauth2_token_fetcher_credentials *c =
       (grpc_oauth2_token_fetcher_credentials *)creds;
@@ -793,30 +792,27 @@ static void md_only_test_destruct(grpc_call_credentials *creds) {
   grpc_credentials_md_store_unref(c->md_store);
 }
 
-static void on_simulated_token_fetch_done(void *user_data) {
+static void on_simulated_token_fetch_done(grpc_exec_ctx *exec_ctx,
+                                          void *user_data, int success) {
   grpc_credentials_metadata_request *r =
       (grpc_credentials_metadata_request *)user_data;
   grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  r->cb(&exec_ctx, r->user_data, c->md_store->entries, c->md_store->num_entries,
+  r->cb(exec_ctx, r->user_data, c->md_store->entries, c->md_store->num_entries,
         GRPC_CREDENTIALS_OK);
   grpc_credentials_metadata_request_destroy(r);
-  grpc_exec_ctx_finish(&exec_ctx);
 }
 
-static void md_only_test_get_request_metadata(grpc_exec_ctx *exec_ctx,
-                                              grpc_call_credentials *creds,
-                                              grpc_pollset *pollset,
-                                              const char *service_url,
-                                              grpc_credentials_metadata_cb cb,
-                                              void *user_data) {
+static void md_only_test_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_pollset *pollset, grpc_auth_metadata_context context,
+    grpc_credentials_metadata_cb cb, void *user_data) {
   grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
 
   if (c->is_async) {
-    gpr_thd_id thd_id;
     grpc_credentials_metadata_request *cb_arg =
         grpc_credentials_metadata_request_create(creds, cb, user_data);
-    gpr_thd_new(&thd_id, on_simulated_token_fetch_done, cb_arg, NULL);
+    grpc_executor_enqueue(
+        grpc_closure_create(on_simulated_token_fetch_done, cb_arg), 1);
   } else {
     cb(exec_ctx, user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK);
   }
@@ -846,12 +842,10 @@ static void access_token_destruct(grpc_call_credentials *creds) {
   grpc_credentials_md_store_unref(c->access_token_md);
 }
 
-static void access_token_get_request_metadata(grpc_exec_ctx *exec_ctx,
-                                              grpc_call_credentials *creds,
-                                              grpc_pollset *pollset,
-                                              const char *service_url,
-                                              grpc_credentials_metadata_cb cb,
-                                              void *user_data) {
+static void access_token_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_pollset *pollset, grpc_auth_metadata_context context,
+    grpc_credentials_metadata_cb cb, void *user_data) {
   grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
   cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
 }
@@ -932,7 +926,7 @@ typedef struct {
   grpc_composite_call_credentials *composite_creds;
   size_t creds_index;
   grpc_credentials_md_store *md_elems;
-  char *service_url;
+  grpc_auth_metadata_context auth_md_context;
   void *user_data;
   grpc_pollset *pollset;
   grpc_credentials_metadata_cb cb;
@@ -950,7 +944,6 @@ static void composite_call_destruct(grpc_call_credentials *creds) {
 static void composite_call_md_context_destroy(
     grpc_composite_call_credentials_metadata_context *ctx) {
   grpc_credentials_md_store_unref(ctx->md_elems);
-  if (ctx->service_url != NULL) gpr_free(ctx->service_url);
   gpr_free(ctx);
 }
 
@@ -978,9 +971,9 @@ static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
   if (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
     grpc_call_credentials *inner_creds =
         ctx->composite_creds->inner.creds_array[ctx->creds_index++];
-    grpc_call_credentials_get_request_metadata(exec_ctx, inner_creds,
-                                               ctx->pollset, ctx->service_url,
-                                               composite_call_metadata_cb, ctx);
+    grpc_call_credentials_get_request_metadata(
+        exec_ctx, inner_creds, ctx->pollset, ctx->auth_md_context,
+        composite_call_metadata_cb, ctx);
     return;
   }
 
@@ -990,26 +983,24 @@ static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
   composite_call_md_context_destroy(ctx);
 }
 
-static void composite_call_get_request_metadata(grpc_exec_ctx *exec_ctx,
-                                                grpc_call_credentials *creds,
-                                                grpc_pollset *pollset,
-                                                const char *service_url,
-                                                grpc_credentials_metadata_cb cb,
-                                                void *user_data) {
+static void composite_call_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_pollset *pollset, grpc_auth_metadata_context auth_md_context,
+    grpc_credentials_metadata_cb cb, void *user_data) {
   grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
   grpc_composite_call_credentials_metadata_context *ctx;
 
   ctx = gpr_malloc(sizeof(grpc_composite_call_credentials_metadata_context));
   memset(ctx, 0, sizeof(grpc_composite_call_credentials_metadata_context));
-  ctx->service_url = gpr_strdup(service_url);
+  ctx->auth_md_context = auth_md_context;
   ctx->user_data = user_data;
   ctx->cb = cb;
   ctx->composite_creds = c;
   ctx->pollset = pollset;
   ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds);
   grpc_call_credentials_get_request_metadata(
-      exec_ctx, c->inner.creds_array[ctx->creds_index++], pollset, service_url,
-      composite_call_metadata_cb, ctx);
+      exec_ctx, c->inner.creds_array[ctx->creds_index++], pollset,
+      auth_md_context, composite_call_metadata_cb, ctx);
 }
 
 static grpc_call_credentials_vtable composite_call_credentials_vtable = {
@@ -1103,7 +1094,7 @@ static void iam_destruct(grpc_call_credentials *creds) {
 static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
                                      grpc_call_credentials *creds,
                                      grpc_pollset *pollset,
-                                     const char *service_url,
+                                     grpc_auth_metadata_context context,
                                      grpc_credentials_metadata_cb cb,
                                      void *user_data) {
   grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
@@ -1192,7 +1183,7 @@ static void plugin_md_request_metadata_ready(void *request,
 static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
                                         grpc_call_credentials *creds,
                                         grpc_pollset *pollset,
-                                        const char *service_url,
+                                        grpc_auth_metadata_context context,
                                         grpc_credentials_metadata_cb cb,
                                         void *user_data) {
   grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
@@ -1201,7 +1192,7 @@ static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
     memset(request, 0, sizeof(*request));
     request->user_data = user_data;
     request->cb = cb;
-    c->plugin.get_metadata(c->plugin.state, service_url,
+    c->plugin.get_metadata(c->plugin.state, context,
                            plugin_md_request_metadata_ready, request);
   } else {
     cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
@@ -1218,7 +1209,7 @@ grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
                  (reserved));
   GPR_ASSERT(reserved == NULL);
   memset(c, 0, sizeof(*c));
-  c->base.type = GRPC_CALL_CREDENTIALS_TYPE_METADATA_PLUGIN;
+  c->base.type = plugin.type;
   c->base.vtable = &plugin_vtable;
   gpr_ref_init(&c->base.refcount, 1);
   c->plugin = plugin;

+ 14 - 8
src/core/security/credentials.h

@@ -59,7 +59,6 @@ typedef enum {
   "FakeTransportSecurity"
 
 #define GRPC_CALL_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
-#define GRPC_CALL_CREDENTIALS_TYPE_METADATA_PLUGIN "Plugin"
 #define GRPC_CALL_CREDENTIALS_TYPE_JWT "Jwt"
 #define GRPC_CALL_CREDENTIALS_TYPE_IAM "Iam"
 #define GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE "Composite"
@@ -94,6 +93,14 @@ typedef enum {
 /* It is the caller's responsibility to gpr_free the result if not NULL. */
 char *grpc_get_well_known_google_credentials_file_path(void);
 
+/* Implementation function for the different platforms. */
+char *grpc_get_well_known_google_credentials_file_path_impl(void);
+
+/* Override for testing only. Not thread-safe */
+typedef char *(*grpc_well_known_credentials_path_getter)(void);
+void grpc_override_well_known_credentials_path_getter(
+    grpc_well_known_credentials_path_getter getter);
+
 /* --- grpc_channel_credentials. --- */
 
 typedef struct {
@@ -162,7 +169,7 @@ typedef struct {
   void (*destruct)(grpc_call_credentials *c);
   void (*get_request_metadata)(grpc_exec_ctx *exec_ctx,
                                grpc_call_credentials *c, grpc_pollset *pollset,
-                               const char *service_url,
+                               grpc_auth_metadata_context context,
                                grpc_credentials_metadata_cb cb,
                                void *user_data);
 } grpc_call_credentials_vtable;
@@ -175,12 +182,10 @@ struct grpc_call_credentials {
 
 grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds);
 void grpc_call_credentials_unref(grpc_call_credentials *creds);
-void grpc_call_credentials_get_request_metadata(grpc_exec_ctx *exec_ctx,
-                                                grpc_call_credentials *creds,
-                                                grpc_pollset *pollset,
-                                                const char *service_url,
-                                                grpc_credentials_metadata_cb cb,
-                                                void *user_data);
+void grpc_call_credentials_get_request_metadata(
+    grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
+    grpc_pollset *pollset, grpc_auth_metadata_context context,
+    grpc_credentials_metadata_cb cb, void *user_data);
 
 typedef struct {
   grpc_call_credentials **creds_array;
@@ -204,6 +209,7 @@ grpc_credentials_status
 grpc_oauth2_token_fetcher_credentials_parse_server_response(
     const struct grpc_httpcli_response *response,
     grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime);
+
 void grpc_flush_cached_google_default_credentials(void);
 
 /* Metadata-only credentials with the specified key and value where

+ 1 - 1
src/core/security/credentials_posix.c

@@ -44,7 +44,7 @@
 #include "src/core/support/env.h"
 #include "src/core/support/string.h"
 
-char *grpc_get_well_known_google_credentials_file_path(void) {
+char *grpc_get_well_known_google_credentials_file_path_impl(void) {
   char *result = NULL;
   char *home = gpr_getenv("HOME");
   if (home == NULL) {

+ 1 - 1
src/core/security/credentials_win32.c

@@ -44,7 +44,7 @@
 #include "src/core/support/env.h"
 #include "src/core/support/string.h"
 
-char *grpc_get_well_known_google_credentials_file_path(void) {
+char *grpc_get_well_known_google_credentials_file_path_impl(void) {
   char *result = NULL;
   char *appdata_path = gpr_getenv("APPDATA");
   if (appdata_path == NULL) {

+ 15 - 0
src/core/security/google_default_credentials.c

@@ -241,5 +241,20 @@ void grpc_flush_cached_google_default_credentials(void) {
     grpc_channel_credentials_unref(default_credentials);
     default_credentials = NULL;
   }
+  compute_engine_detection_done = 0;
   gpr_mu_unlock(&g_mu);
 }
+
+/* -- Well known credentials path. -- */
+
+static grpc_well_known_credentials_path_getter creds_path_getter = NULL;
+
+char *grpc_get_well_known_google_credentials_file_path(void) {
+  if (creds_path_getter != NULL) return creds_path_getter();
+  return grpc_get_well_known_google_credentials_file_path_impl();
+}
+
+void grpc_override_well_known_credentials_path_getter(
+    grpc_well_known_credentials_path_getter getter) {
+  creds_path_getter = getter;
+}

+ 45 - 4
src/core/security/handshake.c

@@ -64,12 +64,39 @@ static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
 static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *setup,
                                            int success);
 
+static void security_connector_remove_handshake(grpc_security_handshake *h) {
+  grpc_security_connector_handshake_list *node;
+  grpc_security_connector_handshake_list *tmp;
+  grpc_security_connector *sc = h->connector;
+  gpr_mu_lock(&sc->mu);
+  node = sc->handshaking_handshakes;
+  if (node && node->handshake == h) {
+    sc->handshaking_handshakes = node->next;
+    gpr_free(node);
+    gpr_mu_unlock(&sc->mu);
+    return;
+  }
+  while (node) {
+    if (node->next->handshake == h) {
+      tmp = node->next;
+      node->next = node->next->next;
+      gpr_free(tmp);
+      gpr_mu_unlock(&sc->mu);
+      return;
+    }
+    node = node->next;
+  }
+  gpr_mu_unlock(&sc->mu);
+}
+
 static void security_handshake_done(grpc_exec_ctx *exec_ctx,
                                     grpc_security_handshake *h,
                                     int is_success) {
+  if (!h->connector->is_client_side) {
+    security_connector_remove_handshake(h);
+  }
   if (is_success) {
-    h->cb(exec_ctx, h->user_data, GRPC_SECURITY_OK, h->wrapped_endpoint,
-          h->secure_endpoint);
+    h->cb(exec_ctx, h->user_data, GRPC_SECURITY_OK, h->secure_endpoint);
   } else {
     if (h->secure_endpoint != NULL) {
       grpc_endpoint_shutdown(exec_ctx, h->secure_endpoint);
@@ -77,8 +104,7 @@ static void security_handshake_done(grpc_exec_ctx *exec_ctx,
     } else {
       grpc_endpoint_destroy(exec_ctx, h->wrapped_endpoint);
     }
-    h->cb(exec_ctx, h->user_data, GRPC_SECURITY_ERROR, h->wrapped_endpoint,
-          NULL);
+    h->cb(exec_ctx, h->user_data, GRPC_SECURITY_ERROR, NULL);
   }
   if (h->handshaker != NULL) tsi_handshaker_destroy(h->handshaker);
   if (h->handshake_buffer != NULL) gpr_free(h->handshake_buffer);
@@ -268,6 +294,7 @@ void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
                                 grpc_endpoint *nonsecure_endpoint,
                                 grpc_security_handshake_done_cb cb,
                                 void *user_data) {
+  grpc_security_connector_handshake_list *handshake_node;
   grpc_security_handshake *h = gpr_malloc(sizeof(grpc_security_handshake));
   memset(h, 0, sizeof(grpc_security_handshake));
   h->handshaker = handshaker;
@@ -284,5 +311,19 @@ void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
   gpr_slice_buffer_init(&h->left_overs);
   gpr_slice_buffer_init(&h->outgoing);
   gpr_slice_buffer_init(&h->incoming);
+  if (!connector->is_client_side) {
+    handshake_node = gpr_malloc(sizeof(grpc_security_connector_handshake_list));
+    handshake_node->handshake = h;
+    gpr_mu_lock(&connector->mu);
+    handshake_node->next = connector->handshaking_handshakes;
+    connector->handshaking_handshakes = handshake_node;
+    gpr_mu_unlock(&connector->mu);
+  }
   send_handshake_bytes_to_peer(exec_ctx, h);
 }
+
+void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx,
+                                      void *handshake) {
+  grpc_security_handshake *h = handshake;
+  grpc_endpoint_shutdown(exec_ctx, h->wrapped_endpoint);
+}

+ 2 - 0
src/core/security/handshake.h

@@ -45,4 +45,6 @@ void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
                                 grpc_security_handshake_done_cb cb,
                                 void *user_data);
 
+void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx, void *handshake);
+
 #endif /* GRPC_INTERNAL_CORE_SECURITY_HANDSHAKE_H */

+ 2 - 2
src/core/security/json_token.c

@@ -215,8 +215,8 @@ static char *encoded_jwt_claim(const grpc_auth_json_key *json_key,
     gpr_log(GPR_INFO, "Cropping token lifetime to maximum allowed value.");
     expiration = gpr_time_add(now, grpc_max_auth_token_lifetime);
   }
-  gpr_ltoa(now.tv_sec, now_str);
-  gpr_ltoa(expiration.tv_sec, expiration_str);
+  gpr_int64toa(now.tv_sec, now_str);
+  gpr_int64toa(expiration.tv_sec, expiration_str);
 
   child =
       create_child(NULL, json, "iss", json_key->client_email, GRPC_JSON_STRING);

+ 24 - 3
src/core/security/security_connector.c

@@ -102,13 +102,29 @@ const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer,
   return NULL;
 }
 
+void grpc_security_connector_shutdown(grpc_exec_ctx *exec_ctx,
+                                      grpc_security_connector *connector) {
+  grpc_security_connector_handshake_list *tmp;
+  if (!connector->is_client_side) {
+    gpr_mu_lock(&connector->mu);
+    while (connector->handshaking_handshakes) {
+      tmp = connector->handshaking_handshakes;
+      grpc_security_handshake_shutdown(
+          exec_ctx, connector->handshaking_handshakes->handshake);
+      connector->handshaking_handshakes = tmp->next;
+      gpr_free(tmp);
+    }
+    gpr_mu_unlock(&connector->mu);
+  }
+}
+
 void grpc_security_connector_do_handshake(grpc_exec_ctx *exec_ctx,
                                           grpc_security_connector *sc,
                                           grpc_endpoint *nonsecure_endpoint,
                                           grpc_security_handshake_done_cb cb,
                                           void *user_data) {
   if (sc == NULL || nonsecure_endpoint == NULL) {
-    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, nonsecure_endpoint, NULL);
+    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL);
   } else {
     sc->vtable->do_handshake(exec_ctx, sc, nonsecure_endpoint, cb, user_data);
   }
@@ -219,6 +235,7 @@ static void fake_channel_destroy(grpc_security_connector *sc) {
 
 static void fake_server_destroy(grpc_security_connector *sc) {
   GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector");
+  gpr_mu_destroy(&sc->mu);
   gpr_free(sc);
 }
 
@@ -319,6 +336,7 @@ grpc_security_connector *grpc_fake_server_security_connector_create(void) {
   c->is_client_side = 0;
   c->vtable = &fake_server_vtable;
   c->url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
+  gpr_mu_init(&c->mu);
   return c;
 }
 
@@ -354,10 +372,12 @@ static void ssl_channel_destroy(grpc_security_connector *sc) {
 static void ssl_server_destroy(grpc_security_connector *sc) {
   grpc_ssl_server_security_connector *c =
       (grpc_ssl_server_security_connector *)sc;
+
   if (c->handshaker_factory != NULL) {
     tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
   }
   GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector");
+  gpr_mu_destroy(&sc->mu);
   gpr_free(sc);
 }
 
@@ -390,7 +410,7 @@ static void ssl_channel_do_handshake(grpc_exec_ctx *exec_ctx,
                                         : c->target_name,
       &handshaker);
   if (status != GRPC_SECURITY_OK) {
-    cb(exec_ctx, user_data, status, nonsecure_endpoint, NULL);
+    cb(exec_ctx, user_data, status, NULL);
   } else {
     grpc_do_security_handshake(exec_ctx, handshaker, sc, nonsecure_endpoint, cb,
                                user_data);
@@ -408,7 +428,7 @@ static void ssl_server_do_handshake(grpc_exec_ctx *exec_ctx,
   grpc_security_status status =
       ssl_create_handshaker(c->handshaker_factory, 0, NULL, &handshaker);
   if (status != GRPC_SECURITY_OK) {
-    cb(exec_ctx, user_data, status, nonsecure_endpoint, NULL);
+    cb(exec_ctx, user_data, status, NULL);
   } else {
     grpc_do_security_handshake(exec_ctx, handshaker, sc, nonsecure_endpoint, cb,
                                user_data);
@@ -691,6 +711,7 @@ grpc_security_status grpc_ssl_server_security_connector_create(
     *sc = NULL;
     goto error;
   }
+  gpr_mu_init(&c->base.mu);
   *sc = &c->base;
   gpr_free((void *)alpn_protocol_strings);
   gpr_free(alpn_protocol_string_lengths);

+ 13 - 1
src/core/security/security_connector.h

@@ -67,7 +67,6 @@ typedef void (*grpc_security_check_cb)(grpc_exec_ctx *exec_ctx, void *user_data,
 typedef void (*grpc_security_handshake_done_cb)(grpc_exec_ctx *exec_ctx,
                                                 void *user_data,
                                                 grpc_security_status status,
-                                                grpc_endpoint *wrapped_endpoint,
                                                 grpc_endpoint *secure_endpoint);
 
 typedef struct {
@@ -80,12 +79,22 @@ typedef struct {
                                      void *user_data);
 } grpc_security_connector_vtable;
 
+typedef struct grpc_security_connector_handshake_list {
+  void *handshake;
+  struct grpc_security_connector_handshake_list *next;
+} grpc_security_connector_handshake_list;
+
 struct grpc_security_connector {
   const grpc_security_connector_vtable *vtable;
   gpr_refcount refcount;
   int is_client_side;
   const char *url_scheme;
   grpc_auth_context *auth_context; /* Populated after the peer is checked. */
+  /* Used on server side only. */
+  /* TODO(yangg) maybe create a grpc_server_security_connector with these */
+  gpr_mu mu;
+  grpc_security_connector_handshake_list *handshaking_handshakes;
+  const grpc_channel_args *channel_args;
 };
 
 /* Refcounting. */
@@ -126,6 +135,9 @@ grpc_security_status grpc_security_connector_check_peer(
     grpc_security_connector *sc, tsi_peer peer, grpc_security_check_cb cb,
     void *user_data);
 
+void grpc_security_connector_shutdown(grpc_exec_ctx *exec_ctx,
+                                      grpc_security_connector *connector);
+
 /* Util to encapsulate the connector in a channel arg. */
 grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc);
 

+ 17 - 61
src/core/security/server_secure_chttp2.c

@@ -52,17 +52,11 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/useful.h>
 
-typedef struct tcp_endpoint_list {
-  grpc_endpoint *tcp_endpoint;
-  struct tcp_endpoint_list *next;
-} tcp_endpoint_list;
-
 typedef struct grpc_server_secure_state {
   grpc_server *server;
   grpc_tcp_server *tcp;
   grpc_security_connector *sc;
   grpc_server_credentials *creds;
-  tcp_endpoint_list *handshaking_tcp_endpoints;
   int is_shutdown;
   gpr_mu mu;
   gpr_refcount refcount;
@@ -103,52 +97,28 @@ static void setup_transport(grpc_exec_ctx *exec_ctx, void *statep,
   grpc_channel_args_destroy(args_copy);
 }
 
-static int remove_tcp_from_list_locked(grpc_server_secure_state *state,
-                                       grpc_endpoint *tcp) {
-  tcp_endpoint_list *node = state->handshaking_tcp_endpoints;
-  tcp_endpoint_list *tmp = NULL;
-  if (node && node->tcp_endpoint == tcp) {
-    state->handshaking_tcp_endpoints = state->handshaking_tcp_endpoints->next;
-    gpr_free(node);
-    return 0;
-  }
-  while (node) {
-    if (node->next->tcp_endpoint == tcp) {
-      tmp = node->next;
-      node->next = node->next->next;
-      gpr_free(tmp);
-      return 0;
-    }
-    node = node->next;
-  }
-  return -1;
-}
-
 static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep,
                                      grpc_security_status status,
-                                     grpc_endpoint *wrapped_endpoint,
                                      grpc_endpoint *secure_endpoint) {
   grpc_server_secure_state *state = statep;
   grpc_transport *transport;
   if (status == GRPC_SECURITY_OK) {
-    gpr_mu_lock(&state->mu);
-    remove_tcp_from_list_locked(state, wrapped_endpoint);
-    if (!state->is_shutdown) {
-      transport = grpc_create_chttp2_transport(
-          exec_ctx, grpc_server_get_channel_args(state->server),
-          secure_endpoint, 0);
-      setup_transport(exec_ctx, state, transport);
-      grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0);
-    } else {
-      /* We need to consume this here, because the server may already have gone
-       * away. */
-      grpc_endpoint_destroy(exec_ctx, secure_endpoint);
+    if (secure_endpoint) {
+      gpr_mu_lock(&state->mu);
+      if (!state->is_shutdown) {
+        transport = grpc_create_chttp2_transport(
+            exec_ctx, grpc_server_get_channel_args(state->server),
+            secure_endpoint, 0);
+        setup_transport(exec_ctx, state, transport);
+        grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0);
+      } else {
+        /* We need to consume this here, because the server may already have
+         * gone away. */
+        grpc_endpoint_destroy(exec_ctx, secure_endpoint);
+      }
+      gpr_mu_unlock(&state->mu);
     }
-    gpr_mu_unlock(&state->mu);
   } else {
-    gpr_mu_lock(&state->mu);
-    remove_tcp_from_list_locked(state, wrapped_endpoint);
-    gpr_mu_unlock(&state->mu);
     gpr_log(GPR_ERROR, "Secure transport failed with error %d", status);
   }
   state_unref(state);
@@ -157,14 +127,7 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep,
 static void on_accept(grpc_exec_ctx *exec_ctx, void *statep,
                       grpc_endpoint *tcp) {
   grpc_server_secure_state *state = statep;
-  tcp_endpoint_list *node;
   state_ref(state);
-  node = gpr_malloc(sizeof(tcp_endpoint_list));
-  node->tcp_endpoint = tcp;
-  gpr_mu_lock(&state->mu);
-  node->next = state->handshaking_tcp_endpoints;
-  state->handshaking_tcp_endpoints = node;
-  gpr_mu_unlock(&state->mu);
   grpc_security_connector_do_handshake(exec_ctx, state->sc, tcp,
                                        on_secure_handshake_done, state);
 }
@@ -181,14 +144,7 @@ static void destroy_done(grpc_exec_ctx *exec_ctx, void *statep, int success) {
   grpc_server_secure_state *state = statep;
   state->destroy_callback->cb(exec_ctx, state->destroy_callback->cb_arg,
                               success);
-  gpr_mu_lock(&state->mu);
-  while (state->handshaking_tcp_endpoints != NULL) {
-    grpc_endpoint_shutdown(exec_ctx,
-                           state->handshaking_tcp_endpoints->tcp_endpoint);
-    remove_tcp_from_list_locked(state,
-                                state->handshaking_tcp_endpoints->tcp_endpoint);
-  }
-  gpr_mu_unlock(&state->mu);
+  grpc_security_connector_shutdown(exec_ctx, state->sc);
   state_unref(state);
 }
 
@@ -234,6 +190,7 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
             creds->type);
     goto error;
   }
+  sc->channel_args = grpc_server_get_channel_args(server);
 
   /* resolve address */
   resolved = grpc_blocking_resolve_address(addr, "https");
@@ -252,7 +209,7 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
         tcp, (struct sockaddr *)&resolved->addrs[i].addr,
         resolved->addrs[i].len);
     port_temp = grpc_tcp_listener_get_port(listener);
-    if (port_temp >= 0) {
+    if (port_temp > 0) {
       if (port_num == -1) {
         port_num = port_temp;
       } else {
@@ -280,7 +237,6 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
   state->sc = sc;
   state->creds = grpc_server_credentials_ref(creds);
 
-  state->handshaking_tcp_endpoints = NULL;
   state->is_shutdown = 0;
   gpr_mu_init(&state->mu);
   gpr_ref_init(&state->refcount, 1);

+ 1 - 1
src/core/statistics/window_stats.c

@@ -94,7 +94,7 @@ static gpr_int64 timespec_to_ns(const gpr_timespec ts) {
   if (ts.tv_sec > max_seconds) {
     return GPR_INT64_MAX - 1;
   }
-  return (gpr_int64)ts.tv_sec * GPR_NS_PER_SEC + ts.tv_nsec;
+  return ts.tv_sec * GPR_NS_PER_SEC + ts.tv_nsec;
 }
 
 static void cws_initialize_statistic(void *statistic,

+ 17 - 3
src/core/support/alloc.c

@@ -34,13 +34,27 @@
 #include <grpc/support/alloc.h>
 
 #include <stdlib.h>
+#include <grpc/support/log.h>
 #include <grpc/support/port_platform.h>
 #include "src/core/profiling/timers.h"
 
+static gpr_allocation_functions g_alloc_functions = {malloc, realloc, free};
+
+gpr_allocation_functions gpr_get_allocation_functions() {
+  return g_alloc_functions;
+}
+
+void gpr_set_allocation_functions(gpr_allocation_functions functions) {
+  GPR_ASSERT(functions.malloc_fn != NULL);
+  GPR_ASSERT(functions.realloc_fn != NULL);
+  GPR_ASSERT(functions.free_fn != NULL);
+  g_alloc_functions = functions;
+}
+
 void *gpr_malloc(size_t size) {
   void *p;
   GPR_TIMER_BEGIN("gpr_malloc", 0);
-  p = malloc(size);
+  p = g_alloc_functions.malloc_fn(size);
   if (!p) {
     abort();
   }
@@ -50,13 +64,13 @@ void *gpr_malloc(size_t size) {
 
 void gpr_free(void *p) {
   GPR_TIMER_BEGIN("gpr_free", 0);
-  free(p);
+  g_alloc_functions.free_fn(p);
   GPR_TIMER_END("gpr_free", 0);
 }
 
 void *gpr_realloc(void *p, size_t size) {
   GPR_TIMER_BEGIN("gpr_realloc", 0);
-  p = realloc(p, size);
+  p = g_alloc_functions.realloc_fn(p, size);
   if (!p) {
     abort();
   }

+ 43 - 19
src/core/support/cmdline.c

@@ -62,11 +62,13 @@ struct gpr_cmdline {
   void (*extra_arg)(void *user_data, const char *arg);
   void *extra_arg_user_data;
 
-  void (*state)(gpr_cmdline *cl, char *arg);
+  int (*state)(gpr_cmdline *cl, char *arg);
   arg *cur_arg;
+
+  int survive_failure;
 };
 
-static void normal_state(gpr_cmdline *cl, char *arg);
+static int normal_state(gpr_cmdline *cl, char *arg);
 
 gpr_cmdline *gpr_cmdline_create(const char *description) {
   gpr_cmdline *cl = gpr_malloc(sizeof(gpr_cmdline));
@@ -78,6 +80,10 @@ gpr_cmdline *gpr_cmdline_create(const char *description) {
   return cl;
 }
 
+void gpr_cmdline_set_survive_failure(gpr_cmdline *cl) {
+  cl->survive_failure = 1;
+}
+
 void gpr_cmdline_destroy(gpr_cmdline *cl) {
   while (cl->args) {
     arg *a = cl->args;
@@ -185,16 +191,22 @@ char *gpr_cmdline_usage_string(gpr_cmdline *cl, const char *argv0) {
   return tmp;
 }
 
-static void print_usage_and_die(gpr_cmdline *cl) {
+static int print_usage_and_die(gpr_cmdline *cl) {
   char *usage = gpr_cmdline_usage_string(cl, cl->argv0);
   fprintf(stderr, "%s", usage);
   gpr_free(usage);
-  exit(1);
+  if (!cl->survive_failure) {
+    exit(1);
+  }
+  return 0;
 }
 
-static void extra_state(gpr_cmdline *cl, char *str) {
-  if (!cl->extra_arg) print_usage_and_die(cl);
+static int extra_state(gpr_cmdline *cl, char *str) {
+  if (!cl->extra_arg) {
+    return print_usage_and_die(cl);
+  }
   cl->extra_arg(cl->extra_arg_user_data, str);
+  return 1;
 }
 
 static arg *find_arg(gpr_cmdline *cl, char *name) {
@@ -208,13 +220,13 @@ static arg *find_arg(gpr_cmdline *cl, char *name) {
 
   if (!a) {
     fprintf(stderr, "Unknown argument: %s\n", name);
-    print_usage_and_die(cl);
+    return NULL;
   }
 
   return a;
 }
 
-static void value_state(gpr_cmdline *cl, char *str) {
+static int value_state(gpr_cmdline *cl, char *str) {
   long intval;
   char *end;
 
@@ -226,7 +238,7 @@ static void value_state(gpr_cmdline *cl, char *str) {
       if (*end || intval < INT_MIN || intval > INT_MAX) {
         fprintf(stderr, "expected integer, got '%s' for %s\n", str,
                 cl->cur_arg->name);
-        print_usage_and_die(cl);
+        return print_usage_and_die(cl);
       }
       *(int *)cl->cur_arg->value = (int)intval;
       break;
@@ -238,7 +250,7 @@ static void value_state(gpr_cmdline *cl, char *str) {
       } else {
         fprintf(stderr, "expected boolean, got '%s' for %s\n", str,
                 cl->cur_arg->name);
-        print_usage_and_die(cl);
+        return print_usage_and_die(cl);
       }
       break;
     case ARGTYPE_STRING:
@@ -247,16 +259,18 @@ static void value_state(gpr_cmdline *cl, char *str) {
   }
 
   cl->state = normal_state;
+  return 1;
 }
 
-static void normal_state(gpr_cmdline *cl, char *str) {
+static int normal_state(gpr_cmdline *cl, char *str) {
   char *eq = NULL;
   char *tmp = NULL;
   char *arg_name = NULL;
+  int r = 1;
 
   if (0 == strcmp(str, "-help") || 0 == strcmp(str, "--help") ||
       0 == strcmp(str, "-h")) {
-    print_usage_and_die(cl);
+    return print_usage_and_die(cl);
   }
 
   cl->cur_arg = NULL;
@@ -266,7 +280,7 @@ static void normal_state(gpr_cmdline *cl, char *str) {
       if (str[2] == 0) {
         /* handle '--' to move to just extra args */
         cl->state = extra_state;
-        return;
+        return 1;
       }
       str += 2;
     } else {
@@ -277,12 +291,15 @@ static void normal_state(gpr_cmdline *cl, char *str) {
       /* str is of the form '--no-foo' - it's a flag disable */
       str += 3;
       cl->cur_arg = find_arg(cl, str);
+      if (cl->cur_arg == NULL) {
+        return print_usage_and_die(cl);
+      }
       if (cl->cur_arg->type != ARGTYPE_BOOL) {
         fprintf(stderr, "%s is not a flag argument\n", str);
-        print_usage_and_die(cl);
+        return print_usage_and_die(cl);
       }
       *(int *)cl->cur_arg->value = 0;
-      return; /* early out */
+      return 1; /* early out */
     }
     eq = strchr(str, '=');
     if (eq != NULL) {
@@ -294,9 +311,12 @@ static void normal_state(gpr_cmdline *cl, char *str) {
       arg_name = str;
     }
     cl->cur_arg = find_arg(cl, arg_name);
+    if (cl->cur_arg == NULL) {
+      return print_usage_and_die(cl);
+    }
     if (eq != NULL) {
       /* str was of the type --foo=value, parse the value */
-      value_state(cl, eq + 1);
+      r = value_state(cl, eq + 1);
     } else if (cl->cur_arg->type != ARGTYPE_BOOL) {
       /* flag types don't have a '--foo value' variant, other types do */
       cl->state = value_state;
@@ -305,19 +325,23 @@ static void normal_state(gpr_cmdline *cl, char *str) {
       *(int *)cl->cur_arg->value = 1;
     }
   } else {
-    extra_state(cl, str);
+    r = extra_state(cl, str);
   }
 
   gpr_free(tmp);
+  return r;
 }
 
-void gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv) {
+int gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv) {
   int i;
 
   GPR_ASSERT(argc >= 1);
   cl->argv0 = argv[0];
 
   for (i = 1; i < argc; i++) {
-    cl->state(cl, argv[i]);
+    if (!cl->state(cl, argv[i])) {
+      return 0;
+    }
   }
+  return 1;
 }

+ 2 - 1
src/core/support/log.c

@@ -32,6 +32,7 @@
  */
 
 #include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
 
 #include <stdio.h>
 #include <string.h>
@@ -48,7 +49,7 @@ const char *gpr_log_severity_string(gpr_log_severity severity) {
     case GPR_LOG_SEVERITY_ERROR:
       return "E";
   }
-  return "UNKNOWN";
+  GPR_UNREACHABLE_CODE(return "UNKNOWN");
 }
 
 void gpr_log_message(const char *file, int line, gpr_log_severity severity,

+ 3 - 1
src/core/support/log_linux.c

@@ -76,16 +76,18 @@ void gpr_default_log(gpr_log_func_args *args) {
   char *prefix;
   const char *display_file;
   char time_buffer[64];
+  time_t timer;
   gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
   struct tm tm;
 
+  timer = (time_t)now.tv_sec;
   final_slash = strrchr(args->file, '/');
   if (final_slash == NULL)
     display_file = args->file;
   else
     display_file = final_slash + 1;
 
-  if (!localtime_r(&now.tv_sec, &tm)) {
+  if (!localtime_r(&timer, &tm)) {
     strcpy(time_buffer, "error:localtime");
   } else if (0 ==
              strftime(time_buffer, sizeof(time_buffer), "%m%d %H:%M:%S", &tm)) {

+ 3 - 1
src/core/support/log_posix.c

@@ -75,16 +75,18 @@ void gpr_default_log(gpr_log_func_args *args) {
   char *final_slash;
   const char *display_file;
   char time_buffer[64];
+  time_t timer;
   gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
   struct tm tm;
 
+  timer = (time_t)now.tv_sec;
   final_slash = strrchr(args->file, '/');
   if (final_slash == NULL)
     display_file = args->file;
   else
     display_file = final_slash + 1;
 
-  if (!localtime_r(&now.tv_sec, &tm)) {
+  if (!localtime_r(&timer, &tm)) {
     strcpy(time_buffer, "error:localtime");
   } else if (0 ==
              strftime(time_buffer, sizeof(time_buffer), "%m%d %H:%M:%S", &tm)) {

+ 3 - 1
src/core/support/log_win32.c

@@ -84,16 +84,18 @@ void gpr_default_log(gpr_log_func_args *args) {
   char *final_slash;
   const char *display_file;
   char time_buffer[64];
+  time_t timer;
   gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
   struct tm tm;
 
+  timer = (time_t)now.tv_sec;
   final_slash = strrchr(args->file, '\\');
   if (final_slash == NULL)
     display_file = args->file;
   else
     display_file = final_slash + 1;
 
-  if (localtime_s(&tm, &now.tv_sec)) {
+  if (localtime_s(&tm, &timer)) {
     strcpy(time_buffer, "error:localtime");
   } else if (0 ==
              strftime(time_buffer, sizeof(time_buffer), "%m%d %H:%M:%S", &tm)) {

+ 0 - 7
src/core/support/slice.c

@@ -341,10 +341,3 @@ int gpr_slice_str_cmp(gpr_slice a, const char *b) {
   if (d != 0) return d;
   return memcmp(GPR_SLICE_START_PTR(a), b, b_length);
 }
-
-char *gpr_slice_to_cstring(gpr_slice slice) {
-  char *result = gpr_malloc(GPR_SLICE_LENGTH(slice) + 1);
-  memcpy(result, GPR_SLICE_START_PTR(slice), GPR_SLICE_LENGTH(slice));
-  result[GPR_SLICE_LENGTH(slice)] = '\0';
-  return result;
-}

+ 4 - 4
src/core/support/stack_lockfree.c

@@ -128,8 +128,8 @@ int gpr_stack_lockfree_push(gpr_stack_lockfree *stack, int entry) {
     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 & (gpr_atm)(1UL << pushed_bit)) == 0);
+                                           ((gpr_atm)1 << pushed_bit));
+    GPR_ASSERT((old_val & (((gpr_atm)1) << pushed_bit)) == 0);
   }
 #endif
 
@@ -166,8 +166,8 @@ int gpr_stack_lockfree_pop(gpr_stack_lockfree *stack) {
     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 & (gpr_atm)(1UL << pushed_bit)) != 0);
+                                           -((gpr_atm)1 << pushed_bit));
+    GPR_ASSERT((old_val & (((gpr_atm)1) << pushed_bit)) != 0);
   }
 #endif
 

+ 25 - 4
src/core/support/string.c

@@ -153,8 +153,8 @@ void gpr_reverse_bytes(char *str, int len) {
 }
 
 int gpr_ltoa(long value, char *string) {
+  long sign;
   int i = 0;
-  int neg = value < 0;
 
   if (value == 0) {
     string[0] = '0';
@@ -162,12 +162,33 @@ int gpr_ltoa(long value, char *string) {
     return 1;
   }
 
-  if (neg) value = -value;
+  sign = value < 0 ? -1 : 1;
   while (value) {
-    string[i++] = (char)('0' + value % 10);
+    string[i++] = (char)('0' + sign * (value % 10));
     value /= 10;
   }
-  if (neg) string[i++] = '-';
+  if (sign < 0) string[i++] = '-';
+  gpr_reverse_bytes(string, i);
+  string[i] = 0;
+  return i;
+}
+
+int gpr_int64toa(gpr_int64 value, char *string) {
+  gpr_int64 sign;
+  int i = 0;
+
+  if (value == 0) {
+    string[0] = '0';
+    string[1] = 0;
+    return 1;
+  }
+
+  sign = value < 0 ? -1 : 1;
+  while (value) {
+    string[i++] = (char)('0' + sign * (value % 10));
+    value /= 10;
+  }
+  if (sign < 0) string[i++] = '-';
   gpr_reverse_bytes(string, i);
   string[i] = 0;
   return i;

+ 10 - 0
src/core/support/string.h

@@ -70,6 +70,16 @@ int gpr_parse_bytes_to_uint32(const char *data, size_t length,
    output must be at least GPR_LTOA_MIN_BUFSIZE bytes long. */
 int gpr_ltoa(long value, char *output);
 
+/* Minimum buffer size for calling int64toa */
+#define GPR_INT64TOA_MIN_BUFSIZE (3 * sizeof(gpr_int64))
+
+/* Convert an int64 to a string in base 10; returns the length of the
+output string (or 0 on failure).
+output must be at least GPR_INT64TOA_MIN_BUFSIZE bytes long.
+NOTE: This function ensures sufficient bit width even on Win x64,
+where long is 32bit is size.*/
+int gpr_int64toa(gpr_int64 value, char *output);
+
 /* Reverse a run of bytes */
 void gpr_reverse_bytes(char *str, int len);
 

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov