grpc 1.3.4 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (286) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +581 -450
  3. data/include/grpc/census.h +49 -49
  4. data/include/grpc/grpc.h +16 -70
  5. data/include/grpc/grpc_security.h +59 -59
  6. data/include/grpc/grpc_security_constants.h +9 -9
  7. data/include/grpc/impl/codegen/atm.h +1 -1
  8. data/include/grpc/impl/codegen/atm_windows.h +4 -4
  9. data/include/grpc/impl/codegen/byte_buffer_reader.h +2 -2
  10. data/include/grpc/impl/codegen/compression_types.h +4 -5
  11. data/include/grpc/impl/codegen/gpr_slice.h +5 -5
  12. data/include/grpc/impl/codegen/gpr_types.h +6 -7
  13. data/include/grpc/impl/codegen/grpc_types.h +128 -59
  14. data/include/grpc/impl/codegen/port_platform.h +6 -0
  15. data/include/grpc/impl/codegen/propagation_bits.h +2 -2
  16. data/include/grpc/impl/codegen/slice.h +13 -12
  17. data/include/grpc/impl/codegen/status.h +23 -18
  18. data/include/grpc/impl/codegen/sync.h +1 -1
  19. data/include/grpc/load_reporting.h +6 -6
  20. data/include/grpc/slice.h +47 -25
  21. data/include/grpc/slice_buffer.h +18 -14
  22. data/include/grpc/support/alloc.h +7 -7
  23. data/include/grpc/support/cmdline.h +10 -10
  24. data/include/grpc/support/cpu.h +3 -3
  25. data/include/grpc/support/histogram.h +1 -1
  26. data/include/grpc/support/host_port.h +2 -2
  27. data/include/grpc/support/log.h +9 -9
  28. data/include/grpc/support/log_windows.h +1 -1
  29. data/include/grpc/support/string_util.h +3 -3
  30. data/include/grpc/support/subprocess.h +3 -3
  31. data/include/grpc/support/sync.h +31 -31
  32. data/include/grpc/support/thd.h +11 -11
  33. data/include/grpc/support/time.h +12 -12
  34. data/include/grpc/support/tls.h +1 -1
  35. data/include/grpc/support/tls_gcc.h +2 -2
  36. data/include/grpc/support/tls_msvc.h +1 -1
  37. data/include/grpc/support/tls_pthread.h +1 -1
  38. data/include/grpc/support/useful.h +2 -2
  39. data/include/grpc/support/workaround_list.h +46 -0
  40. data/src/core/ext/census/context.c +1 -1
  41. data/src/core/ext/census/intrusive_hash_map.c +319 -0
  42. data/src/core/ext/census/intrusive_hash_map.h +167 -0
  43. data/src/core/ext/census/intrusive_hash_map_internal.h +63 -0
  44. data/src/core/ext/census/resource.c +3 -1
  45. data/src/core/ext/filters/client_channel/channel_connectivity.c +1 -1
  46. data/src/core/ext/filters/client_channel/client_channel.c +173 -103
  47. data/src/core/ext/filters/client_channel/client_channel_plugin.c +3 -2
  48. data/src/core/ext/filters/client_channel/lb_policy.c +2 -1
  49. data/src/core/ext/filters/client_channel/lb_policy.h +8 -7
  50. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c +153 -0
  51. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h +42 -0
  52. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c +405 -102
  53. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c +133 -0
  54. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +65 -0
  55. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c +90 -51
  56. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +7 -1
  57. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c +19 -8
  58. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h +63 -34
  59. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c +2 -1
  60. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c +188 -294
  61. data/src/core/ext/filters/client_channel/lb_policy_factory.c +28 -5
  62. data/src/core/ext/filters/client_channel/lb_policy_factory.h +18 -4
  63. data/src/core/ext/filters/client_channel/parse_address.c +90 -59
  64. data/src/core/ext/filters/client_channel/parse_address.h +17 -8
  65. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c +11 -7
  66. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c +59 -14
  67. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +6 -0
  68. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c +3 -3
  69. data/src/core/ext/filters/client_channel/subchannel.c +20 -17
  70. data/src/core/ext/filters/client_channel/subchannel.h +1 -0
  71. data/src/core/ext/filters/client_channel/subchannel_index.c +11 -1
  72. data/src/core/ext/filters/client_channel/uri_parser.c +36 -22
  73. data/src/core/ext/filters/client_channel/uri_parser.h +1 -1
  74. data/src/core/{lib/channel → ext/filters/deadline}/deadline_filter.c +42 -17
  75. data/src/core/{lib/channel → ext/filters/deadline}/deadline_filter.h +8 -9
  76. data/src/core/{lib/channel → ext/filters/http/client}/http_client_filter.c +19 -11
  77. data/src/core/{lib/channel → ext/filters/http/client}/http_client_filter.h +3 -6
  78. data/src/core/ext/filters/http/http_filters_plugin.c +104 -0
  79. data/src/core/{lib/channel/compress_filter.c → ext/filters/http/message_compress/message_compress_filter.c} +124 -23
  80. data/src/core/{lib/channel/compress_filter.h → ext/filters/http/message_compress/message_compress_filter.h} +5 -6
  81. data/src/core/{lib/channel → ext/filters/http/server}/http_server_filter.c +4 -6
  82. data/src/core/{lib/channel → ext/filters/http/server}/http_server_filter.h +3 -3
  83. data/src/core/ext/filters/load_reporting/load_reporting.c +2 -25
  84. data/src/core/ext/filters/load_reporting/load_reporting_filter.c +26 -1
  85. data/src/core/ext/filters/max_age/max_age_filter.c +14 -14
  86. data/src/core/{lib/channel → ext/filters/message_size}/message_size_filter.c +91 -47
  87. data/src/core/{lib/channel → ext/filters/message_size}/message_size_filter.h +3 -3
  88. data/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.c +223 -0
  89. data/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h +40 -0
  90. data/src/core/ext/filters/workarounds/workaround_utils.c +65 -0
  91. data/src/core/ext/filters/workarounds/workaround_utils.h +52 -0
  92. data/src/core/ext/transport/chttp2/client/insecure/channel_create.c +1 -1
  93. data/src/core/ext/transport/chttp2/server/chttp2_server.c +3 -2
  94. data/src/core/ext/transport/chttp2/transport/bin_decoder.c +2 -2
  95. data/src/core/ext/transport/chttp2/transport/bin_encoder.c +3 -3
  96. data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +319 -175
  97. data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +3 -2
  98. data/src/core/ext/transport/chttp2/transport/frame_data.c +203 -164
  99. data/src/core/ext/transport/chttp2/transport/frame_data.h +8 -14
  100. data/src/core/ext/transport/chttp2/transport/frame_goaway.c +1 -1
  101. data/src/core/ext/transport/chttp2/transport/frame_ping.c +1 -1
  102. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +1 -1
  103. data/src/core/ext/transport/chttp2/transport/frame_settings.c +5 -5
  104. data/src/core/ext/transport/chttp2/transport/frame_window_update.c +1 -1
  105. data/src/core/ext/transport/chttp2/transport/hpack_encoder.c +4 -4
  106. data/src/core/ext/transport/chttp2/transport/hpack_parser.c +2 -4
  107. data/src/core/ext/transport/chttp2/transport/hpack_table.c +4 -3
  108. data/src/core/ext/transport/chttp2/transport/internal.h +50 -33
  109. data/src/core/ext/transport/chttp2/transport/parsing.c +10 -11
  110. data/src/core/ext/transport/chttp2/transport/writing.c +32 -13
  111. data/src/core/lib/channel/channel_args.c +30 -9
  112. data/src/core/lib/channel/channel_args.h +5 -1
  113. data/src/core/lib/channel/channel_stack.c +1 -1
  114. data/src/core/lib/channel/channel_stack.h +2 -2
  115. data/src/core/lib/channel/channel_stack_builder.c +13 -1
  116. data/src/core/lib/channel/channel_stack_builder.h +5 -1
  117. data/src/core/lib/channel/connected_channel.c +3 -1
  118. data/src/core/lib/channel/context.h +2 -2
  119. data/src/core/lib/compression/message_compress.c +2 -2
  120. data/src/core/lib/debug/trace.c +13 -6
  121. data/src/core/lib/debug/trace.h +27 -1
  122. data/src/core/lib/http/httpcli.c +1 -1
  123. data/src/core/lib/http/httpcli_security_connector.c +9 -11
  124. data/src/core/lib/http/parser.c +2 -2
  125. data/src/core/lib/http/parser.h +2 -1
  126. data/src/core/lib/iomgr/combiner.c +6 -6
  127. data/src/core/lib/iomgr/combiner.h +2 -1
  128. data/src/core/lib/iomgr/error.c +12 -5
  129. data/src/core/lib/iomgr/error.h +13 -13
  130. data/src/core/lib/iomgr/ev_epoll1_linux.c +984 -0
  131. data/src/core/lib/iomgr/ev_epoll1_linux.h +44 -0
  132. data/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c +2146 -0
  133. data/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h +43 -0
  134. data/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c +1337 -0
  135. data/src/core/lib/iomgr/ev_epoll_thread_pool_linux.h +43 -0
  136. data/src/core/lib/iomgr/ev_epollex_linux.c +1511 -0
  137. data/src/core/lib/iomgr/ev_epollex_linux.h +43 -0
  138. data/src/core/lib/iomgr/{ev_epoll_linux.c → ev_epollsig_linux.c} +41 -33
  139. data/src/core/lib/iomgr/{ev_epoll_linux.h → ev_epollsig_linux.h} +4 -4
  140. data/src/core/lib/iomgr/ev_poll_posix.c +12 -27
  141. data/src/core/lib/iomgr/ev_poll_posix.h +2 -2
  142. data/src/core/lib/iomgr/ev_posix.c +22 -8
  143. data/src/core/lib/iomgr/ev_posix.h +4 -3
  144. data/src/core/lib/iomgr/ev_windows.c +43 -0
  145. data/src/core/lib/iomgr/exec_ctx.c +5 -0
  146. data/src/core/lib/iomgr/exec_ctx.h +2 -0
  147. data/src/core/lib/iomgr/iomgr.c +4 -0
  148. data/src/core/lib/iomgr/iomgr.h +3 -0
  149. data/src/core/lib/iomgr/is_epollexclusive_available.c +116 -0
  150. data/src/core/lib/iomgr/is_epollexclusive_available.h +41 -0
  151. data/src/core/lib/iomgr/lockfree_event.c +16 -0
  152. data/src/core/lib/iomgr/pollset.h +2 -5
  153. data/src/core/lib/iomgr/pollset_uv.c +1 -1
  154. data/src/core/lib/iomgr/pollset_windows.c +3 -3
  155. data/src/core/lib/iomgr/resource_quota.c +9 -8
  156. data/src/core/lib/iomgr/resource_quota.h +2 -1
  157. data/src/core/lib/iomgr/sockaddr_utils.h +1 -1
  158. data/src/core/lib/iomgr/socket_mutator.h +2 -0
  159. data/src/core/lib/iomgr/sys_epoll_wrapper.h +43 -0
  160. data/src/core/lib/iomgr/tcp_client_posix.c +6 -6
  161. data/src/core/lib/iomgr/tcp_client_uv.c +3 -3
  162. data/src/core/lib/iomgr/tcp_posix.c +7 -7
  163. data/src/core/lib/iomgr/tcp_posix.h +2 -1
  164. data/src/core/lib/iomgr/tcp_server_posix.c +1 -1
  165. data/src/core/lib/iomgr/tcp_uv.c +6 -6
  166. data/src/core/lib/iomgr/tcp_uv.h +2 -1
  167. data/src/core/lib/iomgr/tcp_windows.c +1 -1
  168. data/src/core/lib/iomgr/timer_generic.c +24 -25
  169. data/src/core/lib/iomgr/timer_manager.c +276 -0
  170. data/src/core/lib/iomgr/timer_manager.h +52 -0
  171. data/src/core/lib/iomgr/timer_uv.c +6 -0
  172. data/src/core/lib/iomgr/udp_server.c +42 -9
  173. data/src/core/lib/iomgr/udp_server.h +3 -1
  174. data/src/core/lib/security/credentials/credentials.c +0 -1
  175. data/src/core/lib/security/credentials/fake/fake_credentials.c +23 -0
  176. data/src/core/lib/security/credentials/fake/fake_credentials.h +12 -9
  177. data/src/core/lib/security/credentials/google_default/google_default_credentials.c +1 -1
  178. data/src/core/lib/security/credentials/jwt/jwt_credentials.c +1 -1
  179. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +1 -1
  180. data/src/core/lib/security/credentials/ssl/ssl_credentials.c +24 -53
  181. data/src/core/lib/security/transport/client_auth_filter.c +9 -3
  182. data/src/core/lib/security/transport/secure_endpoint.c +7 -7
  183. data/src/core/lib/security/transport/secure_endpoint.h +1 -1
  184. data/src/core/lib/security/transport/security_connector.c +45 -57
  185. data/src/core/lib/security/transport/security_connector.h +10 -14
  186. data/src/core/lib/security/transport/security_handshaker.c +123 -97
  187. data/src/core/lib/slice/b64.c +1 -1
  188. data/src/core/lib/slice/percent_encoding.c +3 -3
  189. data/src/core/lib/slice/slice.c +66 -33
  190. data/src/core/lib/slice/slice_buffer.c +25 -6
  191. data/src/core/lib/slice/slice_hash_table.c +33 -35
  192. data/src/core/lib/slice/slice_hash_table.h +7 -12
  193. data/src/core/lib/support/atomic.h +45 -0
  194. data/src/core/lib/support/atomic_with_atm.h +70 -0
  195. data/src/core/lib/support/atomic_with_std.h +48 -0
  196. data/src/core/lib/support/avl.c +14 -14
  197. data/src/core/lib/support/cmdline.c +3 -3
  198. data/src/core/lib/support/histogram.c +2 -2
  199. data/src/core/lib/support/host_port.c +1 -1
  200. data/src/core/lib/support/memory.h +74 -0
  201. data/src/core/lib/support/mpscq.c +36 -2
  202. data/src/core/lib/support/mpscq.h +28 -1
  203. data/src/core/lib/support/stack_lockfree.c +3 -36
  204. data/src/core/lib/support/string.c +12 -12
  205. data/src/core/lib/support/string_posix.c +1 -1
  206. data/src/core/lib/support/subprocess_posix.c +2 -2
  207. data/src/core/lib/support/thd_posix.c +1 -1
  208. data/src/core/lib/support/time_posix.c +8 -0
  209. data/src/core/lib/support/tmpfile_posix.c +10 -10
  210. data/src/core/lib/surface/alarm.c +3 -1
  211. data/src/core/lib/surface/api_trace.c +2 -1
  212. data/src/core/lib/surface/api_trace.h +2 -2
  213. data/src/core/lib/surface/byte_buffer_reader.c +1 -1
  214. data/src/core/lib/surface/call.c +65 -22
  215. data/src/core/lib/surface/call.h +4 -2
  216. data/src/core/lib/surface/channel_init.c +2 -19
  217. data/src/core/lib/surface/channel_stack_type.c +18 -0
  218. data/src/core/lib/surface/channel_stack_type.h +2 -0
  219. data/src/core/lib/surface/completion_queue.c +694 -247
  220. data/src/core/lib/surface/completion_queue.h +30 -13
  221. data/src/core/lib/surface/completion_queue_factory.c +24 -9
  222. data/src/core/lib/surface/init.c +1 -52
  223. data/src/core/lib/surface/{lame_client.c → lame_client.cc} +37 -26
  224. data/src/core/lib/surface/server.c +79 -110
  225. data/src/core/lib/surface/server.h +2 -1
  226. data/src/core/lib/surface/version.c +2 -2
  227. data/src/core/lib/transport/bdp_estimator.c +25 -9
  228. data/src/core/lib/transport/bdp_estimator.h +7 -1
  229. data/src/core/lib/transport/byte_stream.c +23 -9
  230. data/src/core/lib/transport/byte_stream.h +15 -6
  231. data/src/core/lib/transport/connectivity_state.c +6 -6
  232. data/src/core/lib/transport/connectivity_state.h +2 -1
  233. data/src/core/lib/transport/service_config.c +6 -13
  234. data/src/core/lib/transport/service_config.h +2 -2
  235. data/src/core/lib/transport/static_metadata.c +403 -389
  236. data/src/core/lib/transport/static_metadata.h +127 -114
  237. data/src/core/plugin_registry/grpc_plugin_registry.c +16 -0
  238. data/src/core/tsi/fake_transport_security.c +5 -4
  239. data/src/core/tsi/ssl_transport_security.c +71 -82
  240. data/src/core/tsi/ssl_transport_security.h +39 -61
  241. data/src/core/tsi/transport_security.c +83 -2
  242. data/src/core/tsi/transport_security.h +27 -2
  243. data/src/core/tsi/transport_security_adapter.c +236 -0
  244. data/src/core/tsi/transport_security_adapter.h +62 -0
  245. data/src/core/tsi/transport_security_interface.h +179 -66
  246. data/src/ruby/ext/grpc/extconf.rb +2 -1
  247. data/src/ruby/ext/grpc/rb_byte_buffer.c +8 -6
  248. data/src/ruby/ext/grpc/rb_call.c +56 -48
  249. data/src/ruby/ext/grpc/rb_call.h +3 -4
  250. data/src/ruby/ext/grpc/rb_call_credentials.c +23 -22
  251. data/src/ruby/ext/grpc/rb_channel.c +2 -3
  252. data/src/ruby/ext/grpc/rb_channel_args.c +11 -9
  253. data/src/ruby/ext/grpc/rb_channel_credentials.c +16 -12
  254. data/src/ruby/ext/grpc/rb_completion_queue.c +7 -9
  255. data/src/ruby/ext/grpc/rb_compression_options.c +7 -6
  256. data/src/ruby/ext/grpc/rb_event_thread.c +10 -12
  257. data/src/ruby/ext/grpc/rb_event_thread.h +1 -2
  258. data/src/ruby/ext/grpc/rb_grpc.c +11 -15
  259. data/src/ruby/ext/grpc/rb_grpc.h +2 -2
  260. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +16 -6
  261. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +25 -10
  262. data/src/ruby/ext/grpc/rb_server.c +26 -28
  263. data/src/ruby/lib/grpc/grpc.rb +1 -1
  264. data/src/ruby/lib/grpc/version.rb +1 -1
  265. data/third_party/cares/config_linux/ares_config.h +36 -2
  266. data/third_party/zlib/adler32.c +14 -7
  267. data/third_party/zlib/compress.c +24 -18
  268. data/third_party/zlib/crc32.c +29 -12
  269. data/third_party/zlib/deflate.c +499 -303
  270. data/third_party/zlib/deflate.h +19 -16
  271. data/third_party/zlib/gzguts.h +16 -7
  272. data/third_party/zlib/gzlib.c +17 -14
  273. data/third_party/zlib/gzread.c +108 -48
  274. data/third_party/zlib/gzwrite.c +210 -122
  275. data/third_party/zlib/infback.c +2 -2
  276. data/third_party/zlib/inffast.c +34 -51
  277. data/third_party/zlib/inflate.c +86 -37
  278. data/third_party/zlib/inflate.h +7 -4
  279. data/third_party/zlib/inftrees.c +12 -14
  280. data/third_party/zlib/trees.c +38 -61
  281. data/third_party/zlib/uncompr.c +66 -32
  282. data/third_party/zlib/zconf.h +32 -9
  283. data/third_party/zlib/zlib.h +298 -154
  284. data/third_party/zlib/zutil.c +25 -24
  285. data/third_party/zlib/zutil.h +35 -17
  286. metadata +63 -30
@@ -34,11 +34,14 @@
34
34
  #ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_CONNECTOR_H
35
35
  #define GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_CONNECTOR_H
36
36
 
37
+ #include <stdbool.h>
38
+
37
39
  #include <grpc/grpc_security.h>
38
40
 
39
41
  #include "src/core/lib/channel/handshaker.h"
40
42
  #include "src/core/lib/iomgr/endpoint.h"
41
43
  #include "src/core/lib/iomgr/tcp_server.h"
44
+ #include "src/core/tsi/ssl_transport_security.h"
42
45
  #include "src/core/tsi/transport_security_interface.h"
43
46
 
44
47
  /* --- status enum. --- */
@@ -184,13 +187,10 @@ grpc_server_security_connector *grpc_fake_server_security_connector_create(
184
187
  void);
185
188
 
186
189
  /* Config for ssl clients. */
190
+
187
191
  typedef struct {
188
- unsigned char *pem_private_key;
189
- size_t pem_private_key_size;
190
- unsigned char *pem_cert_chain;
191
- size_t pem_cert_chain_size;
192
- unsigned char *pem_root_certs;
193
- size_t pem_root_certs_size;
192
+ tsi_ssl_pem_key_cert_pair pem_key_cert_pair;
193
+ char *pem_root_certs;
194
194
  } grpc_ssl_config;
195
195
 
196
196
  /* Creates an SSL channel_security_connector.
@@ -211,21 +211,17 @@ grpc_security_status grpc_ssl_channel_security_connector_create(
211
211
  const grpc_ssl_config *config, const char *target_name,
212
212
  const char *overridden_target_name, grpc_channel_security_connector **sc);
213
213
 
214
- /* Gets the default ssl roots. */
215
- size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs);
214
+ /* Gets the default ssl roots. Returns NULL if not found. */
215
+ const char *grpc_get_default_ssl_roots(void);
216
216
 
217
217
  /* Exposed for TESTING ONLY!. */
218
218
  grpc_slice grpc_get_default_ssl_roots_for_testing(void);
219
219
 
220
220
  /* Config for ssl servers. */
221
221
  typedef struct {
222
- unsigned char **pem_private_keys;
223
- size_t *pem_private_keys_sizes;
224
- unsigned char **pem_cert_chains;
225
- size_t *pem_cert_chains_sizes;
222
+ tsi_ssl_pem_key_cert_pair *pem_key_cert_pairs;
226
223
  size_t num_key_cert_pairs;
227
- unsigned char *pem_root_certs;
228
- size_t pem_root_certs_size;
224
+ char *pem_root_certs;
229
225
  grpc_ssl_client_certificate_request_type client_certificate_request;
230
226
  } grpc_ssl_server_config;
231
227
 
@@ -71,12 +71,12 @@ typedef struct {
71
71
 
72
72
  unsigned char *handshake_buffer;
73
73
  size_t handshake_buffer_size;
74
- grpc_slice_buffer left_overs;
75
74
  grpc_slice_buffer outgoing;
76
75
  grpc_closure on_handshake_data_sent_to_peer;
77
76
  grpc_closure on_handshake_data_received_from_peer;
78
77
  grpc_closure on_peer_checked;
79
78
  grpc_auth_context *auth_context;
79
+ tsi_handshaker_result *handshaker_result;
80
80
  } security_handshaker;
81
81
 
82
82
  static void security_handshaker_unref(grpc_exec_ctx *exec_ctx,
@@ -84,6 +84,7 @@ static void security_handshaker_unref(grpc_exec_ctx *exec_ctx,
84
84
  if (gpr_unref(&h->refs)) {
85
85
  gpr_mu_destroy(&h->mu);
86
86
  tsi_handshaker_destroy(h->handshaker);
87
+ tsi_handshaker_result_destroy(h->handshaker_result);
87
88
  if (h->endpoint_to_destroy != NULL) {
88
89
  grpc_endpoint_destroy(exec_ctx, h->endpoint_to_destroy);
89
90
  }
@@ -92,7 +93,6 @@ static void security_handshaker_unref(grpc_exec_ctx *exec_ctx,
92
93
  gpr_free(h->read_buffer_to_destroy);
93
94
  }
94
95
  gpr_free(h->handshake_buffer);
95
- grpc_slice_buffer_destroy_internal(exec_ctx, &h->left_overs);
96
96
  grpc_slice_buffer_destroy_internal(exec_ctx, &h->outgoing);
97
97
  GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake");
98
98
  GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, h->connector, "handshake");
@@ -150,10 +150,10 @@ static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *arg,
150
150
  security_handshake_failed_locked(exec_ctx, h, GRPC_ERROR_REF(error));
151
151
  goto done;
152
152
  }
153
- // Get frame protector.
153
+ // Create frame protector.
154
154
  tsi_frame_protector *protector;
155
- tsi_result result =
156
- tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector);
155
+ tsi_result result = tsi_handshaker_result_create_frame_protector(
156
+ h->handshaker_result, NULL, &protector);
157
157
  if (result != TSI_OK) {
158
158
  error = grpc_set_tsi_error_result(
159
159
  GRPC_ERROR_CREATE_FROM_STATIC_STRING("Frame protector creation failed"),
@@ -161,14 +161,25 @@ static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *arg,
161
161
  security_handshake_failed_locked(exec_ctx, h, error);
162
162
  goto done;
163
163
  }
164
- // Success.
164
+ // Get unused bytes.
165
+ unsigned char *unused_bytes = NULL;
166
+ size_t unused_bytes_size = 0;
167
+ result = tsi_handshaker_result_get_unused_bytes(
168
+ h->handshaker_result, &unused_bytes, &unused_bytes_size);
165
169
  // Create secure endpoint.
166
- h->args->endpoint = grpc_secure_endpoint_create(
167
- protector, h->args->endpoint, h->left_overs.slices, h->left_overs.count);
168
- h->left_overs.count = 0;
169
- h->left_overs.length = 0;
170
- // Clear out the read buffer before it gets passed to the transport,
171
- // since any excess bytes were already copied to h->left_overs.
170
+ if (unused_bytes_size > 0) {
171
+ grpc_slice slice =
172
+ grpc_slice_from_copied_buffer((char *)unused_bytes, unused_bytes_size);
173
+ h->args->endpoint =
174
+ grpc_secure_endpoint_create(protector, h->args->endpoint, &slice, 1);
175
+ grpc_slice_unref_internal(exec_ctx, slice);
176
+ } else {
177
+ h->args->endpoint =
178
+ grpc_secure_endpoint_create(protector, h->args->endpoint, NULL, 0);
179
+ }
180
+ tsi_handshaker_result_destroy(h->handshaker_result);
181
+ h->handshaker_result = NULL;
182
+ // Clear out the read buffer before it gets passed to the transport.
172
183
  grpc_slice_buffer_reset_and_unref_internal(exec_ctx, h->args->read_buffer);
173
184
  // Add auth context to channel args.
174
185
  grpc_arg auth_context_arg = grpc_auth_context_to_arg(h->auth_context);
@@ -189,7 +200,8 @@ done:
189
200
  static grpc_error *check_peer_locked(grpc_exec_ctx *exec_ctx,
190
201
  security_handshaker *h) {
191
202
  tsi_peer peer;
192
- tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer);
203
+ tsi_result result =
204
+ tsi_handshaker_result_extract_peer(h->handshaker_result, &peer);
193
205
  if (result != TSI_OK) {
194
206
  return grpc_set_tsi_error_result(
195
207
  GRPC_ERROR_CREATE_FROM_STATIC_STRING("Peer extraction failed"), result);
@@ -199,34 +211,87 @@ static grpc_error *check_peer_locked(grpc_exec_ctx *exec_ctx,
199
211
  return GRPC_ERROR_NONE;
200
212
  }
201
213
 
202
- static grpc_error *send_handshake_bytes_to_peer_locked(grpc_exec_ctx *exec_ctx,
203
- security_handshaker *h) {
204
- // Get data to send.
205
- tsi_result result = TSI_OK;
206
- size_t offset = 0;
207
- do {
208
- size_t to_send_size = h->handshake_buffer_size - offset;
209
- result = tsi_handshaker_get_bytes_to_send_to_peer(
210
- h->handshaker, h->handshake_buffer + offset, &to_send_size);
211
- offset += to_send_size;
212
- if (result == TSI_INCOMPLETE_DATA) {
213
- h->handshake_buffer_size *= 2;
214
- h->handshake_buffer =
215
- gpr_realloc(h->handshake_buffer, h->handshake_buffer_size);
216
- }
217
- } while (result == TSI_INCOMPLETE_DATA);
214
+ static grpc_error *on_handshake_next_done_locked(
215
+ grpc_exec_ctx *exec_ctx, security_handshaker *h, tsi_result result,
216
+ const unsigned char *bytes_to_send, size_t bytes_to_send_size,
217
+ tsi_handshaker_result *handshaker_result) {
218
+ grpc_error *error = GRPC_ERROR_NONE;
219
+ // Read more if we need to.
220
+ if (result == TSI_INCOMPLETE_DATA) {
221
+ GPR_ASSERT(bytes_to_send_size == 0);
222
+ grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
223
+ &h->on_handshake_data_received_from_peer);
224
+ return error;
225
+ }
218
226
  if (result != TSI_OK) {
219
227
  return grpc_set_tsi_error_result(
220
228
  GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake failed"), result);
221
229
  }
222
- // Send data.
223
- grpc_slice to_send =
224
- grpc_slice_from_copied_buffer((const char *)h->handshake_buffer, offset);
225
- grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &h->outgoing);
226
- grpc_slice_buffer_add(&h->outgoing, to_send);
227
- grpc_endpoint_write(exec_ctx, h->args->endpoint, &h->outgoing,
228
- &h->on_handshake_data_sent_to_peer);
229
- return GRPC_ERROR_NONE;
230
+ // Update handshaker result.
231
+ if (handshaker_result != NULL) {
232
+ GPR_ASSERT(h->handshaker_result == NULL);
233
+ h->handshaker_result = handshaker_result;
234
+ }
235
+ if (bytes_to_send_size > 0) {
236
+ // Send data to peer, if needed.
237
+ grpc_slice to_send = grpc_slice_from_copied_buffer(
238
+ (const char *)bytes_to_send, bytes_to_send_size);
239
+ grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &h->outgoing);
240
+ grpc_slice_buffer_add(&h->outgoing, to_send);
241
+ grpc_endpoint_write(exec_ctx, h->args->endpoint, &h->outgoing,
242
+ &h->on_handshake_data_sent_to_peer);
243
+ } else if (handshaker_result == NULL) {
244
+ // There is nothing to send, but need to read from peer.
245
+ grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
246
+ &h->on_handshake_data_received_from_peer);
247
+ } else {
248
+ // Handshake has finished, check peer and so on.
249
+ error = check_peer_locked(exec_ctx, h);
250
+ }
251
+ return error;
252
+ }
253
+
254
+ static void on_handshake_next_done_grpc_wrapper(
255
+ tsi_result result, void *user_data, const unsigned char *bytes_to_send,
256
+ size_t bytes_to_send_size, tsi_handshaker_result *handshaker_result) {
257
+ security_handshaker *h = user_data;
258
+ // This callback will be invoked by TSI in a non-grpc thread, so it's
259
+ // safe to create our own exec_ctx here.
260
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
261
+ gpr_mu_lock(&h->mu);
262
+ grpc_error *error =
263
+ on_handshake_next_done_locked(&exec_ctx, h, result, bytes_to_send,
264
+ bytes_to_send_size, handshaker_result);
265
+ if (error != GRPC_ERROR_NONE) {
266
+ security_handshake_failed_locked(&exec_ctx, h, error);
267
+ gpr_mu_unlock(&h->mu);
268
+ security_handshaker_unref(&exec_ctx, h);
269
+ } else {
270
+ gpr_mu_unlock(&h->mu);
271
+ }
272
+ grpc_exec_ctx_finish(&exec_ctx);
273
+ }
274
+
275
+ static grpc_error *do_handshaker_next_locked(
276
+ grpc_exec_ctx *exec_ctx, security_handshaker *h,
277
+ const unsigned char *bytes_received, size_t bytes_received_size) {
278
+ // Invoke TSI handshaker.
279
+ unsigned char *bytes_to_send = NULL;
280
+ size_t bytes_to_send_size = 0;
281
+ tsi_handshaker_result *handshaker_result = NULL;
282
+ tsi_result result = tsi_handshaker_next(
283
+ h->handshaker, bytes_received, bytes_received_size, &bytes_to_send,
284
+ &bytes_to_send_size, &handshaker_result,
285
+ &on_handshake_next_done_grpc_wrapper, h);
286
+ if (result == TSI_ASYNC) {
287
+ // Handshaker operating asynchronously. Nothing else to do here;
288
+ // callback will be invoked in a TSI thread.
289
+ return GRPC_ERROR_NONE;
290
+ }
291
+ // Handshaker returned synchronously. Invoke callback directly in
292
+ // this thread with our existing exec_ctx.
293
+ return on_handshake_next_done_locked(exec_ctx, h, result, bytes_to_send,
294
+ bytes_to_send_size, handshaker_result);
230
295
  }
231
296
 
232
297
  static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
@@ -241,72 +306,34 @@ static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
241
306
  security_handshaker_unref(exec_ctx, h);
242
307
  return;
243
308
  }
244
- // Process received data.
245
- tsi_result result = TSI_OK;
246
- size_t consumed_slice_size = 0;
309
+ // Copy all slices received.
247
310
  size_t i;
311
+ size_t bytes_received_size = 0;
248
312
  for (i = 0; i < h->args->read_buffer->count; i++) {
249
- consumed_slice_size = GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]);
250
- result = tsi_handshaker_process_bytes_from_peer(
251
- h->handshaker, GRPC_SLICE_START_PTR(h->args->read_buffer->slices[i]),
252
- &consumed_slice_size);
253
- if (!tsi_handshaker_is_in_progress(h->handshaker)) break;
313
+ bytes_received_size += GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]);
254
314
  }
255
- if (tsi_handshaker_is_in_progress(h->handshaker)) {
256
- /* We may need more data. */
257
- if (result == TSI_INCOMPLETE_DATA) {
258
- grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
259
- &h->on_handshake_data_received_from_peer);
260
- goto done;
261
- } else {
262
- error = send_handshake_bytes_to_peer_locked(exec_ctx, h);
263
- if (error != GRPC_ERROR_NONE) {
264
- security_handshake_failed_locked(exec_ctx, h, error);
265
- gpr_mu_unlock(&h->mu);
266
- security_handshaker_unref(exec_ctx, h);
267
- return;
268
- }
269
- goto done;
270
- }
315
+ if (bytes_received_size > h->handshake_buffer_size) {
316
+ h->handshake_buffer = gpr_realloc(h->handshake_buffer, bytes_received_size);
317
+ h->handshake_buffer_size = bytes_received_size;
271
318
  }
272
- if (result != TSI_OK) {
273
- security_handshake_failed_locked(
274
- exec_ctx, h,
275
- grpc_set_tsi_error_result(
276
- GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake failed"), result));
277
- gpr_mu_unlock(&h->mu);
278
- security_handshaker_unref(exec_ctx, h);
279
- return;
280
- }
281
- /* Handshake is done and successful this point. */
282
- bool has_left_overs_in_current_slice =
283
- (consumed_slice_size <
284
- GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]));
285
- size_t num_left_overs = (has_left_overs_in_current_slice ? 1 : 0) +
286
- h->args->read_buffer->count - i - 1;
287
- if (num_left_overs > 0) {
288
- /* Put the leftovers in our buffer (ownership transfered). */
289
- if (has_left_overs_in_current_slice) {
290
- grpc_slice tail = grpc_slice_split_tail(&h->args->read_buffer->slices[i],
291
- consumed_slice_size);
292
- grpc_slice_buffer_add(&h->left_overs, tail);
293
- /* split_tail above increments refcount. */
294
- grpc_slice_unref_internal(exec_ctx, tail);
295
- }
296
- grpc_slice_buffer_addn(
297
- &h->left_overs, &h->args->read_buffer->slices[i + 1],
298
- num_left_overs - (size_t)has_left_overs_in_current_slice);
319
+ size_t offset = 0;
320
+ for (i = 0; i < h->args->read_buffer->count; i++) {
321
+ size_t slice_size = GPR_SLICE_LENGTH(h->args->read_buffer->slices[i]);
322
+ memcpy(h->handshake_buffer + offset,
323
+ GRPC_SLICE_START_PTR(h->args->read_buffer->slices[i]), slice_size);
324
+ offset += slice_size;
299
325
  }
300
- // Check peer.
301
- error = check_peer_locked(exec_ctx, h);
326
+ // Call TSI handshaker.
327
+ error = do_handshaker_next_locked(exec_ctx, h, h->handshake_buffer,
328
+ bytes_received_size);
329
+
302
330
  if (error != GRPC_ERROR_NONE) {
303
331
  security_handshake_failed_locked(exec_ctx, h, error);
304
332
  gpr_mu_unlock(&h->mu);
305
333
  security_handshaker_unref(exec_ctx, h);
306
- return;
334
+ } else {
335
+ gpr_mu_unlock(&h->mu);
307
336
  }
308
- done:
309
- gpr_mu_unlock(&h->mu);
310
337
  }
311
338
 
312
339
  static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *arg,
@@ -321,8 +348,8 @@ static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *arg,
321
348
  security_handshaker_unref(exec_ctx, h);
322
349
  return;
323
350
  }
324
- /* We may be done. */
325
- if (tsi_handshaker_is_in_progress(h->handshaker)) {
351
+ // We may be done.
352
+ if (h->handshaker_result == NULL) {
326
353
  grpc_endpoint_read(exec_ctx, h->args->endpoint, h->args->read_buffer,
327
354
  &h->on_handshake_data_received_from_peer);
328
355
  } else {
@@ -371,7 +398,7 @@ static void security_handshaker_do_handshake(grpc_exec_ctx *exec_ctx,
371
398
  h->args = args;
372
399
  h->on_handshake_done = on_handshake_done;
373
400
  gpr_ref(&h->refs);
374
- grpc_error *error = send_handshake_bytes_to_peer_locked(exec_ctx, h);
401
+ grpc_error *error = do_handshaker_next_locked(exec_ctx, h, NULL, 0);
375
402
  if (error != GRPC_ERROR_NONE) {
376
403
  security_handshake_failed_locked(exec_ctx, h, error);
377
404
  gpr_mu_unlock(&h->mu);
@@ -404,7 +431,6 @@ static grpc_handshaker *security_handshaker_create(
404
431
  grpc_schedule_on_exec_ctx);
405
432
  grpc_closure_init(&h->on_peer_checked, on_peer_checked, h,
406
433
  grpc_schedule_on_exec_ctx);
407
- grpc_slice_buffer_init(&h->left_overs);
408
434
  grpc_slice_buffer_init(&h->outgoing);
409
435
  return &h->base;
410
436
  }
@@ -202,7 +202,7 @@ static int decode_group(const unsigned char *codes, size_t num_codes,
202
202
 
203
203
  grpc_slice grpc_base64_decode_with_len(grpc_exec_ctx *exec_ctx, const char *b64,
204
204
  size_t b64_len, int url_safe) {
205
- grpc_slice result = grpc_slice_malloc(b64_len);
205
+ grpc_slice result = GRPC_SLICE_MALLOC(b64_len);
206
206
  unsigned char *current = GRPC_SLICE_START_PTR(result);
207
207
  size_t result_size = 0;
208
208
  unsigned char codes[4];
@@ -71,7 +71,7 @@ grpc_slice grpc_percent_encode_slice(grpc_slice slice,
71
71
  return grpc_slice_ref_internal(slice);
72
72
  }
73
73
  // second pass: actually encode
74
- grpc_slice out = grpc_slice_malloc(output_length);
74
+ grpc_slice out = GRPC_SLICE_MALLOC(output_length);
75
75
  uint8_t *q = GRPC_SLICE_START_PTR(out);
76
76
  for (p = slice_start; p < slice_end; p++) {
77
77
  if (is_unreserved_character(*p, unreserved_bytes)) {
@@ -125,7 +125,7 @@ bool grpc_strict_percent_decode_slice(grpc_slice slice_in,
125
125
  return true;
126
126
  }
127
127
  p = GRPC_SLICE_START_PTR(slice_in);
128
- *slice_out = grpc_slice_malloc(out_length);
128
+ *slice_out = GRPC_SLICE_MALLOC(out_length);
129
129
  uint8_t *q = GRPC_SLICE_START_PTR(*slice_out);
130
130
  while (p != in_end) {
131
131
  if (*p == '%') {
@@ -163,7 +163,7 @@ grpc_slice grpc_permissive_percent_decode_slice(grpc_slice slice_in) {
163
163
  return grpc_slice_ref_internal(slice_in);
164
164
  }
165
165
  p = GRPC_SLICE_START_PTR(slice_in);
166
- grpc_slice out = grpc_slice_malloc(out_length);
166
+ grpc_slice out = GRPC_SLICE_MALLOC(out_length);
167
167
  uint8_t *q = GRPC_SLICE_START_PTR(out);
168
168
  while (p != in_end) {
169
169
  if (*p == '%') {
@@ -55,6 +55,13 @@ grpc_slice grpc_empty_slice(void) {
55
55
  return out;
56
56
  }
57
57
 
58
+ grpc_slice grpc_slice_copy(grpc_slice s) {
59
+ grpc_slice out = GRPC_SLICE_MALLOC(GRPC_SLICE_LENGTH(s));
60
+ memcpy(GRPC_SLICE_START_PTR(out), GRPC_SLICE_START_PTR(s),
61
+ GRPC_SLICE_LENGTH(s));
62
+ return out;
63
+ }
64
+
58
65
  grpc_slice grpc_slice_ref_internal(grpc_slice slice) {
59
66
  if (slice.refcount) {
60
67
  slice.refcount->vtable->ref(slice.refcount);
@@ -198,7 +205,7 @@ grpc_slice grpc_slice_new_with_len(void *p, size_t len,
198
205
 
199
206
  grpc_slice grpc_slice_from_copied_buffer(const char *source, size_t length) {
200
207
  if (length == 0) return grpc_empty_slice();
201
- grpc_slice slice = grpc_slice_malloc(length);
208
+ grpc_slice slice = GRPC_SLICE_MALLOC(length);
202
209
  memcpy(GRPC_SLICE_START_PTR(slice), source, length);
203
210
  return slice;
204
211
  }
@@ -228,35 +235,42 @@ static const grpc_slice_refcount_vtable malloc_vtable = {
228
235
  malloc_ref, malloc_unref, grpc_slice_default_eq_impl,
229
236
  grpc_slice_default_hash_impl};
230
237
 
238
+ grpc_slice grpc_slice_malloc_large(size_t length) {
239
+ grpc_slice slice;
240
+
241
+ /* Memory layout used by the slice created here:
242
+
243
+ +-----------+----------------------------------------------------------+
244
+ | refcount | bytes |
245
+ +-----------+----------------------------------------------------------+
246
+
247
+ refcount is a malloc_refcount
248
+ bytes is an array of bytes of the requested length
249
+ Both parts are placed in the same allocation returned from gpr_malloc */
250
+ malloc_refcount *rc = gpr_malloc(sizeof(malloc_refcount) + length);
251
+
252
+ /* Initial refcount on rc is 1 - and it's up to the caller to release
253
+ this reference. */
254
+ gpr_ref_init(&rc->refs, 1);
255
+
256
+ rc->base.vtable = &malloc_vtable;
257
+ rc->base.sub_refcount = &rc->base;
258
+
259
+ /* Build up the slice to be returned. */
260
+ /* The slices refcount points back to the allocated block. */
261
+ slice.refcount = &rc->base;
262
+ /* The data bytes are placed immediately after the refcount struct */
263
+ slice.data.refcounted.bytes = (uint8_t *)(rc + 1);
264
+ /* And the length of the block is set to the requested length */
265
+ slice.data.refcounted.length = length;
266
+ return slice;
267
+ }
268
+
231
269
  grpc_slice grpc_slice_malloc(size_t length) {
232
270
  grpc_slice slice;
233
271
 
234
272
  if (length > sizeof(slice.data.inlined.bytes)) {
235
- /* Memory layout used by the slice created here:
236
-
237
- +-----------+----------------------------------------------------------+
238
- | refcount | bytes |
239
- +-----------+----------------------------------------------------------+
240
-
241
- refcount is a malloc_refcount
242
- bytes is an array of bytes of the requested length
243
- Both parts are placed in the same allocation returned from gpr_malloc */
244
- malloc_refcount *rc = gpr_malloc(sizeof(malloc_refcount) + length);
245
-
246
- /* Initial refcount on rc is 1 - and it's up to the caller to release
247
- this reference. */
248
- gpr_ref_init(&rc->refs, 1);
249
-
250
- rc->base.vtable = &malloc_vtable;
251
- rc->base.sub_refcount = &rc->base;
252
-
253
- /* Build up the slice to be returned. */
254
- /* The slices refcount points back to the allocated block. */
255
- slice.refcount = &rc->base;
256
- /* The data bytes are placed immediately after the refcount struct */
257
- slice.data.refcounted.bytes = (uint8_t *)(rc + 1);
258
- /* And the length of the block is set to the requested length */
259
- slice.data.refcounted.length = length;
273
+ return grpc_slice_malloc_large(length);
260
274
  } else {
261
275
  /* small slice: just inline the data */
262
276
  slice.refcount = NULL;
@@ -306,7 +320,8 @@ grpc_slice grpc_slice_sub(grpc_slice source, size_t begin, size_t end) {
306
320
  return subset;
307
321
  }
308
322
 
309
- grpc_slice grpc_slice_split_tail(grpc_slice *source, size_t split) {
323
+ grpc_slice grpc_slice_split_tail_maybe_ref(grpc_slice *source, size_t split,
324
+ grpc_slice_ref_whom ref_whom) {
310
325
  grpc_slice tail;
311
326
 
312
327
  if (source->refcount == NULL) {
@@ -320,28 +335,46 @@ grpc_slice grpc_slice_split_tail(grpc_slice *source, size_t split) {
320
335
  } else {
321
336
  size_t tail_length = source->data.refcounted.length - split;
322
337
  GPR_ASSERT(source->data.refcounted.length >= split);
323
- if (tail_length < sizeof(tail.data.inlined.bytes)) {
338
+ if (tail_length < sizeof(tail.data.inlined.bytes) &&
339
+ ref_whom != GRPC_SLICE_REF_TAIL) {
324
340
  /* Copy out the bytes - it'll be cheaper than refcounting */
325
341
  tail.refcount = NULL;
326
342
  tail.data.inlined.length = (uint8_t)tail_length;
327
343
  memcpy(tail.data.inlined.bytes, source->data.refcounted.bytes + split,
328
344
  tail_length);
345
+ source->refcount = source->refcount->sub_refcount;
329
346
  } else {
330
347
  /* Build the result */
331
- tail.refcount = source->refcount->sub_refcount;
332
- /* Bump the refcount */
333
- tail.refcount->vtable->ref(tail.refcount);
348
+ switch (ref_whom) {
349
+ case GRPC_SLICE_REF_TAIL:
350
+ tail.refcount = source->refcount->sub_refcount;
351
+ source->refcount = &noop_refcount;
352
+ break;
353
+ case GRPC_SLICE_REF_HEAD:
354
+ tail.refcount = &noop_refcount;
355
+ source->refcount = source->refcount->sub_refcount;
356
+ break;
357
+ case GRPC_SLICE_REF_BOTH:
358
+ tail.refcount = source->refcount->sub_refcount;
359
+ source->refcount = source->refcount->sub_refcount;
360
+ /* Bump the refcount */
361
+ tail.refcount->vtable->ref(tail.refcount);
362
+ break;
363
+ }
334
364
  /* Point into the source array */
335
365
  tail.data.refcounted.bytes = source->data.refcounted.bytes + split;
336
366
  tail.data.refcounted.length = tail_length;
337
367
  }
338
- source->refcount = source->refcount->sub_refcount;
339
368
  source->data.refcounted.length = split;
340
369
  }
341
370
 
342
371
  return tail;
343
372
  }
344
373
 
374
+ grpc_slice grpc_slice_split_tail(grpc_slice *source, size_t split) {
375
+ return grpc_slice_split_tail_maybe_ref(source, split, GRPC_SLICE_REF_BOTH);
376
+ }
377
+
345
378
  grpc_slice grpc_slice_split_head(grpc_slice *source, size_t split) {
346
379
  grpc_slice head;
347
380
 
@@ -459,7 +492,7 @@ int grpc_slice_slice(grpc_slice haystack, grpc_slice needle) {
459
492
  }
460
493
 
461
494
  grpc_slice grpc_slice_dup(grpc_slice a) {
462
- grpc_slice copy = grpc_slice_malloc(GRPC_SLICE_LENGTH(a));
495
+ grpc_slice copy = GRPC_SLICE_MALLOC(GRPC_SLICE_LENGTH(a));
463
496
  memcpy(GRPC_SLICE_START_PTR(copy), GRPC_SLICE_START_PTR(a),
464
497
  GRPC_SLICE_LENGTH(a));
465
498
  return copy;