Revert "Revert "All instances of exec_ctx being passed around in src/core removed""

pull/13659/head
Yash Tibrewal 7 years ago committed by GitHub
parent 1d4e995084
commit 8cf1470a51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      include/grpc++/support/channel_arguments.h
  2. 2
      include/grpc/impl/codegen/grpc_types.h
  3. 2
      include/grpc/impl/codegen/slice.h
  4. 3
      include/grpc/slice_buffer.h
  5. 6
      include/grpc/support/tls.h
  6. 5
      include/grpc/support/tls_gcc.h
  7. 9
      include/grpc/support/tls_msvc.h
  8. 9
      include/grpc/support/tls_pthread.h
  9. 47
      src/core/ext/filters/client_channel/backup_poller.cc
  10. 4
      src/core/ext/filters/client_channel/backup_poller.h
  11. 52
      src/core/ext/filters/client_channel/channel_connectivity.cc
  12. 407
      src/core/ext/filters/client_channel/client_channel.cc
  13. 8
      src/core/ext/filters/client_channel/client_channel.h
  14. 23
      src/core/ext/filters/client_channel/client_channel_factory.cc
  15. 19
      src/core/ext/filters/client_channel/client_channel_factory.h
  16. 13
      src/core/ext/filters/client_channel/client_channel_plugin.cc
  17. 13
      src/core/ext/filters/client_channel/connector.cc
  18. 14
      src/core/ext/filters/client_channel/connector.h
  19. 84
      src/core/ext/filters/client_channel/http_connect_handshaker.cc
  20. 18
      src/core/ext/filters/client_channel/http_proxy.cc
  21. 79
      src/core/ext/filters/client_channel/lb_policy.cc
  22. 80
      src/core/ext/filters/client_channel/lb_policy.h
  23. 27
      src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc
  24. 430
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
  25. 6
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.cc
  26. 4
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h
  27. 10
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc
  28. 190
      src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
  29. 140
      src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
  30. 54
      src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc
  31. 18
      src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
  32. 15
      src/core/ext/filters/client_channel/lb_policy_factory.cc
  33. 11
      src/core/ext/filters/client_channel/lb_policy_factory.h
  34. 4
      src/core/ext/filters/client_channel/lb_policy_registry.cc
  35. 2
      src/core/ext/filters/client_channel/lb_policy_registry.h
  36. 14
      src/core/ext/filters/client_channel/proxy_mapper.cc
  37. 14
      src/core/ext/filters/client_channel/proxy_mapper.h
  38. 30
      src/core/ext/filters/client_channel/proxy_mapper_registry.cc
  39. 6
      src/core/ext/filters/client_channel/proxy_mapper_registry.h
  40. 24
      src/core/ext/filters/client_channel/resolver.cc
  41. 31
      src/core/ext/filters/client_channel/resolver.h
  42. 94
      src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
  43. 6
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h
  44. 52
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
  45. 70
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
  46. 12
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
  47. 20
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc
  48. 90
      src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
  49. 52
      src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
  50. 2
      src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h
  51. 55
      src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc
  52. 5
      src/core/ext/filters/client_channel/resolver_factory.cc
  53. 6
      src/core/ext/filters/client_channel/resolver_factory.h
  54. 27
      src/core/ext/filters/client_channel/resolver_registry.cc
  55. 7
      src/core/ext/filters/client_channel/resolver_registry.h
  56. 239
      src/core/ext/filters/client_channel/subchannel.cc
  57. 75
      src/core/ext/filters/client_channel/subchannel.h
  58. 63
      src/core/ext/filters/client_channel/subchannel_index.cc
  59. 12
      src/core/ext/filters/client_channel/subchannel_index.h
  60. 28
      src/core/ext/filters/client_channel/uri_parser.cc
  61. 3
      src/core/ext/filters/client_channel/uri_parser.h
  62. 112
      src/core/ext/filters/deadline/deadline_filter.cc
  63. 10
      src/core/ext/filters/deadline/deadline_filter.h
  64. 125
      src/core/ext/filters/http/client/http_client_filter.cc
  65. 6
      src/core/ext/filters/http/http_filters_plugin.cc
  66. 126
      src/core/ext/filters/http/message_compress/message_compress_filter.cc
  67. 106
      src/core/ext/filters/http/server/http_server_filter.cc
  68. 33
      src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
  69. 2
      src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc
  70. 99
      src/core/ext/filters/max_age/max_age_filter.cc
  71. 36
      src/core/ext/filters/message_size/message_size_filter.cc
  72. 23
      src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc
  73. 70
      src/core/ext/transport/chttp2/client/chttp2_connector.cc
  74. 32
      src/core/ext/transport/chttp2/client/insecure/channel_create.cc
  75. 16
      src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc
  76. 51
      src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc
  77. 106
      src/core/ext/transport/chttp2/server/chttp2_server.cc
  78. 3
      src/core/ext/transport/chttp2/server/chttp2_server.h
  79. 6
      src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc
  80. 17
      src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc
  81. 11
      src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc
  82. 14
      src/core/ext/transport/chttp2/transport/bin_decoder.cc
  83. 5
      src/core/ext/transport/chttp2/transport/bin_decoder.h
  84. 2
      src/core/ext/transport/chttp2/transport/bin_encoder.h
  85. 1056
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  86. 7
      src/core/ext/transport/chttp2/transport/chttp2_transport.h
  87. 15
      src/core/ext/transport/chttp2/transport/flow_control.cc
  88. 7
      src/core/ext/transport/chttp2/transport/flow_control.h
  89. 62
      src/core/ext/transport/chttp2/transport/frame_data.cc
  90. 7
      src/core/ext/transport/chttp2/transport/frame_data.h
  91. 5
      src/core/ext/transport/chttp2/transport/frame_goaway.cc
  92. 3
      src/core/ext/transport/chttp2/transport/frame_goaway.h
  93. 11
      src/core/ext/transport/chttp2/transport/frame_ping.cc
  94. 2
      src/core/ext/transport/chttp2/transport/frame_ping.h
  95. 5
      src/core/ext/transport/chttp2/transport/frame_rst_stream.cc
  96. 3
      src/core/ext/transport/chttp2/transport/frame_rst_stream.h
  97. 5
      src/core/ext/transport/chttp2/transport/frame_settings.cc
  98. 3
      src/core/ext/transport/chttp2/transport/frame_settings.h
  99. 16
      src/core/ext/transport/chttp2/transport/frame_window_update.cc
  100. 8
      src/core/ext/transport/chttp2/transport/frame_window_update.h
  101. Some files were not shown because too many files have changed in this diff Show More

@ -122,7 +122,7 @@ class ChannelArguments {
/// Default pointer argument operations. /// Default pointer argument operations.
struct PointerVtableMembers { struct PointerVtableMembers {
static void* Copy(void* in) { return in; } static void* Copy(void* in) { return in; }
static void Destroy(grpc_exec_ctx* exec_ctx, void* in) {} static void Destroy(void* in) {}
static int Compare(void* a, void* b) { static int Compare(void* a, void* b) {
if (a < b) return -1; if (a < b) return -1;
if (a > b) return 1; if (a > b) return 1;

@ -85,7 +85,7 @@ typedef enum {
typedef struct grpc_arg_pointer_vtable { typedef struct grpc_arg_pointer_vtable {
void* (*copy)(void* p); void* (*copy)(void* p);
void (*destroy)(grpc_exec_ctx* exec_ctx, void* p); void (*destroy)(void* p);
int (*cmp)(void* p, void* q); int (*cmp)(void* p, void* q);
} grpc_arg_pointer_vtable; } grpc_arg_pointer_vtable;

@ -43,7 +43,7 @@ typedef struct grpc_slice grpc_slice;
typedef struct grpc_slice_refcount_vtable { typedef struct grpc_slice_refcount_vtable {
void (*ref)(void*); void (*ref)(void*);
void (*unref)(grpc_exec_ctx* exec_ctx, void*); void (*unref)(void*);
int (*eq)(grpc_slice a, grpc_slice b); int (*eq)(grpc_slice a, grpc_slice b);
uint32_t (*hash)(grpc_slice slice); uint32_t (*hash)(grpc_slice slice);
} grpc_slice_refcount_vtable; } grpc_slice_refcount_vtable;

@ -67,8 +67,7 @@ GPRAPI void grpc_slice_buffer_move_first_no_ref(grpc_slice_buffer* src,
size_t n, size_t n,
grpc_slice_buffer* dst); grpc_slice_buffer* dst);
/** move the first n bytes of src into dst (copying them) */ /** move the first n bytes of src into dst (copying them) */
GPRAPI void grpc_slice_buffer_move_first_into_buffer(grpc_exec_ctx* exec_ctx, GPRAPI void grpc_slice_buffer_move_first_into_buffer(grpc_slice_buffer* src,
grpc_slice_buffer* src,
size_t n, void* dst); size_t n, void* dst);
/** take the first slice in the slice buffer */ /** take the first slice in the slice buffer */
GPRAPI grpc_slice grpc_slice_buffer_take_first(grpc_slice_buffer* src); GPRAPI grpc_slice grpc_slice_buffer_take_first(grpc_slice_buffer* src);

@ -32,6 +32,12 @@
GPR_TLS_DECL(foo); GPR_TLS_DECL(foo);
Thread locals always have static scope. Thread locals always have static scope.
Declaring a thread local class variable 'foo':
GPR_TLS_CLASS_DECL(foo);
Defining the thread local class variable:
GPR_TLS_CLASS_DEF(foo);
Initializing a thread local (must be done at library initialization Initializing a thread local (must be done at library initialization
time): time):
gpr_tls_init(&foo); gpr_tls_init(&foo);

@ -33,6 +33,11 @@ struct gpr_gcc_thread_local {
#define GPR_TLS_DECL(name) \ #define GPR_TLS_DECL(name) \
static __thread struct gpr_gcc_thread_local name = {0} static __thread struct gpr_gcc_thread_local name = {0}
#define GPR_TLS_CLASS_DECL(name) \
static __thread struct gpr_gcc_thread_local name
#define GPR_TLS_CLASS_DEF(name) __thread struct gpr_gcc_thread_local name = {0}
#define gpr_tls_init(tls) \ #define gpr_tls_init(tls) \
do { \ do { \
} while (0) } while (0)

@ -26,9 +26,18 @@ struct gpr_msvc_thread_local {
intptr_t value; intptr_t value;
}; };
/** Use GPR_TLS_DECL to declare tls static variables outside a class */
#define GPR_TLS_DECL(name) \ #define GPR_TLS_DECL(name) \
static __declspec(thread) struct gpr_msvc_thread_local name = {0} static __declspec(thread) struct gpr_msvc_thread_local name = {0}
/** Use GPR_TLS_CLASS_DECL to declare tls static variable members of a class.
* GPR_TLS_CLASS_DEF needs to be called to define this member. */
#define GPR_TLS_CLASS_DECL(name) \
static __declspec(thread) struct gpr_msvc_thread_local name
#define GPR_TLS_CLASS_DEF(name) \
__declspec(thread) struct gpr_msvc_thread_local name = {0}
#define gpr_tls_init(tls) \ #define gpr_tls_init(tls) \
do { \ do { \
} while (0) } while (0)

@ -29,8 +29,17 @@ struct gpr_pthread_thread_local {
pthread_key_t key; pthread_key_t key;
}; };
/** Use GPR_TLS_DECL to declare tls static variables outside a class */
#define GPR_TLS_DECL(name) static struct gpr_pthread_thread_local name = {0} #define GPR_TLS_DECL(name) static struct gpr_pthread_thread_local name = {0}
/** Use GPR_TLS_CLASS_DECL to declare tls static variable members of a class.
* GPR_TLS_CLASS_DEF needs to be called to define this member. */
#define GPR_TLS_CLASS_DECL(name) static struct gpr_pthread_thread_local name
/** Use GPR_TLS_CLASS_DEF to declare tls static variable members of a class.
* GPR_TLS_CLASS_DEF needs to be called to define this member. */
#define GPR_TLS_CLASS_DEF(name) struct gpr_pthread_thread_local name = {0}
#define gpr_tls_init(tls) GPR_ASSERT(0 == pthread_key_create(&(tls)->key, NULL)) #define gpr_tls_init(tls) GPR_ASSERT(0 == pthread_key_create(&(tls)->key, NULL))
#define gpr_tls_destroy(tls) pthread_key_delete((tls)->key) #define gpr_tls_destroy(tls) pthread_key_delete((tls)->key)
#define gpr_tls_get(tls) ((intptr_t)pthread_getspecific((tls)->key)) #define gpr_tls_get(tls) ((intptr_t)pthread_getspecific((tls)->key))

@ -69,20 +69,19 @@ static void init_globals() {
gpr_free(env); gpr_free(env);
} }
static void backup_poller_shutdown_unref(grpc_exec_ctx* exec_ctx, static void backup_poller_shutdown_unref(backup_poller* p) {
backup_poller* p) {
if (gpr_unref(&p->shutdown_refs)) { if (gpr_unref(&p->shutdown_refs)) {
grpc_pollset_destroy(exec_ctx, p->pollset); grpc_pollset_destroy(p->pollset);
gpr_free(p->pollset); gpr_free(p->pollset);
gpr_free(p); gpr_free(p);
} }
} }
static void done_poller(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { static void done_poller(void* arg, grpc_error* error) {
backup_poller_shutdown_unref(exec_ctx, (backup_poller*)arg); backup_poller_shutdown_unref((backup_poller*)arg);
} }
static void g_poller_unref(grpc_exec_ctx* exec_ctx) { static void g_poller_unref() {
if (gpr_unref(&g_poller->refs)) { if (gpr_unref(&g_poller->refs)) {
gpr_mu_lock(&g_poller_mu); gpr_mu_lock(&g_poller_mu);
backup_poller* p = g_poller; backup_poller* p = g_poller;
@ -90,40 +89,40 @@ static void g_poller_unref(grpc_exec_ctx* exec_ctx) {
gpr_mu_unlock(&g_poller_mu); gpr_mu_unlock(&g_poller_mu);
gpr_mu_lock(p->pollset_mu); gpr_mu_lock(p->pollset_mu);
p->shutting_down = true; p->shutting_down = true;
grpc_pollset_shutdown(exec_ctx, p->pollset, grpc_pollset_shutdown(
GRPC_CLOSURE_INIT(&p->shutdown_closure, done_poller, p->pollset, GRPC_CLOSURE_INIT(&p->shutdown_closure, done_poller, p,
p, grpc_schedule_on_exec_ctx)); grpc_schedule_on_exec_ctx));
gpr_mu_unlock(p->pollset_mu); gpr_mu_unlock(p->pollset_mu);
grpc_timer_cancel(exec_ctx, &p->polling_timer); grpc_timer_cancel(&p->polling_timer);
} }
} }
static void run_poller(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { static void run_poller(void* arg, grpc_error* error) {
backup_poller* p = (backup_poller*)arg; backup_poller* p = (backup_poller*)arg;
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
if (error != GRPC_ERROR_CANCELLED) { if (error != GRPC_ERROR_CANCELLED) {
GRPC_LOG_IF_ERROR("run_poller", GRPC_ERROR_REF(error)); GRPC_LOG_IF_ERROR("run_poller", GRPC_ERROR_REF(error));
} }
backup_poller_shutdown_unref(exec_ctx, p); backup_poller_shutdown_unref(p);
return; return;
} }
gpr_mu_lock(p->pollset_mu); gpr_mu_lock(p->pollset_mu);
if (p->shutting_down) { if (p->shutting_down) {
gpr_mu_unlock(p->pollset_mu); gpr_mu_unlock(p->pollset_mu);
backup_poller_shutdown_unref(exec_ctx, p); backup_poller_shutdown_unref(p);
return; return;
} }
grpc_error* err = grpc_pollset_work(exec_ctx, p->pollset, nullptr, grpc_error* err =
grpc_exec_ctx_now(exec_ctx)); grpc_pollset_work(p->pollset, nullptr, grpc_core::ExecCtx::Get()->Now());
gpr_mu_unlock(p->pollset_mu); gpr_mu_unlock(p->pollset_mu);
GRPC_LOG_IF_ERROR("Run client channel backup poller", err); GRPC_LOG_IF_ERROR("Run client channel backup poller", err);
grpc_timer_init(exec_ctx, &p->polling_timer, grpc_timer_init(&p->polling_timer,
grpc_exec_ctx_now(exec_ctx) + g_poll_interval_ms, grpc_core::ExecCtx::Get()->Now() + g_poll_interval_ms,
&p->run_poller_closure); &p->run_poller_closure);
} }
void grpc_client_channel_start_backup_polling( void grpc_client_channel_start_backup_polling(
grpc_exec_ctx* exec_ctx, grpc_pollset_set* interested_parties) { grpc_pollset_set* interested_parties) {
gpr_once_init(&g_once, init_globals); gpr_once_init(&g_once, init_globals);
if (g_poll_interval_ms == 0) { if (g_poll_interval_ms == 0) {
return; return;
@ -139,8 +138,8 @@ void grpc_client_channel_start_backup_polling(
gpr_ref_init(&g_poller->shutdown_refs, 2); gpr_ref_init(&g_poller->shutdown_refs, 2);
GRPC_CLOSURE_INIT(&g_poller->run_poller_closure, run_poller, g_poller, GRPC_CLOSURE_INIT(&g_poller->run_poller_closure, run_poller, g_poller,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
grpc_timer_init(exec_ctx, &g_poller->polling_timer, grpc_timer_init(&g_poller->polling_timer,
grpc_exec_ctx_now(exec_ctx) + g_poll_interval_ms, grpc_core::ExecCtx::Get()->Now() + g_poll_interval_ms,
&g_poller->run_poller_closure); &g_poller->run_poller_closure);
} }
@ -152,14 +151,14 @@ void grpc_client_channel_start_backup_polling(
grpc_pollset* pollset = g_poller->pollset; grpc_pollset* pollset = g_poller->pollset;
gpr_mu_unlock(&g_poller_mu); gpr_mu_unlock(&g_poller_mu);
grpc_pollset_set_add_pollset(exec_ctx, interested_parties, pollset); grpc_pollset_set_add_pollset(interested_parties, pollset);
} }
void grpc_client_channel_stop_backup_polling( void grpc_client_channel_stop_backup_polling(
grpc_exec_ctx* exec_ctx, grpc_pollset_set* interested_parties) { grpc_pollset_set* interested_parties) {
if (g_poll_interval_ms == 0) { if (g_poll_interval_ms == 0) {
return; return;
} }
grpc_pollset_set_del_pollset(exec_ctx, interested_parties, g_poller->pollset); grpc_pollset_set_del_pollset(interested_parties, g_poller->pollset);
g_poller_unref(exec_ctx); g_poller_unref();
} }

@ -25,10 +25,10 @@
/* Start polling \a interested_parties periodically in the timer thread */ /* Start polling \a interested_parties periodically in the timer thread */
void grpc_client_channel_start_backup_polling( void grpc_client_channel_start_backup_polling(
grpc_exec_ctx* exec_ctx, grpc_pollset_set* interested_parties); grpc_pollset_set* interested_parties);
/* Stop polling \a interested_parties */ /* Stop polling \a interested_parties */
void grpc_client_channel_stop_backup_polling( void grpc_client_channel_stop_backup_polling(
grpc_exec_ctx* exec_ctx, grpc_pollset_set* interested_parties); grpc_pollset_set* interested_parties);
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_BACKUP_POLLER_H */ #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_BACKUP_POLLER_H */

@ -33,22 +33,22 @@ grpc_connectivity_state grpc_channel_check_connectivity_state(
/* forward through to the underlying client channel */ /* forward through to the underlying client channel */
grpc_channel_element* client_channel_elem = grpc_channel_element* client_channel_elem =
grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel)); grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel));
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_core::ExecCtx exec_ctx;
grpc_connectivity_state state; grpc_connectivity_state state;
GRPC_API_TRACE( GRPC_API_TRACE(
"grpc_channel_check_connectivity_state(channel=%p, try_to_connect=%d)", 2, "grpc_channel_check_connectivity_state(channel=%p, try_to_connect=%d)", 2,
(channel, try_to_connect)); (channel, try_to_connect));
if (client_channel_elem->filter == &grpc_client_channel_filter) { if (client_channel_elem->filter == &grpc_client_channel_filter) {
state = grpc_client_channel_check_connectivity_state( state = grpc_client_channel_check_connectivity_state(client_channel_elem,
&exec_ctx, client_channel_elem, try_to_connect); try_to_connect);
grpc_exec_ctx_finish(&exec_ctx);
return state; return state;
} }
gpr_log(GPR_ERROR, gpr_log(GPR_ERROR,
"grpc_channel_check_connectivity_state called on something that is " "grpc_channel_check_connectivity_state called on something that is "
"not a client channel, but '%s'", "not a client channel, but '%s'",
client_channel_elem->filter->name); client_channel_elem->filter->name);
grpc_exec_ctx_finish(&exec_ctx);
return GRPC_CHANNEL_SHUTDOWN; return GRPC_CHANNEL_SHUTDOWN;
} }
@ -73,12 +73,11 @@ typedef struct {
void* tag; void* tag;
} state_watcher; } state_watcher;
static void delete_state_watcher(grpc_exec_ctx* exec_ctx, state_watcher* w) { static void delete_state_watcher(state_watcher* w) {
grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element( grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element(
grpc_channel_get_channel_stack(w->channel)); grpc_channel_get_channel_stack(w->channel));
if (client_channel_elem->filter == &grpc_client_channel_filter) { if (client_channel_elem->filter == &grpc_client_channel_filter) {
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, w->channel, GRPC_CHANNEL_INTERNAL_UNREF(w->channel, "watch_channel_connectivity");
"watch_channel_connectivity");
} else { } else {
abort(); abort();
} }
@ -86,8 +85,7 @@ static void delete_state_watcher(grpc_exec_ctx* exec_ctx, state_watcher* w) {
gpr_free(w); gpr_free(w);
} }
static void finished_completion(grpc_exec_ctx* exec_ctx, void* pw, static void finished_completion(void* pw, grpc_cq_completion* ignored) {
grpc_cq_completion* ignored) {
bool should_delete = false; bool should_delete = false;
state_watcher* w = (state_watcher*)pw; state_watcher* w = (state_watcher*)pw;
gpr_mu_lock(&w->mu); gpr_mu_lock(&w->mu);
@ -102,19 +100,19 @@ static void finished_completion(grpc_exec_ctx* exec_ctx, void* pw,
gpr_mu_unlock(&w->mu); gpr_mu_unlock(&w->mu);
if (should_delete) { if (should_delete) {
delete_state_watcher(exec_ctx, w); delete_state_watcher(w);
} }
} }
static void partly_done(grpc_exec_ctx* exec_ctx, state_watcher* w, static void partly_done(state_watcher* w, bool due_to_completion,
bool due_to_completion, grpc_error* error) { grpc_error* error) {
if (due_to_completion) { if (due_to_completion) {
grpc_timer_cancel(exec_ctx, &w->alarm); grpc_timer_cancel(&w->alarm);
} else { } else {
grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element( grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element(
grpc_channel_get_channel_stack(w->channel)); grpc_channel_get_channel_stack(w->channel));
grpc_client_channel_watch_connectivity_state( grpc_client_channel_watch_connectivity_state(
exec_ctx, client_channel_elem, client_channel_elem,
grpc_polling_entity_create_from_pollset(grpc_cq_pollset(w->cq)), grpc_polling_entity_create_from_pollset(grpc_cq_pollset(w->cq)),
nullptr, &w->on_complete, nullptr); nullptr, &w->on_complete, nullptr);
} }
@ -149,7 +147,7 @@ static void partly_done(grpc_exec_ctx* exec_ctx, state_watcher* w,
w->error = error; w->error = error;
} }
w->phase = CALLING_BACK_AND_FINISHED; w->phase = CALLING_BACK_AND_FINISHED;
grpc_cq_end_op(exec_ctx, w->cq, w->tag, w->error, finished_completion, w, grpc_cq_end_op(w->cq, w->tag, w->error, finished_completion, w,
&w->completion_storage); &w->completion_storage);
break; break;
case CALLING_BACK_AND_FINISHED: case CALLING_BACK_AND_FINISHED:
@ -161,14 +159,12 @@ static void partly_done(grpc_exec_ctx* exec_ctx, state_watcher* w,
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
static void watch_complete(grpc_exec_ctx* exec_ctx, void* pw, static void watch_complete(void* pw, grpc_error* error) {
grpc_error* error) { partly_done((state_watcher*)pw, true, GRPC_ERROR_REF(error));
partly_done(exec_ctx, (state_watcher*)pw, true, GRPC_ERROR_REF(error));
} }
static void timeout_complete(grpc_exec_ctx* exec_ctx, void* pw, static void timeout_complete(void* pw, grpc_error* error) {
grpc_error* error) { partly_done((state_watcher*)pw, false, GRPC_ERROR_REF(error));
partly_done(exec_ctx, (state_watcher*)pw, false, GRPC_ERROR_REF(error));
} }
int grpc_channel_num_external_connectivity_watchers(grpc_channel* channel) { int grpc_channel_num_external_connectivity_watchers(grpc_channel* channel) {
@ -183,12 +179,10 @@ typedef struct watcher_timer_init_arg {
gpr_timespec deadline; gpr_timespec deadline;
} watcher_timer_init_arg; } watcher_timer_init_arg;
static void watcher_timer_init(grpc_exec_ctx* exec_ctx, void* arg, static void watcher_timer_init(void* arg, grpc_error* error_ignored) {
grpc_error* error_ignored) {
watcher_timer_init_arg* wa = (watcher_timer_init_arg*)arg; watcher_timer_init_arg* wa = (watcher_timer_init_arg*)arg;
grpc_timer_init(exec_ctx, &wa->w->alarm, grpc_timer_init(&wa->w->alarm, grpc_timespec_to_millis_round_up(wa->deadline),
grpc_timespec_to_millis_round_up(wa->deadline),
&wa->w->on_timeout); &wa->w->on_timeout);
gpr_free(wa); gpr_free(wa);
} }
@ -204,7 +198,7 @@ void grpc_channel_watch_connectivity_state(
gpr_timespec deadline, grpc_completion_queue* cq, void* tag) { gpr_timespec deadline, grpc_completion_queue* cq, void* tag) {
grpc_channel_element* client_channel_elem = grpc_channel_element* client_channel_elem =
grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel)); grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel));
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_core::ExecCtx exec_ctx;
state_watcher* w = (state_watcher*)gpr_malloc(sizeof(*w)); state_watcher* w = (state_watcher*)gpr_malloc(sizeof(*w));
GRPC_API_TRACE( GRPC_API_TRACE(
@ -241,12 +235,10 @@ void grpc_channel_watch_connectivity_state(
if (client_channel_elem->filter == &grpc_client_channel_filter) { if (client_channel_elem->filter == &grpc_client_channel_filter) {
GRPC_CHANNEL_INTERNAL_REF(channel, "watch_channel_connectivity"); GRPC_CHANNEL_INTERNAL_REF(channel, "watch_channel_connectivity");
grpc_client_channel_watch_connectivity_state( grpc_client_channel_watch_connectivity_state(
&exec_ctx, client_channel_elem, client_channel_elem,
grpc_polling_entity_create_from_pollset(grpc_cq_pollset(cq)), &w->state, grpc_polling_entity_create_from_pollset(grpc_cq_pollset(cq)), &w->state,
&w->on_complete, &w->watcher_timer_init); &w->on_complete, &w->watcher_timer_init);
} else { } else {
abort(); abort();
} }
grpc_exec_ctx_finish(&exec_ctx);
} }

File diff suppressed because it is too large Load Diff

@ -38,15 +38,15 @@ extern grpc_core::TraceFlag grpc_client_channel_trace;
extern const grpc_channel_filter grpc_client_channel_filter; extern const grpc_channel_filter grpc_client_channel_filter;
grpc_connectivity_state grpc_client_channel_check_connectivity_state( grpc_connectivity_state grpc_client_channel_check_connectivity_state(
grpc_exec_ctx* exec_ctx, grpc_channel_element* elem, int try_to_connect); grpc_channel_element* elem, int try_to_connect);
int grpc_client_channel_num_external_connectivity_watchers( int grpc_client_channel_num_external_connectivity_watchers(
grpc_channel_element* elem); grpc_channel_element* elem);
void grpc_client_channel_watch_connectivity_state( void grpc_client_channel_watch_connectivity_state(
grpc_exec_ctx* exec_ctx, grpc_channel_element* elem, grpc_channel_element* elem, grpc_polling_entity pollent,
grpc_polling_entity pollent, grpc_connectivity_state* state, grpc_connectivity_state* state, grpc_closure* on_complete,
grpc_closure* on_complete, grpc_closure* watcher_timer_init); grpc_closure* watcher_timer_init);
/* Debug helper: pull the subchannel call from a call stack element */ /* Debug helper: pull the subchannel call from a call stack element */
grpc_subchannel_call* grpc_client_channel_get_subchannel_call( grpc_subchannel_call* grpc_client_channel_get_subchannel_call(

@ -23,23 +23,19 @@ void grpc_client_channel_factory_ref(grpc_client_channel_factory* factory) {
factory->vtable->ref(factory); factory->vtable->ref(factory);
} }
void grpc_client_channel_factory_unref(grpc_exec_ctx* exec_ctx, void grpc_client_channel_factory_unref(grpc_client_channel_factory* factory) {
grpc_client_channel_factory* factory) { factory->vtable->unref(factory);
factory->vtable->unref(exec_ctx, factory);
} }
grpc_subchannel* grpc_client_channel_factory_create_subchannel( grpc_subchannel* grpc_client_channel_factory_create_subchannel(
grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory, grpc_client_channel_factory* factory, const grpc_subchannel_args* args) {
const grpc_subchannel_args* args) { return factory->vtable->create_subchannel(factory, args);
return factory->vtable->create_subchannel(exec_ctx, factory, args);
} }
grpc_channel* grpc_client_channel_factory_create_channel( grpc_channel* grpc_client_channel_factory_create_channel(
grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory, grpc_client_channel_factory* factory, const char* target,
const char* target, grpc_client_channel_type type, grpc_client_channel_type type, const grpc_channel_args* args) {
const grpc_channel_args* args) { return factory->vtable->create_client_channel(factory, target, type, args);
return factory->vtable->create_client_channel(exec_ctx, factory, target, type,
args);
} }
static void* factory_arg_copy(void* factory) { static void* factory_arg_copy(void* factory) {
@ -47,9 +43,8 @@ static void* factory_arg_copy(void* factory) {
return factory; return factory;
} }
static void factory_arg_destroy(grpc_exec_ctx* exec_ctx, void* factory) { static void factory_arg_destroy(void* factory) {
grpc_client_channel_factory_unref(exec_ctx, grpc_client_channel_factory_unref((grpc_client_channel_factory*)factory);
(grpc_client_channel_factory*)factory);
} }
static int factory_arg_cmp(void* factory1, void* factory2) { static int factory_arg_cmp(void* factory1, void* factory2) {

@ -45,31 +45,26 @@ struct grpc_client_channel_factory {
struct grpc_client_channel_factory_vtable { struct grpc_client_channel_factory_vtable {
void (*ref)(grpc_client_channel_factory* factory); void (*ref)(grpc_client_channel_factory* factory);
void (*unref)(grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory); void (*unref)(grpc_client_channel_factory* factory);
grpc_subchannel* (*create_subchannel)(grpc_exec_ctx* exec_ctx, grpc_subchannel* (*create_subchannel)(grpc_client_channel_factory* factory,
grpc_client_channel_factory* factory,
const grpc_subchannel_args* args); const grpc_subchannel_args* args);
grpc_channel* (*create_client_channel)(grpc_exec_ctx* exec_ctx, grpc_channel* (*create_client_channel)(grpc_client_channel_factory* factory,
grpc_client_channel_factory* factory,
const char* target, const char* target,
grpc_client_channel_type type, grpc_client_channel_type type,
const grpc_channel_args* args); const grpc_channel_args* args);
}; };
void grpc_client_channel_factory_ref(grpc_client_channel_factory* factory); void grpc_client_channel_factory_ref(grpc_client_channel_factory* factory);
void grpc_client_channel_factory_unref(grpc_exec_ctx* exec_ctx, void grpc_client_channel_factory_unref(grpc_client_channel_factory* factory);
grpc_client_channel_factory* factory);
/** Create a new grpc_subchannel */ /** Create a new grpc_subchannel */
grpc_subchannel* grpc_client_channel_factory_create_subchannel( grpc_subchannel* grpc_client_channel_factory_create_subchannel(
grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory, grpc_client_channel_factory* factory, const grpc_subchannel_args* args);
const grpc_subchannel_args* args);
/** Create a new grpc_channel */ /** Create a new grpc_channel */
grpc_channel* grpc_client_channel_factory_create_channel( grpc_channel* grpc_client_channel_factory_create_channel(
grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory, grpc_client_channel_factory* factory, const char* target,
const char* target, grpc_client_channel_type type, grpc_client_channel_type type, const grpc_channel_args* args);
const grpc_channel_args* args);
grpc_arg grpc_client_channel_factory_create_channel_arg( grpc_arg grpc_client_channel_factory_create_channel_arg(
grpc_client_channel_factory* factory); grpc_client_channel_factory* factory);

@ -34,14 +34,12 @@
#include "src/core/ext/filters/client_channel/subchannel_index.h" #include "src/core/ext/filters/client_channel/subchannel_index.h"
#include "src/core/lib/surface/channel_init.h" #include "src/core/lib/surface/channel_init.h"
static bool append_filter(grpc_exec_ctx* exec_ctx, static bool append_filter(grpc_channel_stack_builder* builder, void* arg) {
grpc_channel_stack_builder* builder, void* arg) {
return grpc_channel_stack_builder_append_filter( return grpc_channel_stack_builder_append_filter(
builder, (const grpc_channel_filter*)arg, nullptr, nullptr); builder, (const grpc_channel_filter*)arg, nullptr, nullptr);
} }
static bool set_default_host_if_unset(grpc_exec_ctx* exec_ctx, static bool set_default_host_if_unset(grpc_channel_stack_builder* builder,
grpc_channel_stack_builder* builder,
void* unused) { void* unused) {
const grpc_channel_args* args = const grpc_channel_args* args =
grpc_channel_stack_builder_get_channel_arguments(builder); grpc_channel_stack_builder_get_channel_arguments(builder);
@ -52,15 +50,14 @@ static bool set_default_host_if_unset(grpc_exec_ctx* exec_ctx,
} }
} }
char* default_authority = grpc_get_default_authority( char* default_authority = grpc_get_default_authority(
exec_ctx, grpc_channel_stack_builder_get_target(builder)); grpc_channel_stack_builder_get_target(builder));
if (default_authority != nullptr) { if (default_authority != nullptr) {
grpc_arg arg = grpc_channel_arg_string_create( grpc_arg arg = grpc_channel_arg_string_create(
(char*)GRPC_ARG_DEFAULT_AUTHORITY, default_authority); (char*)GRPC_ARG_DEFAULT_AUTHORITY, default_authority);
grpc_channel_args* new_args = grpc_channel_args_copy_and_add(args, &arg, 1); grpc_channel_args* new_args = grpc_channel_args_copy_and_add(args, &arg, 1);
grpc_channel_stack_builder_set_channel_arguments(exec_ctx, builder, grpc_channel_stack_builder_set_channel_arguments(builder, new_args);
new_args);
gpr_free(default_authority); gpr_free(default_authority);
grpc_channel_args_destroy(exec_ctx, new_args); grpc_channel_args_destroy(new_args);
} }
return true; return true;
} }

@ -23,18 +23,17 @@ grpc_connector* grpc_connector_ref(grpc_connector* connector) {
return connector; return connector;
} }
void grpc_connector_unref(grpc_exec_ctx* exec_ctx, grpc_connector* connector) { void grpc_connector_unref(grpc_connector* connector) {
connector->vtable->unref(exec_ctx, connector); connector->vtable->unref(connector);
} }
void grpc_connector_connect(grpc_exec_ctx* exec_ctx, grpc_connector* connector, void grpc_connector_connect(grpc_connector* connector,
const grpc_connect_in_args* in_args, const grpc_connect_in_args* in_args,
grpc_connect_out_args* out_args, grpc_connect_out_args* out_args,
grpc_closure* notify) { grpc_closure* notify) {
connector->vtable->connect(exec_ctx, connector, in_args, out_args, notify); connector->vtable->connect(connector, in_args, out_args, notify);
} }
void grpc_connector_shutdown(grpc_exec_ctx* exec_ctx, grpc_connector* connector, void grpc_connector_shutdown(grpc_connector* connector, grpc_error* why) {
grpc_error* why) { connector->vtable->shutdown(connector, why);
connector->vtable->shutdown(exec_ctx, connector, why);
} }

@ -49,25 +49,23 @@ typedef struct {
struct grpc_connector_vtable { struct grpc_connector_vtable {
void (*ref)(grpc_connector* connector); void (*ref)(grpc_connector* connector);
void (*unref)(grpc_exec_ctx* exec_ctx, grpc_connector* connector); void (*unref)(grpc_connector* connector);
/** Implementation of grpc_connector_shutdown */ /** Implementation of grpc_connector_shutdown */
void (*shutdown)(grpc_exec_ctx* exec_ctx, grpc_connector* connector, void (*shutdown)(grpc_connector* connector, grpc_error* why);
grpc_error* why);
/** Implementation of grpc_connector_connect */ /** Implementation of grpc_connector_connect */
void (*connect)(grpc_exec_ctx* exec_ctx, grpc_connector* connector, void (*connect)(grpc_connector* connector,
const grpc_connect_in_args* in_args, const grpc_connect_in_args* in_args,
grpc_connect_out_args* out_args, grpc_closure* notify); grpc_connect_out_args* out_args, grpc_closure* notify);
}; };
grpc_connector* grpc_connector_ref(grpc_connector* connector); grpc_connector* grpc_connector_ref(grpc_connector* connector);
void grpc_connector_unref(grpc_exec_ctx* exec_ctx, grpc_connector* connector); void grpc_connector_unref(grpc_connector* connector);
/** Connect using the connector: max one outstanding call at a time */ /** Connect using the connector: max one outstanding call at a time */
void grpc_connector_connect(grpc_exec_ctx* exec_ctx, grpc_connector* connector, void grpc_connector_connect(grpc_connector* connector,
const grpc_connect_in_args* in_args, const grpc_connect_in_args* in_args,
grpc_connect_out_args* out_args, grpc_connect_out_args* out_args,
grpc_closure* notify); grpc_closure* notify);
/** Cancel any pending connection */ /** Cancel any pending connection */
void grpc_connector_shutdown(grpc_exec_ctx* exec_ctx, grpc_connector* connector, void grpc_connector_shutdown(grpc_connector* connector, grpc_error* why);
grpc_error* why);
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CONNECTOR_H */ #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CONNECTOR_H */

@ -61,41 +61,38 @@ typedef struct http_connect_handshaker {
} http_connect_handshaker; } http_connect_handshaker;
// Unref and clean up handshaker. // Unref and clean up handshaker.
static void http_connect_handshaker_unref(grpc_exec_ctx* exec_ctx, static void http_connect_handshaker_unref(http_connect_handshaker* handshaker) {
http_connect_handshaker* handshaker) {
if (gpr_unref(&handshaker->refcount)) { if (gpr_unref(&handshaker->refcount)) {
gpr_mu_destroy(&handshaker->mu); gpr_mu_destroy(&handshaker->mu);
if (handshaker->endpoint_to_destroy != nullptr) { if (handshaker->endpoint_to_destroy != nullptr) {
grpc_endpoint_destroy(exec_ctx, handshaker->endpoint_to_destroy); grpc_endpoint_destroy(handshaker->endpoint_to_destroy);
} }
if (handshaker->read_buffer_to_destroy != nullptr) { if (handshaker->read_buffer_to_destroy != nullptr) {
grpc_slice_buffer_destroy_internal(exec_ctx, grpc_slice_buffer_destroy_internal(handshaker->read_buffer_to_destroy);
handshaker->read_buffer_to_destroy);
gpr_free(handshaker->read_buffer_to_destroy); gpr_free(handshaker->read_buffer_to_destroy);
} }
grpc_slice_buffer_destroy_internal(exec_ctx, &handshaker->write_buffer); grpc_slice_buffer_destroy_internal(&handshaker->write_buffer);
grpc_http_parser_destroy(&handshaker->http_parser); grpc_http_parser_destroy(&handshaker->http_parser);
grpc_http_response_destroy(&handshaker->http_response); grpc_http_response_destroy(&handshaker->http_response);
gpr_free(handshaker); gpr_free(handshaker);
} }
} }
// Set args fields to NULL, saving the endpoint and read buffer for // Set args fields to nullptr, saving the endpoint and read buffer for
// later destruction. // later destruction.
static void cleanup_args_for_failure_locked( static void cleanup_args_for_failure_locked(
grpc_exec_ctx* exec_ctx, http_connect_handshaker* handshaker) { http_connect_handshaker* handshaker) {
handshaker->endpoint_to_destroy = handshaker->args->endpoint; handshaker->endpoint_to_destroy = handshaker->args->endpoint;
handshaker->args->endpoint = nullptr; handshaker->args->endpoint = nullptr;
handshaker->read_buffer_to_destroy = handshaker->args->read_buffer; handshaker->read_buffer_to_destroy = handshaker->args->read_buffer;
handshaker->args->read_buffer = nullptr; handshaker->args->read_buffer = nullptr;
grpc_channel_args_destroy(exec_ctx, handshaker->args->args); grpc_channel_args_destroy(handshaker->args->args);
handshaker->args->args = nullptr; handshaker->args->args = nullptr;
} }
// If the handshake failed or we're shutting down, clean up and invoke the // If the handshake failed or we're shutting down, clean up and invoke the
// callback with the error. // callback with the error.
static void handshake_failed_locked(grpc_exec_ctx* exec_ctx, static void handshake_failed_locked(http_connect_handshaker* handshaker,
http_connect_handshaker* handshaker,
grpc_error* error) { grpc_error* error) {
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
// If we were shut down after an endpoint operation succeeded but // If we were shut down after an endpoint operation succeeded but
@ -108,34 +105,32 @@ static void handshake_failed_locked(grpc_exec_ctx* exec_ctx,
// before destroying them, even if we know that there are no // before destroying them, even if we know that there are no
// pending read/write callbacks. This should be fixed, at which // pending read/write callbacks. This should be fixed, at which
// point this can be removed. // point this can be removed.
grpc_endpoint_shutdown(exec_ctx, handshaker->args->endpoint, grpc_endpoint_shutdown(handshaker->args->endpoint, GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error));
// Not shutting down, so the handshake failed. Clean up before // Not shutting down, so the handshake failed. Clean up before
// invoking the callback. // invoking the callback.
cleanup_args_for_failure_locked(exec_ctx, handshaker); cleanup_args_for_failure_locked(handshaker);
// Set shutdown to true so that subsequent calls to // Set shutdown to true so that subsequent calls to
// http_connect_handshaker_shutdown() do nothing. // http_connect_handshaker_shutdown() do nothing.
handshaker->shutdown = true; handshaker->shutdown = true;
} }
// Invoke callback. // Invoke callback.
GRPC_CLOSURE_SCHED(exec_ctx, handshaker->on_handshake_done, error); GRPC_CLOSURE_SCHED(handshaker->on_handshake_done, error);
} }
// Callback invoked when finished writing HTTP CONNECT request. // Callback invoked when finished writing HTTP CONNECT request.
static void on_write_done(grpc_exec_ctx* exec_ctx, void* arg, static void on_write_done(void* arg, grpc_error* error) {
grpc_error* error) {
http_connect_handshaker* handshaker = (http_connect_handshaker*)arg; http_connect_handshaker* handshaker = (http_connect_handshaker*)arg;
gpr_mu_lock(&handshaker->mu); gpr_mu_lock(&handshaker->mu);
if (error != GRPC_ERROR_NONE || handshaker->shutdown) { if (error != GRPC_ERROR_NONE || handshaker->shutdown) {
// If the write failed or we're shutting down, clean up and invoke the // If the write failed or we're shutting down, clean up and invoke the
// callback with the error. // callback with the error.
handshake_failed_locked(exec_ctx, handshaker, GRPC_ERROR_REF(error)); handshake_failed_locked(handshaker, GRPC_ERROR_REF(error));
gpr_mu_unlock(&handshaker->mu); gpr_mu_unlock(&handshaker->mu);
http_connect_handshaker_unref(exec_ctx, handshaker); http_connect_handshaker_unref(handshaker);
} else { } else {
// Otherwise, read the response. // Otherwise, read the response.
// The read callback inherits our ref to the handshaker. // The read callback inherits our ref to the handshaker.
grpc_endpoint_read(exec_ctx, handshaker->args->endpoint, grpc_endpoint_read(handshaker->args->endpoint,
handshaker->args->read_buffer, handshaker->args->read_buffer,
&handshaker->response_read_closure); &handshaker->response_read_closure);
gpr_mu_unlock(&handshaker->mu); gpr_mu_unlock(&handshaker->mu);
@ -143,14 +138,13 @@ static void on_write_done(grpc_exec_ctx* exec_ctx, void* arg,
} }
// Callback invoked for reading HTTP CONNECT response. // Callback invoked for reading HTTP CONNECT response.
static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg, static void on_read_done(void* arg, grpc_error* error) {
grpc_error* error) {
http_connect_handshaker* handshaker = (http_connect_handshaker*)arg; http_connect_handshaker* handshaker = (http_connect_handshaker*)arg;
gpr_mu_lock(&handshaker->mu); gpr_mu_lock(&handshaker->mu);
if (error != GRPC_ERROR_NONE || handshaker->shutdown) { if (error != GRPC_ERROR_NONE || handshaker->shutdown) {
// If the read failed or we're shutting down, clean up and invoke the // If the read failed or we're shutting down, clean up and invoke the
// callback with the error. // callback with the error.
handshake_failed_locked(exec_ctx, handshaker, GRPC_ERROR_REF(error)); handshake_failed_locked(handshaker, GRPC_ERROR_REF(error));
goto done; goto done;
} }
// Add buffer to parser. // Add buffer to parser.
@ -161,7 +155,7 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg,
handshaker->args->read_buffer->slices[i], handshaker->args->read_buffer->slices[i],
&body_start_offset); &body_start_offset);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
handshake_failed_locked(exec_ctx, handshaker, error); handshake_failed_locked(handshaker, error);
goto done; goto done;
} }
if (handshaker->http_parser.state == GRPC_HTTP_BODY) { if (handshaker->http_parser.state == GRPC_HTTP_BODY) {
@ -180,7 +174,7 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg,
&handshaker->args->read_buffer->slices[i + 1], &handshaker->args->read_buffer->slices[i + 1],
handshaker->args->read_buffer->count - i - 1); handshaker->args->read_buffer->count - i - 1);
grpc_slice_buffer_swap(handshaker->args->read_buffer, &tmp_buffer); grpc_slice_buffer_swap(handshaker->args->read_buffer, &tmp_buffer);
grpc_slice_buffer_destroy_internal(exec_ctx, &tmp_buffer); grpc_slice_buffer_destroy_internal(&tmp_buffer);
break; break;
} }
} }
@ -197,9 +191,8 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg,
// complete (e.g., handling chunked transfer encoding or looking // complete (e.g., handling chunked transfer encoding or looking
// at the Content-Length: header). // at the Content-Length: header).
if (handshaker->http_parser.state != GRPC_HTTP_BODY) { if (handshaker->http_parser.state != GRPC_HTTP_BODY) {
grpc_slice_buffer_reset_and_unref_internal(exec_ctx, grpc_slice_buffer_reset_and_unref_internal(handshaker->args->read_buffer);
handshaker->args->read_buffer); grpc_endpoint_read(handshaker->args->endpoint,
grpc_endpoint_read(exec_ctx, handshaker->args->endpoint,
handshaker->args->read_buffer, handshaker->args->read_buffer,
&handshaker->response_read_closure); &handshaker->response_read_closure);
gpr_mu_unlock(&handshaker->mu); gpr_mu_unlock(&handshaker->mu);
@ -213,48 +206,44 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg,
handshaker->http_response.status); handshaker->http_response.status);
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
gpr_free(msg); gpr_free(msg);
handshake_failed_locked(exec_ctx, handshaker, error); handshake_failed_locked(handshaker, error);
goto done; goto done;
} }
// Success. Invoke handshake-done callback. // Success. Invoke handshake-done callback.
GRPC_CLOSURE_SCHED(exec_ctx, handshaker->on_handshake_done, error); GRPC_CLOSURE_SCHED(handshaker->on_handshake_done, error);
done: done:
// Set shutdown to true so that subsequent calls to // Set shutdown to true so that subsequent calls to
// http_connect_handshaker_shutdown() do nothing. // http_connect_handshaker_shutdown() do nothing.
handshaker->shutdown = true; handshaker->shutdown = true;
gpr_mu_unlock(&handshaker->mu); gpr_mu_unlock(&handshaker->mu);
http_connect_handshaker_unref(exec_ctx, handshaker); http_connect_handshaker_unref(handshaker);
} }
// //
// Public handshaker methods // Public handshaker methods
// //
static void http_connect_handshaker_destroy(grpc_exec_ctx* exec_ctx, static void http_connect_handshaker_destroy(grpc_handshaker* handshaker_in) {
grpc_handshaker* handshaker_in) {
http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in; http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in;
http_connect_handshaker_unref(exec_ctx, handshaker); http_connect_handshaker_unref(handshaker);
} }
static void http_connect_handshaker_shutdown(grpc_exec_ctx* exec_ctx, static void http_connect_handshaker_shutdown(grpc_handshaker* handshaker_in,
grpc_handshaker* handshaker_in,
grpc_error* why) { grpc_error* why) {
http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in; http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in;
gpr_mu_lock(&handshaker->mu); gpr_mu_lock(&handshaker->mu);
if (!handshaker->shutdown) { if (!handshaker->shutdown) {
handshaker->shutdown = true; handshaker->shutdown = true;
grpc_endpoint_shutdown(exec_ctx, handshaker->args->endpoint, grpc_endpoint_shutdown(handshaker->args->endpoint, GRPC_ERROR_REF(why));
GRPC_ERROR_REF(why)); cleanup_args_for_failure_locked(handshaker);
cleanup_args_for_failure_locked(exec_ctx, handshaker);
} }
gpr_mu_unlock(&handshaker->mu); gpr_mu_unlock(&handshaker->mu);
GRPC_ERROR_UNREF(why); GRPC_ERROR_UNREF(why);
} }
static void http_connect_handshaker_do_handshake( static void http_connect_handshaker_do_handshake(
grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker_in, grpc_handshaker* handshaker_in, grpc_tcp_server_acceptor* acceptor,
grpc_tcp_server_acceptor* acceptor, grpc_closure* on_handshake_done, grpc_closure* on_handshake_done, grpc_handshaker_args* args) {
grpc_handshaker_args* args) {
http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in; http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in;
// Check for HTTP CONNECT channel arg. // Check for HTTP CONNECT channel arg.
// If not found, invoke on_handshake_done without doing anything. // If not found, invoke on_handshake_done without doing anything.
@ -266,7 +255,7 @@ static void http_connect_handshaker_do_handshake(
gpr_mu_lock(&handshaker->mu); gpr_mu_lock(&handshaker->mu);
handshaker->shutdown = true; handshaker->shutdown = true;
gpr_mu_unlock(&handshaker->mu); gpr_mu_unlock(&handshaker->mu);
GRPC_CLOSURE_SCHED(exec_ctx, on_handshake_done, GRPC_ERROR_NONE); GRPC_CLOSURE_SCHED(on_handshake_done, GRPC_ERROR_NONE);
return; return;
} }
GPR_ASSERT(arg->type == GRPC_ARG_STRING); GPR_ASSERT(arg->type == GRPC_ARG_STRING);
@ -324,7 +313,7 @@ static void http_connect_handshaker_do_handshake(
gpr_free(header_strings); gpr_free(header_strings);
// Take a new ref to be held by the write callback. // Take a new ref to be held by the write callback.
gpr_ref(&handshaker->refcount); gpr_ref(&handshaker->refcount);
grpc_endpoint_write(exec_ctx, args->endpoint, &handshaker->write_buffer, grpc_endpoint_write(args->endpoint, &handshaker->write_buffer,
&handshaker->request_done_closure); &handshaker->request_done_closure);
gpr_mu_unlock(&handshaker->mu); gpr_mu_unlock(&handshaker->mu);
} }
@ -355,14 +344,13 @@ static grpc_handshaker* grpc_http_connect_handshaker_create() {
// //
static void handshaker_factory_add_handshakers( static void handshaker_factory_add_handshakers(
grpc_exec_ctx* exec_ctx, grpc_handshaker_factory* factory, grpc_handshaker_factory* factory, const grpc_channel_args* args,
const grpc_channel_args* args, grpc_handshake_manager* handshake_mgr) { grpc_handshake_manager* handshake_mgr) {
grpc_handshake_manager_add(handshake_mgr, grpc_handshake_manager_add(handshake_mgr,
grpc_http_connect_handshaker_create()); grpc_http_connect_handshaker_create());
} }
static void handshaker_factory_destroy(grpc_exec_ctx* exec_ctx, static void handshaker_factory_destroy(grpc_handshaker_factory* factory) {}
grpc_handshaker_factory* factory) {}
static const grpc_handshaker_factory_vtable handshaker_factory_vtable = { static const grpc_handshaker_factory_vtable handshaker_factory_vtable = {
handshaker_factory_add_handshakers, handshaker_factory_destroy}; handshaker_factory_add_handshakers, handshaker_factory_destroy};

@ -36,19 +36,18 @@
/** /**
* Parses the 'http_proxy' env var and returns the proxy hostname to resolve or * Parses the 'http_proxy' env var and returns the proxy hostname to resolve or
* NULL on error. Also sets 'user_cred' to user credentials if present in the * nullptr on error. Also sets 'user_cred' to user credentials if present in the
* 'http_proxy' env var, otherwise leaves it unchanged. It is caller's * 'http_proxy' env var, otherwise leaves it unchanged. It is caller's
* responsibility to gpr_free user_cred. * responsibility to gpr_free user_cred.
*/ */
static char* get_http_proxy_server(grpc_exec_ctx* exec_ctx, char** user_cred) { static char* get_http_proxy_server(char** user_cred) {
GPR_ASSERT(user_cred != nullptr); GPR_ASSERT(user_cred != nullptr);
char* proxy_name = nullptr; char* proxy_name = nullptr;
char* uri_str = gpr_getenv("http_proxy"); char* uri_str = gpr_getenv("http_proxy");
char** authority_strs = nullptr; char** authority_strs = nullptr;
size_t authority_nstrs; size_t authority_nstrs;
if (uri_str == nullptr) return nullptr; if (uri_str == nullptr) return nullptr;
grpc_uri* uri = grpc_uri* uri = grpc_uri_parse(uri_str, false /* suppress_errors */);
grpc_uri_parse(exec_ctx, uri_str, false /* suppress_errors */);
if (uri == nullptr || uri->authority == nullptr) { if (uri == nullptr || uri->authority == nullptr) {
gpr_log(GPR_ERROR, "cannot parse value of 'http_proxy' env var"); gpr_log(GPR_ERROR, "cannot parse value of 'http_proxy' env var");
goto done; goto done;
@ -82,18 +81,16 @@ done:
return proxy_name; return proxy_name;
} }
static bool proxy_mapper_map_name(grpc_exec_ctx* exec_ctx, static bool proxy_mapper_map_name(grpc_proxy_mapper* mapper,
grpc_proxy_mapper* mapper,
const char* server_uri, const char* server_uri,
const grpc_channel_args* args, const grpc_channel_args* args,
char** name_to_resolve, char** name_to_resolve,
grpc_channel_args** new_args) { grpc_channel_args** new_args) {
char* user_cred = nullptr; char* user_cred = nullptr;
*name_to_resolve = get_http_proxy_server(exec_ctx, &user_cred); *name_to_resolve = get_http_proxy_server(&user_cred);
if (*name_to_resolve == nullptr) return false; if (*name_to_resolve == nullptr) return false;
char* no_proxy_str = nullptr; char* no_proxy_str = nullptr;
grpc_uri* uri = grpc_uri* uri = grpc_uri_parse(server_uri, false /* suppress_errors */);
grpc_uri_parse(exec_ctx, server_uri, false /* suppress_errors */);
if (uri == nullptr || uri->path[0] == '\0') { if (uri == nullptr || uri->path[0] == '\0') {
gpr_log(GPR_ERROR, gpr_log(GPR_ERROR,
"'http_proxy' environment variable set, but cannot " "'http_proxy' environment variable set, but cannot "
@ -174,8 +171,7 @@ no_use_proxy:
return false; return false;
} }
static bool proxy_mapper_map_address(grpc_exec_ctx* exec_ctx, static bool proxy_mapper_map_address(grpc_proxy_mapper* mapper,
grpc_proxy_mapper* mapper,
const grpc_resolved_address* address, const grpc_resolved_address* address,
const grpc_channel_args* args, const grpc_channel_args* args,
grpc_resolved_address** new_address, grpc_resolved_address** new_address,

@ -63,15 +63,13 @@ void grpc_lb_policy_ref(grpc_lb_policy* policy REF_FUNC_EXTRA_ARGS) {
ref_mutate(policy, 1 << WEAK_REF_BITS, 0 REF_MUTATE_PASS_ARGS("STRONG_REF")); ref_mutate(policy, 1 << WEAK_REF_BITS, 0 REF_MUTATE_PASS_ARGS("STRONG_REF"));
} }
static void shutdown_locked(grpc_exec_ctx* exec_ctx, void* arg, static void shutdown_locked(void* arg, grpc_error* error) {
grpc_error* error) {
grpc_lb_policy* policy = (grpc_lb_policy*)arg; grpc_lb_policy* policy = (grpc_lb_policy*)arg;
policy->vtable->shutdown_locked(exec_ctx, policy); policy->vtable->shutdown_locked(policy);
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, policy, "strong-unref"); GRPC_LB_POLICY_WEAK_UNREF(policy, "strong-unref");
} }
void grpc_lb_policy_unref(grpc_exec_ctx* exec_ctx, void grpc_lb_policy_unref(grpc_lb_policy* policy REF_FUNC_EXTRA_ARGS) {
grpc_lb_policy* policy REF_FUNC_EXTRA_ARGS) {
gpr_atm old_val = gpr_atm old_val =
ref_mutate(policy, (gpr_atm)1 - (gpr_atm)(1 << WEAK_REF_BITS), ref_mutate(policy, (gpr_atm)1 - (gpr_atm)(1 << WEAK_REF_BITS),
1 REF_MUTATE_PASS_ARGS("STRONG_UNREF")); 1 REF_MUTATE_PASS_ARGS("STRONG_UNREF"));
@ -79,13 +77,11 @@ void grpc_lb_policy_unref(grpc_exec_ctx* exec_ctx,
gpr_atm check = 1 << WEAK_REF_BITS; gpr_atm check = 1 << WEAK_REF_BITS;
if ((old_val & mask) == check) { if ((old_val & mask) == check) {
GRPC_CLOSURE_SCHED( GRPC_CLOSURE_SCHED(
exec_ctx,
GRPC_CLOSURE_CREATE(shutdown_locked, policy, GRPC_CLOSURE_CREATE(shutdown_locked, policy,
grpc_combiner_scheduler(policy->combiner)), grpc_combiner_scheduler(policy->combiner)),
GRPC_ERROR_NONE); GRPC_ERROR_NONE);
} else { } else {
grpc_lb_policy_weak_unref(exec_ctx, grpc_lb_policy_weak_unref(policy REF_FUNC_PASS_ARGS("strong-unref"));
policy REF_FUNC_PASS_ARGS("strong-unref"));
} }
} }
@ -93,88 +89,75 @@ void grpc_lb_policy_weak_ref(grpc_lb_policy* policy REF_FUNC_EXTRA_ARGS) {
ref_mutate(policy, 1, 0 REF_MUTATE_PASS_ARGS("WEAK_REF")); ref_mutate(policy, 1, 0 REF_MUTATE_PASS_ARGS("WEAK_REF"));
} }
void grpc_lb_policy_weak_unref(grpc_exec_ctx* exec_ctx, void grpc_lb_policy_weak_unref(grpc_lb_policy* policy REF_FUNC_EXTRA_ARGS) {
grpc_lb_policy* policy REF_FUNC_EXTRA_ARGS) {
gpr_atm old_val = gpr_atm old_val =
ref_mutate(policy, -(gpr_atm)1, 1 REF_MUTATE_PASS_ARGS("WEAK_UNREF")); ref_mutate(policy, -(gpr_atm)1, 1 REF_MUTATE_PASS_ARGS("WEAK_UNREF"));
if (old_val == 1) { if (old_val == 1) {
grpc_pollset_set_destroy(exec_ctx, policy->interested_parties); grpc_pollset_set_destroy(policy->interested_parties);
grpc_combiner* combiner = policy->combiner; grpc_combiner* combiner = policy->combiner;
policy->vtable->destroy(exec_ctx, policy); policy->vtable->destroy(policy);
GRPC_COMBINER_UNREF(exec_ctx, combiner, "lb_policy"); GRPC_COMBINER_UNREF(combiner, "lb_policy");
} }
} }
int grpc_lb_policy_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, int grpc_lb_policy_pick_locked(grpc_lb_policy* policy,
const grpc_lb_policy_pick_args* pick_args, const grpc_lb_policy_pick_args* pick_args,
grpc_connected_subchannel** target, grpc_connected_subchannel** target,
grpc_call_context_element* context, grpc_call_context_element* context,
void** user_data, grpc_closure* on_complete) { void** user_data, grpc_closure* on_complete) {
return policy->vtable->pick_locked(exec_ctx, policy, pick_args, target, return policy->vtable->pick_locked(policy, pick_args, target, context,
context, user_data, on_complete); user_data, on_complete);
} }
void grpc_lb_policy_cancel_pick_locked(grpc_exec_ctx* exec_ctx, void grpc_lb_policy_cancel_pick_locked(grpc_lb_policy* policy,
grpc_lb_policy* policy,
grpc_connected_subchannel** target, grpc_connected_subchannel** target,
grpc_error* error) { grpc_error* error) {
policy->vtable->cancel_pick_locked(exec_ctx, policy, target, error); policy->vtable->cancel_pick_locked(policy, target, error);
} }
void grpc_lb_policy_cancel_picks_locked(grpc_exec_ctx* exec_ctx, void grpc_lb_policy_cancel_picks_locked(grpc_lb_policy* policy,
grpc_lb_policy* policy,
uint32_t initial_metadata_flags_mask, uint32_t initial_metadata_flags_mask,
uint32_t initial_metadata_flags_eq, uint32_t initial_metadata_flags_eq,
grpc_error* error) { grpc_error* error) {
policy->vtable->cancel_picks_locked(exec_ctx, policy, policy->vtable->cancel_picks_locked(policy, initial_metadata_flags_mask,
initial_metadata_flags_mask,
initial_metadata_flags_eq, error); initial_metadata_flags_eq, error);
} }
void grpc_lb_policy_exit_idle_locked(grpc_exec_ctx* exec_ctx, void grpc_lb_policy_exit_idle_locked(grpc_lb_policy* policy) {
grpc_lb_policy* policy) { policy->vtable->exit_idle_locked(policy);
policy->vtable->exit_idle_locked(exec_ctx, policy);
} }
void grpc_lb_policy_ping_one_locked(grpc_exec_ctx* exec_ctx, void grpc_lb_policy_ping_one_locked(grpc_lb_policy* policy,
grpc_lb_policy* policy,
grpc_closure* closure) { grpc_closure* closure) {
policy->vtable->ping_one_locked(exec_ctx, policy, closure); policy->vtable->ping_one_locked(policy, closure);
} }
void grpc_lb_policy_notify_on_state_change_locked( void grpc_lb_policy_notify_on_state_change_locked(
grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, grpc_lb_policy* policy, grpc_connectivity_state* state,
grpc_connectivity_state* state, grpc_closure* closure) { grpc_closure* closure) {
policy->vtable->notify_on_state_change_locked(exec_ctx, policy, state, policy->vtable->notify_on_state_change_locked(policy, state, closure);
closure);
} }
grpc_connectivity_state grpc_lb_policy_check_connectivity_locked( grpc_connectivity_state grpc_lb_policy_check_connectivity_locked(
grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, grpc_lb_policy* policy, grpc_error** connectivity_error) {
grpc_error** connectivity_error) { return policy->vtable->check_connectivity_locked(policy, connectivity_error);
return policy->vtable->check_connectivity_locked(exec_ctx, policy,
connectivity_error);
} }
void grpc_lb_policy_update_locked(grpc_exec_ctx* exec_ctx, void grpc_lb_policy_update_locked(grpc_lb_policy* policy,
grpc_lb_policy* policy,
const grpc_lb_policy_args* lb_policy_args) { const grpc_lb_policy_args* lb_policy_args) {
policy->vtable->update_locked(exec_ctx, policy, lb_policy_args); policy->vtable->update_locked(policy, lb_policy_args);
} }
void grpc_lb_policy_set_reresolve_closure_locked( void grpc_lb_policy_set_reresolve_closure_locked(
grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, grpc_lb_policy* policy, grpc_closure* request_reresolution) {
grpc_closure* request_reresolution) { policy->vtable->set_reresolve_closure_locked(policy, request_reresolution);
policy->vtable->set_reresolve_closure_locked(exec_ctx, policy,
request_reresolution);
} }
void grpc_lb_policy_try_reresolve(grpc_exec_ctx* exec_ctx, void grpc_lb_policy_try_reresolve(grpc_lb_policy* policy,
grpc_lb_policy* policy,
grpc_core::TraceFlag* grpc_lb_trace, grpc_core::TraceFlag* grpc_lb_trace,
grpc_error* error) { grpc_error* error) {
if (policy->request_reresolution != nullptr) { if (policy->request_reresolution != nullptr) {
GRPC_CLOSURE_SCHED(exec_ctx, policy->request_reresolution, error); GRPC_CLOSURE_SCHED(policy->request_reresolution, error);
policy->request_reresolution = nullptr; policy->request_reresolution = nullptr;
if (grpc_lb_trace->enabled()) { if (grpc_lb_trace->enabled()) {
gpr_log(GPR_DEBUG, gpr_log(GPR_DEBUG,

@ -55,53 +55,49 @@ typedef struct grpc_lb_policy_pick_args {
} grpc_lb_policy_pick_args; } grpc_lb_policy_pick_args;
struct grpc_lb_policy_vtable { struct grpc_lb_policy_vtable {
void (*destroy)(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy); void (*destroy)(grpc_lb_policy* policy);
void (*shutdown_locked)(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy); void (*shutdown_locked)(grpc_lb_policy* policy);
/** \see grpc_lb_policy_pick */ /** \see grpc_lb_policy_pick */
int (*pick_locked)(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, int (*pick_locked)(grpc_lb_policy* policy,
const grpc_lb_policy_pick_args* pick_args, const grpc_lb_policy_pick_args* pick_args,
grpc_connected_subchannel** target, grpc_connected_subchannel** target,
grpc_call_context_element* context, void** user_data, grpc_call_context_element* context, void** user_data,
grpc_closure* on_complete); grpc_closure* on_complete);
/** \see grpc_lb_policy_cancel_pick */ /** \see grpc_lb_policy_cancel_pick */
void (*cancel_pick_locked)(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, void (*cancel_pick_locked)(grpc_lb_policy* policy,
grpc_connected_subchannel** target, grpc_connected_subchannel** target,
grpc_error* error); grpc_error* error);
/** \see grpc_lb_policy_cancel_picks */ /** \see grpc_lb_policy_cancel_picks */
void (*cancel_picks_locked)(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, void (*cancel_picks_locked)(grpc_lb_policy* policy,
uint32_t initial_metadata_flags_mask, uint32_t initial_metadata_flags_mask,
uint32_t initial_metadata_flags_eq, uint32_t initial_metadata_flags_eq,
grpc_error* error); grpc_error* error);
/** \see grpc_lb_policy_ping_one */ /** \see grpc_lb_policy_ping_one */
void (*ping_one_locked)(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, void (*ping_one_locked)(grpc_lb_policy* policy, grpc_closure* closure);
grpc_closure* closure);
/** Try to enter a READY connectivity state */ /** Try to enter a READY connectivity state */
void (*exit_idle_locked)(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy); void (*exit_idle_locked)(grpc_lb_policy* policy);
/** check the current connectivity of the lb_policy */ /** check the current connectivity of the lb_policy */
grpc_connectivity_state (*check_connectivity_locked)( grpc_connectivity_state (*check_connectivity_locked)(
grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, grpc_lb_policy* policy, grpc_error** connectivity_error);
grpc_error** connectivity_error);
/** call notify when the connectivity state of a channel changes from *state. /** call notify when the connectivity state of a channel changes from *state.
Updates *state with the new state of the policy. Calling with a NULL \a Updates *state with the new state of the policy. Calling with a NULL \a
state cancels the subscription. */ state cancels the subscription. */
void (*notify_on_state_change_locked)(grpc_exec_ctx* exec_ctx, void (*notify_on_state_change_locked)(grpc_lb_policy* policy,
grpc_lb_policy* policy,
grpc_connectivity_state* state, grpc_connectivity_state* state,
grpc_closure* closure); grpc_closure* closure);
void (*update_locked)(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, void (*update_locked)(grpc_lb_policy* policy,
const grpc_lb_policy_args* args); const grpc_lb_policy_args* args);
/** \see grpc_lb_policy_set_reresolve_closure */ /** \see grpc_lb_policy_set_reresolve_closure */
void (*set_reresolve_closure_locked)(grpc_exec_ctx* exec_ctx, void (*set_reresolve_closure_locked)(grpc_lb_policy* policy,
grpc_lb_policy* policy,
grpc_closure* request_reresolution); grpc_closure* request_reresolution);
}; };
@ -110,33 +106,33 @@ struct grpc_lb_policy_vtable {
/* Strong references: the policy will shutdown when they reach zero */ /* Strong references: the policy will shutdown when they reach zero */
#define GRPC_LB_POLICY_REF(p, r) \ #define GRPC_LB_POLICY_REF(p, r) \
grpc_lb_policy_ref((p), __FILE__, __LINE__, (r)) grpc_lb_policy_ref((p), __FILE__, __LINE__, (r))
#define GRPC_LB_POLICY_UNREF(exec_ctx, p, r) \ #define GRPC_LB_POLICY_UNREF(p, r) \
grpc_lb_policy_unref((exec_ctx), (p), __FILE__, __LINE__, (r)) grpc_lb_policy_unref((p), __FILE__, __LINE__, (r))
/* Weak references: they don't prevent the shutdown of the LB policy. When no /* Weak references: they don't prevent the shutdown of the LB policy. When no
* strong references are left but there are still weak ones, shutdown is called. * strong references are left but there are still weak ones, shutdown is called.
* Once the weak reference also reaches zero, the LB policy is destroyed. */ * Once the weak reference also reaches zero, the LB policy is destroyed. */
#define GRPC_LB_POLICY_WEAK_REF(p, r) \ #define GRPC_LB_POLICY_WEAK_REF(p, r) \
grpc_lb_policy_weak_ref((p), __FILE__, __LINE__, (r)) grpc_lb_policy_weak_ref((p), __FILE__, __LINE__, (r))
#define GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, p, r) \ #define GRPC_LB_POLICY_WEAK_UNREF(p, r) \
grpc_lb_policy_weak_unref((exec_ctx), (p), __FILE__, __LINE__, (r)) grpc_lb_policy_weak_unref((p), __FILE__, __LINE__, (r))
void grpc_lb_policy_ref(grpc_lb_policy* policy, const char* file, int line, void grpc_lb_policy_ref(grpc_lb_policy* policy, const char* file, int line,
const char* reason); const char* reason);
void grpc_lb_policy_unref(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, void grpc_lb_policy_unref(grpc_lb_policy* policy, const char* file, int line,
const char* file, int line, const char* reason); const char* reason);
void grpc_lb_policy_weak_ref(grpc_lb_policy* policy, const char* file, int line, void grpc_lb_policy_weak_ref(grpc_lb_policy* policy, const char* file, int line,
const char* reason); const char* reason);
void grpc_lb_policy_weak_unref(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, void grpc_lb_policy_weak_unref(grpc_lb_policy* policy, const char* file,
const char* file, int line, const char* reason); int line, const char* reason);
#else #else
#define GRPC_LB_POLICY_REF(p, r) grpc_lb_policy_ref((p)) #define GRPC_LB_POLICY_REF(p, r) grpc_lb_policy_ref((p))
#define GRPC_LB_POLICY_UNREF(cl, p, r) grpc_lb_policy_unref((cl), (p)) #define GRPC_LB_POLICY_UNREF(p, r) grpc_lb_policy_unref((p))
#define GRPC_LB_POLICY_WEAK_REF(p, r) grpc_lb_policy_weak_ref((p)) #define GRPC_LB_POLICY_WEAK_REF(p, r) grpc_lb_policy_weak_ref((p))
#define GRPC_LB_POLICY_WEAK_UNREF(cl, p, r) grpc_lb_policy_weak_unref((cl), (p)) #define GRPC_LB_POLICY_WEAK_UNREF(p, r) grpc_lb_policy_weak_unref((p))
void grpc_lb_policy_ref(grpc_lb_policy* policy); void grpc_lb_policy_ref(grpc_lb_policy* policy);
void grpc_lb_policy_unref(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy); void grpc_lb_policy_unref(grpc_lb_policy* policy);
void grpc_lb_policy_weak_ref(grpc_lb_policy* policy); void grpc_lb_policy_weak_ref(grpc_lb_policy* policy);
void grpc_lb_policy_weak_unref(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy); void grpc_lb_policy_weak_unref(grpc_lb_policy* policy);
#endif #endif
/** called by concrete implementations to initialize the base struct */ /** called by concrete implementations to initialize the base struct */
@ -161,7 +157,7 @@ void grpc_lb_policy_init(grpc_lb_policy* policy,
Any IO should be done under the \a interested_parties \a grpc_pollset_set Any IO should be done under the \a interested_parties \a grpc_pollset_set
in the \a grpc_lb_policy struct. */ in the \a grpc_lb_policy struct. */
int grpc_lb_policy_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, int grpc_lb_policy_pick_locked(grpc_lb_policy* policy,
const grpc_lb_policy_pick_args* pick_args, const grpc_lb_policy_pick_args* pick_args,
grpc_connected_subchannel** target, grpc_connected_subchannel** target,
grpc_call_context_element* context, grpc_call_context_element* context,
@ -169,55 +165,47 @@ int grpc_lb_policy_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy,
/** Perform a connected subchannel ping (see \a grpc_connected_subchannel_ping) /** Perform a connected subchannel ping (see \a grpc_connected_subchannel_ping)
against one of the connected subchannels managed by \a policy. */ against one of the connected subchannels managed by \a policy. */
void grpc_lb_policy_ping_one_locked(grpc_exec_ctx* exec_ctx, void grpc_lb_policy_ping_one_locked(grpc_lb_policy* policy,
grpc_lb_policy* policy,
grpc_closure* closure); grpc_closure* closure);
/** Cancel picks for \a target. /** Cancel picks for \a target.
The \a on_complete callback of the pending picks will be invoked with \a The \a on_complete callback of the pending picks will be invoked with \a
*target set to NULL. */ *target set to NULL. */
void grpc_lb_policy_cancel_pick_locked(grpc_exec_ctx* exec_ctx, void grpc_lb_policy_cancel_pick_locked(grpc_lb_policy* policy,
grpc_lb_policy* policy,
grpc_connected_subchannel** target, grpc_connected_subchannel** target,
grpc_error* error); grpc_error* error);
/** Cancel all pending picks for which their \a initial_metadata_flags (as given /** Cancel all pending picks for which their \a initial_metadata_flags (as given
in the call to \a grpc_lb_policy_pick) matches \a initial_metadata_flags_eq in the call to \a grpc_lb_policy_pick) matches \a initial_metadata_flags_eq
when AND'd with \a initial_metadata_flags_mask */ when AND'd with \a initial_metadata_flags_mask */
void grpc_lb_policy_cancel_picks_locked(grpc_exec_ctx* exec_ctx, void grpc_lb_policy_cancel_picks_locked(grpc_lb_policy* policy,
grpc_lb_policy* policy,
uint32_t initial_metadata_flags_mask, uint32_t initial_metadata_flags_mask,
uint32_t initial_metadata_flags_eq, uint32_t initial_metadata_flags_eq,
grpc_error* error); grpc_error* error);
/** Try to enter a READY connectivity state */ /** Try to enter a READY connectivity state */
void grpc_lb_policy_exit_idle_locked(grpc_exec_ctx* exec_ctx, void grpc_lb_policy_exit_idle_locked(grpc_lb_policy* policy);
grpc_lb_policy* policy);
/* Call notify when the connectivity state of a channel changes from \a *state. /* Call notify when the connectivity state of a channel changes from \a *state.
* Updates \a *state with the new state of the policy */ * Updates \a *state with the new state of the policy */
void grpc_lb_policy_notify_on_state_change_locked( void grpc_lb_policy_notify_on_state_change_locked(
grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, grpc_lb_policy* policy, grpc_connectivity_state* state,
grpc_connectivity_state* state, grpc_closure* closure); grpc_closure* closure);
grpc_connectivity_state grpc_lb_policy_check_connectivity_locked( grpc_connectivity_state grpc_lb_policy_check_connectivity_locked(
grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, grpc_lb_policy* policy, grpc_error** connectivity_error);
grpc_error** connectivity_error);
/** Update \a policy with \a lb_policy_args. */ /** Update \a policy with \a lb_policy_args. */
void grpc_lb_policy_update_locked(grpc_exec_ctx* exec_ctx, void grpc_lb_policy_update_locked(grpc_lb_policy* policy,
grpc_lb_policy* policy,
const grpc_lb_policy_args* lb_policy_args); const grpc_lb_policy_args* lb_policy_args);
/** Set the re-resolution closure to \a request_reresolution. */ /** Set the re-resolution closure to \a request_reresolution. */
void grpc_lb_policy_set_reresolve_closure_locked( void grpc_lb_policy_set_reresolve_closure_locked(
grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, grpc_lb_policy* policy, grpc_closure* request_reresolution);
grpc_closure* request_reresolution);
/** Try to request a re-resolution. It's NOT a public API; it's only for use by /** Try to request a re-resolution. It's NOT a public API; it's only for use by
the LB policy implementations. */ the LB policy implementations. */
void grpc_lb_policy_try_reresolve(grpc_exec_ctx* exec_ctx, void grpc_lb_policy_try_reresolve(grpc_lb_policy* policy,
grpc_lb_policy* policy,
grpc_core::TraceFlag* grpc_lb_trace, grpc_core::TraceFlag* grpc_lb_trace,
grpc_error* error); grpc_error* error);

@ -25,14 +25,12 @@
#include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/error.h"
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_channel_elem(grpc_channel_element* elem,
grpc_channel_element* elem,
grpc_channel_element_args* args) { grpc_channel_element_args* args) {
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, static void destroy_channel_elem(grpc_channel_element* elem) {}
grpc_channel_element* elem) {}
typedef struct { typedef struct {
// Stats object to update. // Stats object to update.
@ -47,28 +45,24 @@ typedef struct {
bool recv_initial_metadata_succeeded; bool recv_initial_metadata_succeeded;
} call_data; } call_data;
static void on_complete_for_send(grpc_exec_ctx* exec_ctx, void* arg, static void on_complete_for_send(void* arg, grpc_error* error) {
grpc_error* error) {
call_data* calld = (call_data*)arg; call_data* calld = (call_data*)arg;
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
calld->send_initial_metadata_succeeded = true; calld->send_initial_metadata_succeeded = true;
} }
GRPC_CLOSURE_RUN(exec_ctx, calld->original_on_complete_for_send, GRPC_CLOSURE_RUN(calld->original_on_complete_for_send, GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error));
} }
static void recv_initial_metadata_ready(grpc_exec_ctx* exec_ctx, void* arg, static void recv_initial_metadata_ready(void* arg, grpc_error* error) {
grpc_error* error) {
call_data* calld = (call_data*)arg; call_data* calld = (call_data*)arg;
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
calld->recv_initial_metadata_succeeded = true; calld->recv_initial_metadata_succeeded = true;
} }
GRPC_CLOSURE_RUN(exec_ctx, calld->original_recv_initial_metadata_ready, GRPC_CLOSURE_RUN(calld->original_recv_initial_metadata_ready,
GRPC_ERROR_REF(error)); GRPC_ERROR_REF(error));
} }
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_call_elem(grpc_call_element* elem,
grpc_call_element* elem,
const grpc_call_element_args* args) { const grpc_call_element_args* args) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
// Get stats object from context and take a ref. // Get stats object from context and take a ref.
@ -81,7 +75,7 @@ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, static void destroy_call_elem(grpc_call_element* elem,
const grpc_call_final_info* final_info, const grpc_call_final_info* final_info,
grpc_closure* ignored) { grpc_closure* ignored) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
@ -96,8 +90,7 @@ static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
} }
static void start_transport_stream_op_batch( static void start_transport_stream_op_batch(
grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_element* elem, grpc_transport_stream_op_batch* batch) {
grpc_transport_stream_op_batch* batch) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
GPR_TIMER_BEGIN("clr_start_transport_stream_op_batch", 0); GPR_TIMER_BEGIN("clr_start_transport_stream_op_batch", 0);
// Intercept send_initial_metadata. // Intercept send_initial_metadata.
@ -118,7 +111,7 @@ static void start_transport_stream_op_batch(
&calld->recv_initial_metadata_ready; &calld->recv_initial_metadata_ready;
} }
// Chain to next filter. // Chain to next filter.
grpc_call_next_op(exec_ctx, elem, batch); grpc_call_next_op(elem, batch);
GPR_TIMER_END("clr_start_transport_stream_op_batch", 0); GPR_TIMER_END("clr_start_transport_stream_op_batch", 0);
} }

@ -26,17 +26,17 @@
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
grpc_channel* grpc_lb_policy_grpclb_create_lb_channel( grpc_channel* grpc_lb_policy_grpclb_create_lb_channel(
grpc_exec_ctx* exec_ctx, const char* lb_service_target_addresses, const char* lb_service_target_addresses,
grpc_client_channel_factory* client_channel_factory, grpc_client_channel_factory* client_channel_factory,
grpc_channel_args* args) { grpc_channel_args* args) {
grpc_channel* lb_channel = grpc_client_channel_factory_create_channel( grpc_channel* lb_channel = grpc_client_channel_factory_create_channel(
exec_ctx, client_channel_factory, lb_service_target_addresses, client_channel_factory, lb_service_target_addresses,
GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, args); GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, args);
return lb_channel; return lb_channel;
} }
grpc_channel_args* grpc_lb_policy_grpclb_build_lb_channel_args( grpc_channel_args* grpc_lb_policy_grpclb_build_lb_channel_args(
grpc_exec_ctx* exec_ctx, grpc_slice_hash_table* targets_info, grpc_slice_hash_table* targets_info,
grpc_fake_resolver_response_generator* response_generator, grpc_fake_resolver_response_generator* response_generator,
const grpc_channel_args* args) { const grpc_channel_args* args) {
const grpc_arg to_add[] = { const grpc_arg to_add[] = {

@ -31,12 +31,12 @@
* \a client_channel_factory will be used for the creation of the LB channel, * \a client_channel_factory will be used for the creation of the LB channel,
* alongside the channel args passed in \a args. */ * alongside the channel args passed in \a args. */
grpc_channel* grpc_lb_policy_grpclb_create_lb_channel( grpc_channel* grpc_lb_policy_grpclb_create_lb_channel(
grpc_exec_ctx* exec_ctx, const char* lb_service_target_addresses, const char* lb_service_target_addresses,
grpc_client_channel_factory* client_channel_factory, grpc_client_channel_factory* client_channel_factory,
grpc_channel_args* args); grpc_channel_args* args);
grpc_channel_args* grpc_lb_policy_grpclb_build_lb_channel_args( grpc_channel_args* grpc_lb_policy_grpclb_build_lb_channel_args(
grpc_exec_ctx* exec_ctx, grpc_slice_hash_table* targets_info, grpc_slice_hash_table* targets_info,
grpc_fake_resolver_response_generator* response_generator, grpc_fake_resolver_response_generator* response_generator,
const grpc_channel_args* args); const grpc_channel_args* args);

@ -29,7 +29,7 @@
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
grpc_channel* grpc_lb_policy_grpclb_create_lb_channel( grpc_channel* grpc_lb_policy_grpclb_create_lb_channel(
grpc_exec_ctx* exec_ctx, const char* lb_service_target_addresses, const char* lb_service_target_addresses,
grpc_client_channel_factory* client_channel_factory, grpc_client_channel_factory* client_channel_factory,
grpc_channel_args* args) { grpc_channel_args* args) {
grpc_channel_args* new_args = args; grpc_channel_args* new_args = args;
@ -50,19 +50,19 @@ grpc_channel* grpc_lb_policy_grpclb_create_lb_channel(
new_args = grpc_channel_args_copy_and_add_and_remove( new_args = grpc_channel_args_copy_and_add_and_remove(
args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), args_to_add, args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), args_to_add,
GPR_ARRAY_SIZE(args_to_add)); GPR_ARRAY_SIZE(args_to_add));
grpc_channel_credentials_unref(exec_ctx, creds_sans_call_creds); grpc_channel_credentials_unref(creds_sans_call_creds);
} }
grpc_channel* lb_channel = grpc_client_channel_factory_create_channel( grpc_channel* lb_channel = grpc_client_channel_factory_create_channel(
exec_ctx, client_channel_factory, lb_service_target_addresses, client_channel_factory, lb_service_target_addresses,
GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, new_args); GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, new_args);
if (channel_credentials != nullptr) { if (channel_credentials != nullptr) {
grpc_channel_args_destroy(exec_ctx, new_args); grpc_channel_args_destroy(new_args);
} }
return lb_channel; return lb_channel;
} }
grpc_channel_args* grpc_lb_policy_grpclb_build_lb_channel_args( grpc_channel_args* grpc_lb_policy_grpclb_build_lb_channel_args(
grpc_exec_ctx* exec_ctx, grpc_slice_hash_table* targets_info, grpc_slice_hash_table* targets_info,
grpc_fake_resolver_response_generator* response_generator, grpc_fake_resolver_response_generator* response_generator,
const grpc_channel_args* args) { const grpc_channel_args* args) {
const grpc_arg to_add[] = { const grpc_arg to_add[] = {

@ -57,12 +57,12 @@ typedef struct {
grpc_connectivity_state_tracker state_tracker; grpc_connectivity_state_tracker state_tracker;
} pick_first_lb_policy; } pick_first_lb_policy;
static void pf_destroy(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol) { static void pf_destroy(grpc_lb_policy* pol) {
pick_first_lb_policy* p = (pick_first_lb_policy*)pol; pick_first_lb_policy* p = (pick_first_lb_policy*)pol;
GPR_ASSERT(p->subchannel_list == nullptr); GPR_ASSERT(p->subchannel_list == nullptr);
GPR_ASSERT(p->latest_pending_subchannel_list == nullptr); GPR_ASSERT(p->latest_pending_subchannel_list == nullptr);
GPR_ASSERT(p->pending_picks == nullptr); GPR_ASSERT(p->pending_picks == nullptr);
grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker); grpc_connectivity_state_destroy(&p->state_tracker);
gpr_free(p); gpr_free(p);
grpc_subchannel_index_unref(); grpc_subchannel_index_unref();
if (grpc_lb_pick_first_trace.enabled()) { if (grpc_lb_pick_first_trace.enabled()) {
@ -70,7 +70,7 @@ static void pf_destroy(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol) {
} }
} }
static void pf_shutdown_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol) { static void pf_shutdown_locked(grpc_lb_policy* pol) {
pick_first_lb_policy* p = (pick_first_lb_policy*)pol; pick_first_lb_policy* p = (pick_first_lb_policy*)pol;
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown"); grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown");
if (grpc_lb_pick_first_trace.enabled()) { if (grpc_lb_pick_first_trace.enabled()) {
@ -81,28 +81,27 @@ static void pf_shutdown_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol) {
while ((pp = p->pending_picks) != nullptr) { while ((pp = p->pending_picks) != nullptr) {
p->pending_picks = pp->next; p->pending_picks = pp->next;
*pp->target = nullptr; *pp->target = nullptr;
GRPC_CLOSURE_SCHED(exec_ctx, pp->on_complete, GRPC_ERROR_REF(error)); GRPC_CLOSURE_SCHED(pp->on_complete, GRPC_ERROR_REF(error));
gpr_free(pp); gpr_free(pp);
} }
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error), GRPC_ERROR_REF(error), "shutdown");
"shutdown");
if (p->subchannel_list != nullptr) { if (p->subchannel_list != nullptr) {
grpc_lb_subchannel_list_shutdown_and_unref(exec_ctx, p->subchannel_list, grpc_lb_subchannel_list_shutdown_and_unref(p->subchannel_list,
"pf_shutdown"); "pf_shutdown");
p->subchannel_list = nullptr; p->subchannel_list = nullptr;
} }
if (p->latest_pending_subchannel_list != nullptr) { if (p->latest_pending_subchannel_list != nullptr) {
grpc_lb_subchannel_list_shutdown_and_unref( grpc_lb_subchannel_list_shutdown_and_unref(
exec_ctx, p->latest_pending_subchannel_list, "pf_shutdown"); p->latest_pending_subchannel_list, "pf_shutdown");
p->latest_pending_subchannel_list = nullptr; p->latest_pending_subchannel_list = nullptr;
} }
grpc_lb_policy_try_reresolve(exec_ctx, &p->base, &grpc_lb_pick_first_trace, grpc_lb_policy_try_reresolve(&p->base, &grpc_lb_pick_first_trace,
GRPC_ERROR_CANCELLED); GRPC_ERROR_CANCELLED);
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
static void pf_cancel_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol, static void pf_cancel_pick_locked(grpc_lb_policy* pol,
grpc_connected_subchannel** target, grpc_connected_subchannel** target,
grpc_error* error) { grpc_error* error) {
pick_first_lb_policy* p = (pick_first_lb_policy*)pol; pick_first_lb_policy* p = (pick_first_lb_policy*)pol;
@ -112,7 +111,7 @@ static void pf_cancel_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
pending_pick* next = pp->next; pending_pick* next = pp->next;
if (pp->target == target) { if (pp->target == target) {
*target = nullptr; *target = nullptr;
GRPC_CLOSURE_SCHED(exec_ctx, pp->on_complete, GRPC_CLOSURE_SCHED(pp->on_complete,
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Pick Cancelled", &error, 1)); "Pick Cancelled", &error, 1));
gpr_free(pp); gpr_free(pp);
@ -125,7 +124,7 @@ static void pf_cancel_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
static void pf_cancel_picks_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol, static void pf_cancel_picks_locked(grpc_lb_policy* pol,
uint32_t initial_metadata_flags_mask, uint32_t initial_metadata_flags_mask,
uint32_t initial_metadata_flags_eq, uint32_t initial_metadata_flags_eq,
grpc_error* error) { grpc_error* error) {
@ -136,7 +135,7 @@ static void pf_cancel_picks_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
pending_pick* next = pp->next; pending_pick* next = pp->next;
if ((pp->initial_metadata_flags & initial_metadata_flags_mask) == if ((pp->initial_metadata_flags & initial_metadata_flags_mask) ==
initial_metadata_flags_eq) { initial_metadata_flags_eq) {
GRPC_CLOSURE_SCHED(exec_ctx, pp->on_complete, GRPC_CLOSURE_SCHED(pp->on_complete,
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Pick Cancelled", &error, 1)); "Pick Cancelled", &error, 1));
gpr_free(pp); gpr_free(pp);
@ -149,8 +148,7 @@ static void pf_cancel_picks_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
static void start_picking_locked(grpc_exec_ctx* exec_ctx, static void start_picking_locked(pick_first_lb_policy* p) {
pick_first_lb_policy* p) {
p->started_picking = true; p->started_picking = true;
if (p->subchannel_list != nullptr && if (p->subchannel_list != nullptr &&
p->subchannel_list->num_subchannels > 0) { p->subchannel_list->num_subchannels > 0) {
@ -160,21 +158,21 @@ static void start_picking_locked(grpc_exec_ctx* exec_ctx,
grpc_lb_subchannel_list_ref_for_connectivity_watch( grpc_lb_subchannel_list_ref_for_connectivity_watch(
p->subchannel_list, "connectivity_watch+start_picking"); p->subchannel_list, "connectivity_watch+start_picking");
grpc_lb_subchannel_data_start_connectivity_watch( grpc_lb_subchannel_data_start_connectivity_watch(
exec_ctx, &p->subchannel_list->subchannels[i]); &p->subchannel_list->subchannels[i]);
break; break;
} }
} }
} }
} }
static void pf_exit_idle_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol) { static void pf_exit_idle_locked(grpc_lb_policy* pol) {
pick_first_lb_policy* p = (pick_first_lb_policy*)pol; pick_first_lb_policy* p = (pick_first_lb_policy*)pol;
if (!p->started_picking) { if (!p->started_picking) {
start_picking_locked(exec_ctx, p); start_picking_locked(p);
} }
} }
static int pf_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol, static int pf_pick_locked(grpc_lb_policy* pol,
const grpc_lb_policy_pick_args* pick_args, const grpc_lb_policy_pick_args* pick_args,
grpc_connected_subchannel** target, grpc_connected_subchannel** target,
grpc_call_context_element* context, void** user_data, grpc_call_context_element* context, void** user_data,
@ -188,7 +186,7 @@ static int pf_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
} }
// No subchannel selected yet, so handle asynchronously. // No subchannel selected yet, so handle asynchronously.
if (!p->started_picking) { if (!p->started_picking) {
start_picking_locked(exec_ctx, p); start_picking_locked(p);
} }
pending_pick* pp = (pending_pick*)gpr_malloc(sizeof(*pp)); pending_pick* pp = (pending_pick*)gpr_malloc(sizeof(*pp));
pp->next = p->pending_picks; pp->next = p->pending_picks;
@ -199,48 +197,43 @@ static int pf_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
return 0; return 0;
} }
static void destroy_unselected_subchannels_locked(grpc_exec_ctx* exec_ctx, static void destroy_unselected_subchannels_locked(pick_first_lb_policy* p) {
pick_first_lb_policy* p) {
for (size_t i = 0; i < p->subchannel_list->num_subchannels; ++i) { for (size_t i = 0; i < p->subchannel_list->num_subchannels; ++i) {
grpc_lb_subchannel_data* sd = &p->subchannel_list->subchannels[i]; grpc_lb_subchannel_data* sd = &p->subchannel_list->subchannels[i];
if (p->selected != sd) { if (p->selected != sd) {
grpc_lb_subchannel_data_unref_subchannel(exec_ctx, sd, grpc_lb_subchannel_data_unref_subchannel(sd,
"selected_different_subchannel"); "selected_different_subchannel");
} }
} }
} }
static grpc_connectivity_state pf_check_connectivity_locked( static grpc_connectivity_state pf_check_connectivity_locked(
grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol, grpc_error** error) { grpc_lb_policy* pol, grpc_error** error) {
pick_first_lb_policy* p = (pick_first_lb_policy*)pol; pick_first_lb_policy* p = (pick_first_lb_policy*)pol;
return grpc_connectivity_state_get(&p->state_tracker, error); return grpc_connectivity_state_get(&p->state_tracker, error);
} }
static void pf_notify_on_state_change_locked(grpc_exec_ctx* exec_ctx, static void pf_notify_on_state_change_locked(grpc_lb_policy* pol,
grpc_lb_policy* pol,
grpc_connectivity_state* current, grpc_connectivity_state* current,
grpc_closure* notify) { grpc_closure* notify) {
pick_first_lb_policy* p = (pick_first_lb_policy*)pol; pick_first_lb_policy* p = (pick_first_lb_policy*)pol;
grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker, grpc_connectivity_state_notify_on_state_change(&p->state_tracker, current,
current, notify); notify);
} }
static void pf_ping_one_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol, static void pf_ping_one_locked(grpc_lb_policy* pol, grpc_closure* closure) {
grpc_closure* closure) {
pick_first_lb_policy* p = (pick_first_lb_policy*)pol; pick_first_lb_policy* p = (pick_first_lb_policy*)pol;
if (p->selected) { if (p->selected) {
grpc_connected_subchannel_ping(exec_ctx, p->selected->connected_subchannel, grpc_connected_subchannel_ping(p->selected->connected_subchannel, closure);
closure);
} else { } else {
GRPC_CLOSURE_SCHED(exec_ctx, closure, GRPC_CLOSURE_SCHED(closure,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Not connected")); GRPC_ERROR_CREATE_FROM_STATIC_STRING("Not connected"));
} }
} }
static void pf_connectivity_changed_locked(grpc_exec_ctx* exec_ctx, void* arg, static void pf_connectivity_changed_locked(void* arg, grpc_error* error);
grpc_error* error);
static void pf_update_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, static void pf_update_locked(grpc_lb_policy* policy,
const grpc_lb_policy_args* args) { const grpc_lb_policy_args* args) {
pick_first_lb_policy* p = (pick_first_lb_policy*)policy; pick_first_lb_policy* p = (pick_first_lb_policy*)policy;
const grpc_arg* arg = const grpc_arg* arg =
@ -249,7 +242,7 @@ static void pf_update_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy,
if (p->subchannel_list == nullptr) { if (p->subchannel_list == nullptr) {
// If we don't have a current subchannel list, go into TRANSIENT FAILURE. // If we don't have a current subchannel list, go into TRANSIENT FAILURE.
grpc_connectivity_state_set( grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing update in args"), GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing update in args"),
"pf_update_missing"); "pf_update_missing");
} else { } else {
@ -268,17 +261,17 @@ static void pf_update_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy,
(void*)p, (unsigned long)addresses->num_addresses); (void*)p, (unsigned long)addresses->num_addresses);
} }
grpc_lb_subchannel_list* subchannel_list = grpc_lb_subchannel_list_create( grpc_lb_subchannel_list* subchannel_list = grpc_lb_subchannel_list_create(
exec_ctx, &p->base, &grpc_lb_pick_first_trace, addresses, args, &p->base, &grpc_lb_pick_first_trace, addresses, args,
pf_connectivity_changed_locked); pf_connectivity_changed_locked);
if (subchannel_list->num_subchannels == 0) { if (subchannel_list->num_subchannels == 0) {
// Empty update or no valid subchannels. Unsubscribe from all current // Empty update or no valid subchannels. Unsubscribe from all current
// subchannels and put the channel in TRANSIENT_FAILURE. // subchannels and put the channel in TRANSIENT_FAILURE.
grpc_connectivity_state_set( grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"), GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
"pf_update_empty"); "pf_update_empty");
if (p->subchannel_list != nullptr) { if (p->subchannel_list != nullptr) {
grpc_lb_subchannel_list_shutdown_and_unref(exec_ctx, p->subchannel_list, grpc_lb_subchannel_list_shutdown_and_unref(p->subchannel_list,
"sl_shutdown_empty_update"); "sl_shutdown_empty_update");
} }
p->subchannel_list = subchannel_list; // Empty list. p->subchannel_list = subchannel_list; // Empty list.
@ -289,7 +282,7 @@ static void pf_update_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy,
// We don't yet have a selected subchannel, so replace the current // We don't yet have a selected subchannel, so replace the current
// subchannel list immediately. // subchannel list immediately.
if (p->subchannel_list != nullptr) { if (p->subchannel_list != nullptr) {
grpc_lb_subchannel_list_shutdown_and_unref(exec_ctx, p->subchannel_list, grpc_lb_subchannel_list_shutdown_and_unref(p->subchannel_list,
"pf_update_before_selected"); "pf_update_before_selected");
} }
p->subchannel_list = subchannel_list; p->subchannel_list = subchannel_list;
@ -314,19 +307,19 @@ static void pf_update_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy,
p->selected = sd; p->selected = sd;
if (p->subchannel_list != nullptr) { if (p->subchannel_list != nullptr) {
grpc_lb_subchannel_list_shutdown_and_unref( grpc_lb_subchannel_list_shutdown_and_unref(
exec_ctx, p->subchannel_list, "pf_update_includes_selected"); p->subchannel_list, "pf_update_includes_selected");
} }
p->subchannel_list = subchannel_list; p->subchannel_list = subchannel_list;
destroy_unselected_subchannels_locked(exec_ctx, p); destroy_unselected_subchannels_locked(p);
grpc_lb_subchannel_list_ref_for_connectivity_watch( grpc_lb_subchannel_list_ref_for_connectivity_watch(
subchannel_list, "connectivity_watch+replace_selected"); subchannel_list, "connectivity_watch+replace_selected");
grpc_lb_subchannel_data_start_connectivity_watch(exec_ctx, sd); grpc_lb_subchannel_data_start_connectivity_watch(sd);
// If there was a previously pending update (which may or may // If there was a previously pending update (which may or may
// not have contained the currently selected subchannel), drop // not have contained the currently selected subchannel), drop
// it, so that it doesn't override what we've done here. // it, so that it doesn't override what we've done here.
if (p->latest_pending_subchannel_list != nullptr) { if (p->latest_pending_subchannel_list != nullptr) {
grpc_lb_subchannel_list_shutdown_and_unref( grpc_lb_subchannel_list_shutdown_and_unref(
exec_ctx, p->latest_pending_subchannel_list, p->latest_pending_subchannel_list,
"pf_update_includes_selected+outdated"); "pf_update_includes_selected+outdated");
p->latest_pending_subchannel_list = nullptr; p->latest_pending_subchannel_list = nullptr;
} }
@ -346,8 +339,7 @@ static void pf_update_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy,
(void*)subchannel_list); (void*)subchannel_list);
} }
grpc_lb_subchannel_list_shutdown_and_unref( grpc_lb_subchannel_list_shutdown_and_unref(
exec_ctx, p->latest_pending_subchannel_list, p->latest_pending_subchannel_list, "sl_outdated_dont_smash");
"sl_outdated_dont_smash");
} }
p->latest_pending_subchannel_list = subchannel_list; p->latest_pending_subchannel_list = subchannel_list;
} }
@ -357,12 +349,11 @@ static void pf_update_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy,
grpc_lb_subchannel_list_ref_for_connectivity_watch( grpc_lb_subchannel_list_ref_for_connectivity_watch(
subchannel_list, "connectivity_watch+update"); subchannel_list, "connectivity_watch+update");
grpc_lb_subchannel_data_start_connectivity_watch( grpc_lb_subchannel_data_start_connectivity_watch(
exec_ctx, &subchannel_list->subchannels[0]); &subchannel_list->subchannels[0]);
} }
} }
static void pf_connectivity_changed_locked(grpc_exec_ctx* exec_ctx, void* arg, static void pf_connectivity_changed_locked(void* arg, grpc_error* error) {
grpc_error* error) {
grpc_lb_subchannel_data* sd = (grpc_lb_subchannel_data*)arg; grpc_lb_subchannel_data* sd = (grpc_lb_subchannel_data*)arg;
pick_first_lb_policy* p = (pick_first_lb_policy*)sd->subchannel_list->policy; pick_first_lb_policy* p = (pick_first_lb_policy*)sd->subchannel_list->policy;
if (grpc_lb_pick_first_trace.enabled()) { if (grpc_lb_pick_first_trace.enabled()) {
@ -380,18 +371,18 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx* exec_ctx, void* arg,
} }
// If the policy is shutting down, unref and return. // If the policy is shutting down, unref and return.
if (p->shutdown) { if (p->shutdown) {
grpc_lb_subchannel_data_stop_connectivity_watch(exec_ctx, sd); grpc_lb_subchannel_data_stop_connectivity_watch(sd);
grpc_lb_subchannel_data_unref_subchannel(exec_ctx, sd, "pf_shutdown"); grpc_lb_subchannel_data_unref_subchannel(sd, "pf_shutdown");
grpc_lb_subchannel_list_unref_for_connectivity_watch( grpc_lb_subchannel_list_unref_for_connectivity_watch(sd->subchannel_list,
exec_ctx, sd->subchannel_list, "pf_shutdown"); "pf_shutdown");
return; return;
} }
// If the subchannel list is shutting down, stop watching. // If the subchannel list is shutting down, stop watching.
if (sd->subchannel_list->shutting_down || error == GRPC_ERROR_CANCELLED) { if (sd->subchannel_list->shutting_down || error == GRPC_ERROR_CANCELLED) {
grpc_lb_subchannel_data_stop_connectivity_watch(exec_ctx, sd); grpc_lb_subchannel_data_stop_connectivity_watch(sd);
grpc_lb_subchannel_data_unref_subchannel(exec_ctx, sd, "pf_sl_shutdown"); grpc_lb_subchannel_data_unref_subchannel(sd, "pf_sl_shutdown");
grpc_lb_subchannel_list_unref_for_connectivity_watch( grpc_lb_subchannel_list_unref_for_connectivity_watch(sd->subchannel_list,
exec_ctx, sd->subchannel_list, "pf_sl_shutdown"); "pf_sl_shutdown");
return; return;
} }
// If we're still here, the notification must be for a subchannel in // If we're still here, the notification must be for a subchannel in
@ -407,15 +398,15 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx* exec_ctx, void* arg,
if (sd->curr_connectivity_state != GRPC_CHANNEL_READY && if (sd->curr_connectivity_state != GRPC_CHANNEL_READY &&
p->latest_pending_subchannel_list != nullptr) { p->latest_pending_subchannel_list != nullptr) {
p->selected = nullptr; p->selected = nullptr;
grpc_lb_subchannel_data_stop_connectivity_watch(exec_ctx, sd); grpc_lb_subchannel_data_stop_connectivity_watch(sd);
grpc_lb_subchannel_list_unref_for_connectivity_watch( grpc_lb_subchannel_list_unref_for_connectivity_watch(
exec_ctx, sd->subchannel_list, "selected_not_ready+switch_to_update"); sd->subchannel_list, "selected_not_ready+switch_to_update");
grpc_lb_subchannel_list_shutdown_and_unref( grpc_lb_subchannel_list_shutdown_and_unref(
exec_ctx, p->subchannel_list, "selected_not_ready+switch_to_update"); p->subchannel_list, "selected_not_ready+switch_to_update");
p->subchannel_list = p->latest_pending_subchannel_list; p->subchannel_list = p->latest_pending_subchannel_list;
p->latest_pending_subchannel_list = nullptr; p->latest_pending_subchannel_list = nullptr;
grpc_connectivity_state_set( grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_REF(error), "selected_not_ready+switch_to_update"); GRPC_ERROR_REF(error), "selected_not_ready+switch_to_update");
} else { } else {
// TODO(juanlishen): we re-resolve when the selected subchannel goes to // TODO(juanlishen): we re-resolve when the selected subchannel goes to
@ -426,27 +417,26 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx* exec_ctx, void* arg,
if (sd->curr_connectivity_state == GRPC_CHANNEL_SHUTDOWN || if (sd->curr_connectivity_state == GRPC_CHANNEL_SHUTDOWN ||
sd->curr_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { sd->curr_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
// If the selected channel goes bad, request a re-resolution. // If the selected channel goes bad, request a re-resolution.
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_IDLE,
GRPC_CHANNEL_IDLE, GRPC_ERROR_NONE, GRPC_ERROR_NONE,
"selected_changed+reresolve"); "selected_changed+reresolve");
p->started_picking = false; p->started_picking = false;
grpc_lb_policy_try_reresolve( grpc_lb_policy_try_reresolve(&p->base, &grpc_lb_pick_first_trace,
exec_ctx, &p->base, &grpc_lb_pick_first_trace, GRPC_ERROR_NONE); GRPC_ERROR_NONE);
} else { } else {
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, grpc_connectivity_state_set(&p->state_tracker,
sd->curr_connectivity_state, sd->curr_connectivity_state,
GRPC_ERROR_REF(error), "selected_changed"); GRPC_ERROR_REF(error), "selected_changed");
} }
if (sd->curr_connectivity_state != GRPC_CHANNEL_SHUTDOWN) { if (sd->curr_connectivity_state != GRPC_CHANNEL_SHUTDOWN) {
// Renew notification. // Renew notification.
grpc_lb_subchannel_data_start_connectivity_watch(exec_ctx, sd); grpc_lb_subchannel_data_start_connectivity_watch(sd);
} else { } else {
p->selected = nullptr; p->selected = nullptr;
grpc_lb_subchannel_data_stop_connectivity_watch(exec_ctx, sd); grpc_lb_subchannel_data_stop_connectivity_watch(sd);
grpc_lb_subchannel_list_unref_for_connectivity_watch( grpc_lb_subchannel_list_unref_for_connectivity_watch(
exec_ctx, sd->subchannel_list, "pf_selected_shutdown"); sd->subchannel_list, "pf_selected_shutdown");
grpc_lb_subchannel_data_unref_subchannel(exec_ctx, sd, grpc_lb_subchannel_data_unref_subchannel(sd, "pf_selected_shutdown");
"pf_selected_shutdown");
} }
} }
return; return;
@ -466,15 +456,14 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx* exec_ctx, void* arg,
// p->subchannel_list. // p->subchannel_list.
if (sd->subchannel_list == p->latest_pending_subchannel_list) { if (sd->subchannel_list == p->latest_pending_subchannel_list) {
GPR_ASSERT(p->subchannel_list != nullptr); GPR_ASSERT(p->subchannel_list != nullptr);
grpc_lb_subchannel_list_shutdown_and_unref(exec_ctx, p->subchannel_list, grpc_lb_subchannel_list_shutdown_and_unref(p->subchannel_list,
"finish_update"); "finish_update");
p->subchannel_list = p->latest_pending_subchannel_list; p->subchannel_list = p->latest_pending_subchannel_list;
p->latest_pending_subchannel_list = nullptr; p->latest_pending_subchannel_list = nullptr;
} }
// Cases 1 and 2. // Cases 1 and 2.
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_READY,
GRPC_CHANNEL_READY, GRPC_ERROR_NONE, GRPC_ERROR_NONE, "connecting_ready");
"connecting_ready");
sd->connected_subchannel = GRPC_CONNECTED_SUBCHANNEL_REF( sd->connected_subchannel = GRPC_CONNECTED_SUBCHANNEL_REF(
grpc_subchannel_get_connected_subchannel(sd->subchannel), grpc_subchannel_get_connected_subchannel(sd->subchannel),
"connected"); "connected");
@ -484,7 +473,7 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx* exec_ctx, void* arg,
(void*)sd->subchannel); (void*)sd->subchannel);
} }
// Drop all other subchannels, since we are now connected. // Drop all other subchannels, since we are now connected.
destroy_unselected_subchannels_locked(exec_ctx, p); destroy_unselected_subchannels_locked(p);
// Update any calls that were waiting for a pick. // Update any calls that were waiting for a pick.
pending_pick* pp; pending_pick* pp;
while ((pp = p->pending_picks)) { while ((pp = p->pending_picks)) {
@ -496,15 +485,15 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx* exec_ctx, void* arg,
"Servicing pending pick with selected subchannel %p", "Servicing pending pick with selected subchannel %p",
(void*)p->selected); (void*)p->selected);
} }
GRPC_CLOSURE_SCHED(exec_ctx, pp->on_complete, GRPC_ERROR_NONE); GRPC_CLOSURE_SCHED(pp->on_complete, GRPC_ERROR_NONE);
gpr_free(pp); gpr_free(pp);
} }
// Renew notification. // Renew notification.
grpc_lb_subchannel_data_start_connectivity_watch(exec_ctx, sd); grpc_lb_subchannel_data_start_connectivity_watch(sd);
break; break;
} }
case GRPC_CHANNEL_TRANSIENT_FAILURE: { case GRPC_CHANNEL_TRANSIENT_FAILURE: {
grpc_lb_subchannel_data_stop_connectivity_watch(exec_ctx, sd); grpc_lb_subchannel_data_stop_connectivity_watch(sd);
do { do {
sd->subchannel_list->checking_subchannel = sd->subchannel_list->checking_subchannel =
(sd->subchannel_list->checking_subchannel + 1) % (sd->subchannel_list->checking_subchannel + 1) %
@ -517,29 +506,28 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx* exec_ctx, void* arg,
if (sd->subchannel_list->checking_subchannel == 0 && if (sd->subchannel_list->checking_subchannel == 0 &&
sd->subchannel_list == p->subchannel_list) { sd->subchannel_list == p->subchannel_list) {
grpc_connectivity_state_set( grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_REF(error), "connecting_transient_failure"); GRPC_ERROR_REF(error), "connecting_transient_failure");
} }
// Reuses the connectivity refs from the previous watch. // Reuses the connectivity refs from the previous watch.
grpc_lb_subchannel_data_start_connectivity_watch(exec_ctx, sd); grpc_lb_subchannel_data_start_connectivity_watch(sd);
break; break;
} }
case GRPC_CHANNEL_CONNECTING: case GRPC_CHANNEL_CONNECTING:
case GRPC_CHANNEL_IDLE: { case GRPC_CHANNEL_IDLE: {
// Only update connectivity state in case 1. // Only update connectivity state in case 1.
if (sd->subchannel_list == p->subchannel_list) { if (sd->subchannel_list == p->subchannel_list) {
grpc_connectivity_state_set( grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_CONNECTING,
exec_ctx, &p->state_tracker, GRPC_CHANNEL_CONNECTING, GRPC_ERROR_REF(error),
GRPC_ERROR_REF(error), "connecting_changed"); "connecting_changed");
} }
// Renew notification. // Renew notification.
grpc_lb_subchannel_data_start_connectivity_watch(exec_ctx, sd); grpc_lb_subchannel_data_start_connectivity_watch(sd);
break; break;
} }
case GRPC_CHANNEL_SHUTDOWN: { case GRPC_CHANNEL_SHUTDOWN: {
grpc_lb_subchannel_data_stop_connectivity_watch(exec_ctx, sd); grpc_lb_subchannel_data_stop_connectivity_watch(sd);
grpc_lb_subchannel_data_unref_subchannel(exec_ctx, sd, grpc_lb_subchannel_data_unref_subchannel(sd, "pf_candidate_shutdown");
"pf_candidate_shutdown");
// Advance to next subchannel and check its state. // Advance to next subchannel and check its state.
grpc_lb_subchannel_data* original_sd = sd; grpc_lb_subchannel_data* original_sd = sd;
do { do {
@ -551,31 +539,30 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx* exec_ctx, void* arg,
} while (sd->subchannel == nullptr && sd != original_sd); } while (sd->subchannel == nullptr && sd != original_sd);
if (sd == original_sd) { if (sd == original_sd) {
grpc_lb_subchannel_list_unref_for_connectivity_watch( grpc_lb_subchannel_list_unref_for_connectivity_watch(
exec_ctx, sd->subchannel_list, "pf_exhausted_subchannels"); sd->subchannel_list, "pf_exhausted_subchannels");
if (sd->subchannel_list == p->subchannel_list) { if (sd->subchannel_list == p->subchannel_list) {
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_IDLE,
GRPC_CHANNEL_IDLE, GRPC_ERROR_NONE, GRPC_ERROR_NONE,
"exhausted_subchannels+reresolve"); "exhausted_subchannels+reresolve");
p->started_picking = false; p->started_picking = false;
grpc_lb_policy_try_reresolve( grpc_lb_policy_try_reresolve(&p->base, &grpc_lb_pick_first_trace,
exec_ctx, &p->base, &grpc_lb_pick_first_trace, GRPC_ERROR_NONE); GRPC_ERROR_NONE);
} }
} else { } else {
if (sd->subchannel_list == p->subchannel_list) { if (sd->subchannel_list == p->subchannel_list) {
grpc_connectivity_state_set( grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_REF(error), "subchannel_failed"); GRPC_ERROR_REF(error), "subchannel_failed");
} }
// Reuses the connectivity refs from the previous watch. // Reuses the connectivity refs from the previous watch.
grpc_lb_subchannel_data_start_connectivity_watch(exec_ctx, sd); grpc_lb_subchannel_data_start_connectivity_watch(sd);
} }
} }
} }
} }
static void pf_set_reresolve_closure_locked( static void pf_set_reresolve_closure_locked(
grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, grpc_lb_policy* policy, grpc_closure* request_reresolution) {
grpc_closure* request_reresolution) {
pick_first_lb_policy* p = (pick_first_lb_policy*)policy; pick_first_lb_policy* p = (pick_first_lb_policy*)policy;
GPR_ASSERT(!p->shutdown); GPR_ASSERT(!p->shutdown);
GPR_ASSERT(policy->request_reresolution == nullptr); GPR_ASSERT(policy->request_reresolution == nullptr);
@ -599,15 +586,14 @@ static void pick_first_factory_ref(grpc_lb_policy_factory* factory) {}
static void pick_first_factory_unref(grpc_lb_policy_factory* factory) {} static void pick_first_factory_unref(grpc_lb_policy_factory* factory) {}
static grpc_lb_policy* create_pick_first(grpc_exec_ctx* exec_ctx, static grpc_lb_policy* create_pick_first(grpc_lb_policy_factory* factory,
grpc_lb_policy_factory* factory,
grpc_lb_policy_args* args) { grpc_lb_policy_args* args) {
GPR_ASSERT(args->client_channel_factory != nullptr); GPR_ASSERT(args->client_channel_factory != nullptr);
pick_first_lb_policy* p = (pick_first_lb_policy*)gpr_zalloc(sizeof(*p)); pick_first_lb_policy* p = (pick_first_lb_policy*)gpr_zalloc(sizeof(*p));
if (grpc_lb_pick_first_trace.enabled()) { if (grpc_lb_pick_first_trace.enabled()) {
gpr_log(GPR_DEBUG, "Pick First %p created.", (void*)p); gpr_log(GPR_DEBUG, "Pick First %p created.", (void*)p);
} }
pf_update_locked(exec_ctx, &p->base, args); pf_update_locked(&p->base, args);
grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable, args->combiner); grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable, args->combiner);
grpc_subchannel_index_ref(); grpc_subchannel_index_ref();
return &p->base; return &p->base;

@ -154,7 +154,7 @@ static void update_last_ready_subchannel_index_locked(round_robin_lb_policy* p,
} }
} }
static void rr_destroy(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol) { static void rr_destroy(grpc_lb_policy* pol) {
round_robin_lb_policy* p = (round_robin_lb_policy*)pol; round_robin_lb_policy* p = (round_robin_lb_policy*)pol;
if (grpc_lb_round_robin_trace.enabled()) { if (grpc_lb_round_robin_trace.enabled()) {
gpr_log(GPR_DEBUG, "[RR %p] Destroying Round Robin policy at %p", gpr_log(GPR_DEBUG, "[RR %p] Destroying Round Robin policy at %p",
@ -162,12 +162,12 @@ static void rr_destroy(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol) {
} }
GPR_ASSERT(p->subchannel_list == nullptr); GPR_ASSERT(p->subchannel_list == nullptr);
GPR_ASSERT(p->latest_pending_subchannel_list == nullptr); GPR_ASSERT(p->latest_pending_subchannel_list == nullptr);
grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker); grpc_connectivity_state_destroy(&p->state_tracker);
grpc_subchannel_index_unref(); grpc_subchannel_index_unref();
gpr_free(p); gpr_free(p);
} }
static void rr_shutdown_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol) { static void rr_shutdown_locked(grpc_lb_policy* pol) {
round_robin_lb_policy* p = (round_robin_lb_policy*)pol; round_robin_lb_policy* p = (round_robin_lb_policy*)pol;
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown"); grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown");
if (grpc_lb_round_robin_trace.enabled()) { if (grpc_lb_round_robin_trace.enabled()) {
@ -178,29 +178,27 @@ static void rr_shutdown_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol) {
while ((pp = p->pending_picks) != nullptr) { while ((pp = p->pending_picks) != nullptr) {
p->pending_picks = pp->next; p->pending_picks = pp->next;
*pp->target = nullptr; *pp->target = nullptr;
GRPC_CLOSURE_SCHED(exec_ctx, pp->on_complete, GRPC_ERROR_REF(error)); GRPC_CLOSURE_SCHED(pp->on_complete, GRPC_ERROR_REF(error));
gpr_free(pp); gpr_free(pp);
} }
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error), GRPC_ERROR_REF(error), "rr_shutdown");
"rr_shutdown");
if (p->subchannel_list != nullptr) { if (p->subchannel_list != nullptr) {
grpc_lb_subchannel_list_shutdown_and_unref(exec_ctx, p->subchannel_list, grpc_lb_subchannel_list_shutdown_and_unref(p->subchannel_list,
"sl_shutdown_rr_shutdown"); "sl_shutdown_rr_shutdown");
p->subchannel_list = nullptr; p->subchannel_list = nullptr;
} }
if (p->latest_pending_subchannel_list != nullptr) { if (p->latest_pending_subchannel_list != nullptr) {
grpc_lb_subchannel_list_shutdown_and_unref( grpc_lb_subchannel_list_shutdown_and_unref(
exec_ctx, p->latest_pending_subchannel_list, p->latest_pending_subchannel_list, "sl_shutdown_pending_rr_shutdown");
"sl_shutdown_pending_rr_shutdown");
p->latest_pending_subchannel_list = nullptr; p->latest_pending_subchannel_list = nullptr;
} }
grpc_lb_policy_try_reresolve(exec_ctx, &p->base, &grpc_lb_round_robin_trace, grpc_lb_policy_try_reresolve(&p->base, &grpc_lb_round_robin_trace,
GRPC_ERROR_CANCELLED); GRPC_ERROR_CANCELLED);
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
static void rr_cancel_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol, static void rr_cancel_pick_locked(grpc_lb_policy* pol,
grpc_connected_subchannel** target, grpc_connected_subchannel** target,
grpc_error* error) { grpc_error* error) {
round_robin_lb_policy* p = (round_robin_lb_policy*)pol; round_robin_lb_policy* p = (round_robin_lb_policy*)pol;
@ -210,7 +208,7 @@ static void rr_cancel_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
pending_pick* next = pp->next; pending_pick* next = pp->next;
if (pp->target == target) { if (pp->target == target) {
*target = nullptr; *target = nullptr;
GRPC_CLOSURE_SCHED(exec_ctx, pp->on_complete, GRPC_CLOSURE_SCHED(pp->on_complete,
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Pick cancelled", &error, 1)); "Pick cancelled", &error, 1));
gpr_free(pp); gpr_free(pp);
@ -223,7 +221,7 @@ static void rr_cancel_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
static void rr_cancel_picks_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol, static void rr_cancel_picks_locked(grpc_lb_policy* pol,
uint32_t initial_metadata_flags_mask, uint32_t initial_metadata_flags_mask,
uint32_t initial_metadata_flags_eq, uint32_t initial_metadata_flags_eq,
grpc_error* error) { grpc_error* error) {
@ -235,7 +233,7 @@ static void rr_cancel_picks_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
if ((pp->initial_metadata_flags & initial_metadata_flags_mask) == if ((pp->initial_metadata_flags & initial_metadata_flags_mask) ==
initial_metadata_flags_eq) { initial_metadata_flags_eq) {
*pp->target = nullptr; *pp->target = nullptr;
GRPC_CLOSURE_SCHED(exec_ctx, pp->on_complete, GRPC_CLOSURE_SCHED(pp->on_complete,
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Pick cancelled", &error, 1)); "Pick cancelled", &error, 1));
gpr_free(pp); gpr_free(pp);
@ -248,27 +246,26 @@ static void rr_cancel_picks_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
static void start_picking_locked(grpc_exec_ctx* exec_ctx, static void start_picking_locked(round_robin_lb_policy* p) {
round_robin_lb_policy* p) {
p->started_picking = true; p->started_picking = true;
for (size_t i = 0; i < p->subchannel_list->num_subchannels; i++) { for (size_t i = 0; i < p->subchannel_list->num_subchannels; i++) {
if (p->subchannel_list->subchannels[i].subchannel != nullptr) { if (p->subchannel_list->subchannels[i].subchannel != nullptr) {
grpc_lb_subchannel_list_ref_for_connectivity_watch(p->subchannel_list, grpc_lb_subchannel_list_ref_for_connectivity_watch(p->subchannel_list,
"connectivity_watch"); "connectivity_watch");
grpc_lb_subchannel_data_start_connectivity_watch( grpc_lb_subchannel_data_start_connectivity_watch(
exec_ctx, &p->subchannel_list->subchannels[i]); &p->subchannel_list->subchannels[i]);
} }
} }
} }
static void rr_exit_idle_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol) { static void rr_exit_idle_locked(grpc_lb_policy* pol) {
round_robin_lb_policy* p = (round_robin_lb_policy*)pol; round_robin_lb_policy* p = (round_robin_lb_policy*)pol;
if (!p->started_picking) { if (!p->started_picking) {
start_picking_locked(exec_ctx, p); start_picking_locked(p);
} }
} }
static int rr_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol, static int rr_pick_locked(grpc_lb_policy* pol,
const grpc_lb_policy_pick_args* pick_args, const grpc_lb_policy_pick_args* pick_args,
grpc_connected_subchannel** target, grpc_connected_subchannel** target,
grpc_call_context_element* context, void** user_data, grpc_call_context_element* context, void** user_data,
@ -305,7 +302,7 @@ static int rr_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
} }
/* no pick currently available. Save for later in list of pending picks */ /* no pick currently available. Save for later in list of pending picks */
if (!p->started_picking) { if (!p->started_picking) {
start_picking_locked(exec_ctx, p); start_picking_locked(p);
} }
pending_pick* pp = (pending_pick*)gpr_malloc(sizeof(*pp)); pending_pick* pp = (pending_pick*)gpr_malloc(sizeof(*pp));
pp->next = p->pending_picks; pp->next = p->pending_picks;
@ -348,8 +345,7 @@ static void update_state_counters_locked(grpc_lb_subchannel_data* sd) {
* (the grpc_lb_subchannel_data associated with the updated subchannel) and the * (the grpc_lb_subchannel_data associated with the updated subchannel) and the
* subchannel list \a sd belongs to (sd->subchannel_list). \a error will be used * subchannel list \a sd belongs to (sd->subchannel_list). \a error will be used
* only if the policy transitions to state TRANSIENT_FAILURE. */ * only if the policy transitions to state TRANSIENT_FAILURE. */
static void update_lb_connectivity_status_locked(grpc_exec_ctx* exec_ctx, static void update_lb_connectivity_status_locked(grpc_lb_subchannel_data* sd,
grpc_lb_subchannel_data* sd,
grpc_error* error) { grpc_error* error) {
/* In priority order. The first rule to match terminates the search (ie, if we /* In priority order. The first rule to match terminates the search (ie, if we
* are on rule n, all previous rules were unfulfilled). * are on rule n, all previous rules were unfulfilled).
@ -382,38 +378,36 @@ static void update_lb_connectivity_status_locked(grpc_exec_ctx* exec_ctx,
round_robin_lb_policy* p = (round_robin_lb_policy*)subchannel_list->policy; round_robin_lb_policy* p = (round_robin_lb_policy*)subchannel_list->policy;
if (subchannel_list->num_ready > 0) { if (subchannel_list->num_ready > 0) {
/* 1) READY */ /* 1) READY */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, GRPC_CHANNEL_READY, grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_READY,
GRPC_ERROR_NONE, "rr_ready"); GRPC_ERROR_NONE, "rr_ready");
} else if (sd->curr_connectivity_state == GRPC_CHANNEL_CONNECTING) { } else if (sd->curr_connectivity_state == GRPC_CHANNEL_CONNECTING) {
/* 2) CONNECTING */ /* 2) CONNECTING */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_CONNECTING,
GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, GRPC_ERROR_NONE, "rr_connecting");
"rr_connecting");
} else if (subchannel_list->num_shutdown == } else if (subchannel_list->num_shutdown ==
subchannel_list->num_subchannels) { subchannel_list->num_subchannels) {
/* 3) IDLE and re-resolve */ /* 3) IDLE and re-resolve */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, GRPC_CHANNEL_IDLE, grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_IDLE,
GRPC_ERROR_NONE, GRPC_ERROR_NONE,
"rr_exhausted_subchannels+reresolve"); "rr_exhausted_subchannels+reresolve");
p->started_picking = false; p->started_picking = false;
grpc_lb_policy_try_reresolve(exec_ctx, &p->base, &grpc_lb_round_robin_trace, grpc_lb_policy_try_reresolve(&p->base, &grpc_lb_round_robin_trace,
GRPC_ERROR_NONE); GRPC_ERROR_NONE);
} else if (subchannel_list->num_transient_failures == } else if (subchannel_list->num_transient_failures ==
subchannel_list->num_subchannels) { subchannel_list->num_subchannels) {
/* 4) TRANSIENT_FAILURE */ /* 4) TRANSIENT_FAILURE */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, grpc_connectivity_state_set(&p->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_REF(error), "rr_transient_failure"); GRPC_ERROR_REF(error), "rr_transient_failure");
} else if (subchannel_list->num_idle == subchannel_list->num_subchannels) { } else if (subchannel_list->num_idle == subchannel_list->num_subchannels) {
/* 5) IDLE */ /* 5) IDLE */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, GRPC_CHANNEL_IDLE, grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_IDLE,
GRPC_ERROR_NONE, "rr_idle"); GRPC_ERROR_NONE, "rr_idle");
} }
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
static void rr_connectivity_changed_locked(grpc_exec_ctx* exec_ctx, void* arg, static void rr_connectivity_changed_locked(void* arg, grpc_error* error) {
grpc_error* error) {
grpc_lb_subchannel_data* sd = (grpc_lb_subchannel_data*)arg; grpc_lb_subchannel_data* sd = (grpc_lb_subchannel_data*)arg;
round_robin_lb_policy* p = round_robin_lb_policy* p =
(round_robin_lb_policy*)sd->subchannel_list->policy; (round_robin_lb_policy*)sd->subchannel_list->policy;
@ -431,18 +425,18 @@ static void rr_connectivity_changed_locked(grpc_exec_ctx* exec_ctx, void* arg,
} }
// If the policy is shutting down, unref and return. // If the policy is shutting down, unref and return.
if (p->shutdown) { if (p->shutdown) {
grpc_lb_subchannel_data_stop_connectivity_watch(exec_ctx, sd); grpc_lb_subchannel_data_stop_connectivity_watch(sd);
grpc_lb_subchannel_data_unref_subchannel(exec_ctx, sd, "rr_shutdown"); grpc_lb_subchannel_data_unref_subchannel(sd, "rr_shutdown");
grpc_lb_subchannel_list_unref_for_connectivity_watch( grpc_lb_subchannel_list_unref_for_connectivity_watch(sd->subchannel_list,
exec_ctx, sd->subchannel_list, "rr_shutdown"); "rr_shutdown");
return; return;
} }
// If the subchannel list is shutting down, stop watching. // If the subchannel list is shutting down, stop watching.
if (sd->subchannel_list->shutting_down || error == GRPC_ERROR_CANCELLED) { if (sd->subchannel_list->shutting_down || error == GRPC_ERROR_CANCELLED) {
grpc_lb_subchannel_data_stop_connectivity_watch(exec_ctx, sd); grpc_lb_subchannel_data_stop_connectivity_watch(sd);
grpc_lb_subchannel_data_unref_subchannel(exec_ctx, sd, "rr_sl_shutdown"); grpc_lb_subchannel_data_unref_subchannel(sd, "rr_sl_shutdown");
grpc_lb_subchannel_list_unref_for_connectivity_watch( grpc_lb_subchannel_list_unref_for_connectivity_watch(sd->subchannel_list,
exec_ctx, sd->subchannel_list, "rr_sl_shutdown"); "rr_sl_shutdown");
return; return;
} }
// If we're still here, the notification must be for a subchannel in // If we're still here, the notification must be for a subchannel in
@ -455,14 +449,13 @@ static void rr_connectivity_changed_locked(grpc_exec_ctx* exec_ctx, void* arg,
sd->curr_connectivity_state = sd->pending_connectivity_state_unsafe; sd->curr_connectivity_state = sd->pending_connectivity_state_unsafe;
// Update state counters and new overall state. // Update state counters and new overall state.
update_state_counters_locked(sd); update_state_counters_locked(sd);
update_lb_connectivity_status_locked(exec_ctx, sd, GRPC_ERROR_REF(error)); update_lb_connectivity_status_locked(sd, GRPC_ERROR_REF(error));
// If the sd's new state is SHUTDOWN, unref the subchannel. // If the sd's new state is SHUTDOWN, unref the subchannel.
if (sd->curr_connectivity_state == GRPC_CHANNEL_SHUTDOWN) { if (sd->curr_connectivity_state == GRPC_CHANNEL_SHUTDOWN) {
grpc_lb_subchannel_data_stop_connectivity_watch(exec_ctx, sd); grpc_lb_subchannel_data_stop_connectivity_watch(sd);
grpc_lb_subchannel_data_unref_subchannel(exec_ctx, sd, grpc_lb_subchannel_data_unref_subchannel(sd, "rr_connectivity_shutdown");
"rr_connectivity_shutdown");
grpc_lb_subchannel_list_unref_for_connectivity_watch( grpc_lb_subchannel_list_unref_for_connectivity_watch(
exec_ctx, sd->subchannel_list, "rr_connectivity_shutdown"); sd->subchannel_list, "rr_connectivity_shutdown");
} else { // sd not in SHUTDOWN } else { // sd not in SHUTDOWN
if (sd->curr_connectivity_state == GRPC_CHANNEL_READY) { if (sd->curr_connectivity_state == GRPC_CHANNEL_READY) {
if (sd->connected_subchannel == nullptr) { if (sd->connected_subchannel == nullptr) {
@ -490,8 +483,8 @@ static void rr_connectivity_changed_locked(grpc_exec_ctx* exec_ctx, void* arg,
} }
if (p->subchannel_list != nullptr) { if (p->subchannel_list != nullptr) {
// dispose of the current subchannel_list // dispose of the current subchannel_list
grpc_lb_subchannel_list_shutdown_and_unref( grpc_lb_subchannel_list_shutdown_and_unref(p->subchannel_list,
exec_ctx, p->subchannel_list, "sl_phase_out_shutdown"); "sl_phase_out_shutdown");
} }
p->subchannel_list = p->latest_pending_subchannel_list; p->subchannel_list = p->latest_pending_subchannel_list;
p->latest_pending_subchannel_list = nullptr; p->latest_pending_subchannel_list = nullptr;
@ -523,32 +516,30 @@ static void rr_connectivity_changed_locked(grpc_exec_ctx* exec_ctx, void* arg,
(void*)p, (void*)selected->subchannel, (void*)p, (void*)selected->subchannel,
(void*)p->subchannel_list, (unsigned long)next_ready_index); (void*)p->subchannel_list, (unsigned long)next_ready_index);
} }
GRPC_CLOSURE_SCHED(exec_ctx, pp->on_complete, GRPC_ERROR_NONE); GRPC_CLOSURE_SCHED(pp->on_complete, GRPC_ERROR_NONE);
gpr_free(pp); gpr_free(pp);
} }
} }
// Renew notification. // Renew notification.
grpc_lb_subchannel_data_start_connectivity_watch(exec_ctx, sd); grpc_lb_subchannel_data_start_connectivity_watch(sd);
} }
} }
static grpc_connectivity_state rr_check_connectivity_locked( static grpc_connectivity_state rr_check_connectivity_locked(
grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol, grpc_error** error) { grpc_lb_policy* pol, grpc_error** error) {
round_robin_lb_policy* p = (round_robin_lb_policy*)pol; round_robin_lb_policy* p = (round_robin_lb_policy*)pol;
return grpc_connectivity_state_get(&p->state_tracker, error); return grpc_connectivity_state_get(&p->state_tracker, error);
} }
static void rr_notify_on_state_change_locked(grpc_exec_ctx* exec_ctx, static void rr_notify_on_state_change_locked(grpc_lb_policy* pol,
grpc_lb_policy* pol,
grpc_connectivity_state* current, grpc_connectivity_state* current,
grpc_closure* notify) { grpc_closure* notify) {
round_robin_lb_policy* p = (round_robin_lb_policy*)pol; round_robin_lb_policy* p = (round_robin_lb_policy*)pol;
grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker, grpc_connectivity_state_notify_on_state_change(&p->state_tracker, current,
current, notify); notify);
} }
static void rr_ping_one_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol, static void rr_ping_one_locked(grpc_lb_policy* pol, grpc_closure* closure) {
grpc_closure* closure) {
round_robin_lb_policy* p = (round_robin_lb_policy*)pol; round_robin_lb_policy* p = (round_robin_lb_policy*)pol;
const size_t next_ready_index = get_next_ready_subchannel_index_locked(p); const size_t next_ready_index = get_next_ready_subchannel_index_locked(p);
if (next_ready_index < p->subchannel_list->num_subchannels) { if (next_ready_index < p->subchannel_list->num_subchannels) {
@ -556,16 +547,15 @@ static void rr_ping_one_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
&p->subchannel_list->subchannels[next_ready_index]; &p->subchannel_list->subchannels[next_ready_index];
grpc_connected_subchannel* target = GRPC_CONNECTED_SUBCHANNEL_REF( grpc_connected_subchannel* target = GRPC_CONNECTED_SUBCHANNEL_REF(
selected->connected_subchannel, "rr_ping"); selected->connected_subchannel, "rr_ping");
grpc_connected_subchannel_ping(exec_ctx, target, closure); grpc_connected_subchannel_ping(target, closure);
GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, target, "rr_ping"); GRPC_CONNECTED_SUBCHANNEL_UNREF(target, "rr_ping");
} else { } else {
GRPC_CLOSURE_SCHED( GRPC_CLOSURE_SCHED(closure, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
exec_ctx, closure, "Round Robin not connected"));
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Round Robin not connected"));
} }
} }
static void rr_update_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, static void rr_update_locked(grpc_lb_policy* policy,
const grpc_lb_policy_args* args) { const grpc_lb_policy_args* args) {
round_robin_lb_policy* p = (round_robin_lb_policy*)policy; round_robin_lb_policy* p = (round_robin_lb_policy*)policy;
const grpc_arg* arg = const grpc_arg* arg =
@ -576,7 +566,7 @@ static void rr_update_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy,
// Otherwise, keep using the current subchannel list (ignore this update). // Otherwise, keep using the current subchannel list (ignore this update).
if (p->subchannel_list == nullptr) { if (p->subchannel_list == nullptr) {
grpc_connectivity_state_set( grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing update in args"), GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing update in args"),
"rr_update_missing"); "rr_update_missing");
} }
@ -588,15 +578,15 @@ static void rr_update_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy,
addresses->num_addresses); addresses->num_addresses);
} }
grpc_lb_subchannel_list* subchannel_list = grpc_lb_subchannel_list_create( grpc_lb_subchannel_list* subchannel_list = grpc_lb_subchannel_list_create(
exec_ctx, &p->base, &grpc_lb_round_robin_trace, addresses, args, &p->base, &grpc_lb_round_robin_trace, addresses, args,
rr_connectivity_changed_locked); rr_connectivity_changed_locked);
if (subchannel_list->num_subchannels == 0) { if (subchannel_list->num_subchannels == 0) {
grpc_connectivity_state_set( grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"), GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
"rr_update_empty"); "rr_update_empty");
if (p->subchannel_list != nullptr) { if (p->subchannel_list != nullptr) {
grpc_lb_subchannel_list_shutdown_and_unref(exec_ctx, p->subchannel_list, grpc_lb_subchannel_list_shutdown_and_unref(p->subchannel_list,
"sl_shutdown_empty_update"); "sl_shutdown_empty_update");
} }
p->subchannel_list = subchannel_list; // empty list p->subchannel_list = subchannel_list; // empty list
@ -612,7 +602,7 @@ static void rr_update_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy,
(void*)subchannel_list); (void*)subchannel_list);
} }
grpc_lb_subchannel_list_shutdown_and_unref( grpc_lb_subchannel_list_shutdown_and_unref(
exec_ctx, p->latest_pending_subchannel_list, "sl_outdated"); p->latest_pending_subchannel_list, "sl_outdated");
} }
p->latest_pending_subchannel_list = subchannel_list; p->latest_pending_subchannel_list = subchannel_list;
for (size_t i = 0; i < subchannel_list->num_subchannels; ++i) { for (size_t i = 0; i < subchannel_list->num_subchannels; ++i) {
@ -623,22 +613,21 @@ static void rr_update_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy,
grpc_lb_subchannel_list_ref_for_connectivity_watch(subchannel_list, grpc_lb_subchannel_list_ref_for_connectivity_watch(subchannel_list,
"connectivity_watch"); "connectivity_watch");
grpc_lb_subchannel_data_start_connectivity_watch( grpc_lb_subchannel_data_start_connectivity_watch(
exec_ctx, &subchannel_list->subchannels[i]); &subchannel_list->subchannels[i]);
} }
} else { } else {
// The policy isn't picking yet. Save the update for later, disposing of // The policy isn't picking yet. Save the update for later, disposing of
// previous version if any. // previous version if any.
if (p->subchannel_list != nullptr) { if (p->subchannel_list != nullptr) {
grpc_lb_subchannel_list_shutdown_and_unref( grpc_lb_subchannel_list_shutdown_and_unref(
exec_ctx, p->subchannel_list, "rr_update_before_started_picking"); p->subchannel_list, "rr_update_before_started_picking");
} }
p->subchannel_list = subchannel_list; p->subchannel_list = subchannel_list;
} }
} }
static void rr_set_reresolve_closure_locked( static void rr_set_reresolve_closure_locked(
grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy, grpc_lb_policy* policy, grpc_closure* request_reresolution) {
grpc_closure* request_reresolution) {
round_robin_lb_policy* p = (round_robin_lb_policy*)policy; round_robin_lb_policy* p = (round_robin_lb_policy*)policy;
GPR_ASSERT(!p->shutdown); GPR_ASSERT(!p->shutdown);
GPR_ASSERT(policy->request_reresolution == nullptr); GPR_ASSERT(policy->request_reresolution == nullptr);
@ -662,8 +651,7 @@ static void round_robin_factory_ref(grpc_lb_policy_factory* factory) {}
static void round_robin_factory_unref(grpc_lb_policy_factory* factory) {} static void round_robin_factory_unref(grpc_lb_policy_factory* factory) {}
static grpc_lb_policy* round_robin_create(grpc_exec_ctx* exec_ctx, static grpc_lb_policy* round_robin_create(grpc_lb_policy_factory* factory,
grpc_lb_policy_factory* factory,
grpc_lb_policy_args* args) { grpc_lb_policy_args* args) {
GPR_ASSERT(args->client_channel_factory != nullptr); GPR_ASSERT(args->client_channel_factory != nullptr);
round_robin_lb_policy* p = (round_robin_lb_policy*)gpr_zalloc(sizeof(*p)); round_robin_lb_policy* p = (round_robin_lb_policy*)gpr_zalloc(sizeof(*p));
@ -671,7 +659,7 @@ static grpc_lb_policy* round_robin_create(grpc_exec_ctx* exec_ctx,
grpc_subchannel_index_ref(); grpc_subchannel_index_ref();
grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE, grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE,
"round_robin"); "round_robin");
rr_update_locked(exec_ctx, &p->base, args); rr_update_locked(&p->base, args);
if (grpc_lb_round_robin_trace.enabled()) { if (grpc_lb_round_robin_trace.enabled()) {
gpr_log(GPR_DEBUG, "[RR %p] Created with %lu subchannels", (void*)p, gpr_log(GPR_DEBUG, "[RR %p] Created with %lu subchannels", (void*)p,
(unsigned long)p->subchannel_list->num_subchannels); (unsigned long)p->subchannel_list->num_subchannels);

@ -28,8 +28,7 @@
#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/connectivity_state.h"
void grpc_lb_subchannel_data_unref_subchannel(grpc_exec_ctx* exec_ctx, void grpc_lb_subchannel_data_unref_subchannel(grpc_lb_subchannel_data* sd,
grpc_lb_subchannel_data* sd,
const char* reason) { const char* reason) {
if (sd->subchannel != nullptr) { if (sd->subchannel != nullptr) {
if (sd->subchannel_list->tracer->enabled()) { if (sd->subchannel_list->tracer->enabled()) {
@ -41,23 +40,22 @@ void grpc_lb_subchannel_data_unref_subchannel(grpc_exec_ctx* exec_ctx,
(size_t)(sd - sd->subchannel_list->subchannels), (size_t)(sd - sd->subchannel_list->subchannels),
sd->subchannel_list->num_subchannels, sd->subchannel); sd->subchannel_list->num_subchannels, sd->subchannel);
} }
GRPC_SUBCHANNEL_UNREF(exec_ctx, sd->subchannel, reason); GRPC_SUBCHANNEL_UNREF(sd->subchannel, reason);
sd->subchannel = nullptr; sd->subchannel = nullptr;
if (sd->connected_subchannel != nullptr) { if (sd->connected_subchannel != nullptr) {
GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, sd->connected_subchannel, GRPC_CONNECTED_SUBCHANNEL_UNREF(sd->connected_subchannel, reason);
reason);
sd->connected_subchannel = nullptr; sd->connected_subchannel = nullptr;
} }
if (sd->user_data != nullptr) { if (sd->user_data != nullptr) {
GPR_ASSERT(sd->user_data_vtable != nullptr); GPR_ASSERT(sd->user_data_vtable != nullptr);
sd->user_data_vtable->destroy(exec_ctx, sd->user_data); sd->user_data_vtable->destroy(sd->user_data);
sd->user_data = nullptr; sd->user_data = nullptr;
} }
} }
} }
void grpc_lb_subchannel_data_start_connectivity_watch( void grpc_lb_subchannel_data_start_connectivity_watch(
grpc_exec_ctx* exec_ctx, grpc_lb_subchannel_data* sd) { grpc_lb_subchannel_data* sd) {
if (sd->subchannel_list->tracer->enabled()) { if (sd->subchannel_list->tracer->enabled()) {
gpr_log(GPR_DEBUG, gpr_log(GPR_DEBUG,
"[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
@ -69,13 +67,13 @@ void grpc_lb_subchannel_data_start_connectivity_watch(
} }
sd->connectivity_notification_pending = true; sd->connectivity_notification_pending = true;
grpc_subchannel_notify_on_state_change( grpc_subchannel_notify_on_state_change(
exec_ctx, sd->subchannel, sd->subchannel_list->policy->interested_parties, sd->subchannel, sd->subchannel_list->policy->interested_parties,
&sd->pending_connectivity_state_unsafe, &sd->pending_connectivity_state_unsafe,
&sd->connectivity_changed_closure); &sd->connectivity_changed_closure);
} }
void grpc_lb_subchannel_data_stop_connectivity_watch( void grpc_lb_subchannel_data_stop_connectivity_watch(
grpc_exec_ctx* exec_ctx, grpc_lb_subchannel_data* sd) { grpc_lb_subchannel_data* sd) {
if (sd->subchannel_list->tracer->enabled()) { if (sd->subchannel_list->tracer->enabled()) {
gpr_log(GPR_DEBUG, gpr_log(GPR_DEBUG,
"[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
@ -90,7 +88,7 @@ void grpc_lb_subchannel_data_stop_connectivity_watch(
} }
grpc_lb_subchannel_list* grpc_lb_subchannel_list_create( grpc_lb_subchannel_list* grpc_lb_subchannel_list_create(
grpc_exec_ctx* exec_ctx, grpc_lb_policy* p, grpc_core::TraceFlag* tracer, grpc_lb_policy* p, grpc_core::TraceFlag* tracer,
const grpc_lb_addresses* addresses, const grpc_lb_policy_args* args, const grpc_lb_addresses* addresses, const grpc_lb_policy_args* args,
grpc_iomgr_cb_func connectivity_changed_cb) { grpc_iomgr_cb_func connectivity_changed_cb) {
grpc_lb_subchannel_list* subchannel_list = grpc_lb_subchannel_list* subchannel_list =
@ -124,8 +122,8 @@ grpc_lb_subchannel_list* grpc_lb_subchannel_list_create(
gpr_free(addr_arg.value.string); gpr_free(addr_arg.value.string);
sc_args.args = new_args; sc_args.args = new_args;
grpc_subchannel* subchannel = grpc_client_channel_factory_create_subchannel( grpc_subchannel* subchannel = grpc_client_channel_factory_create_subchannel(
exec_ctx, args->client_channel_factory, &sc_args); args->client_channel_factory, &sc_args);
grpc_channel_args_destroy(exec_ctx, new_args); grpc_channel_args_destroy(new_args);
if (subchannel == nullptr) { if (subchannel == nullptr) {
// Subchannel could not be created. // Subchannel could not be created.
if (tracer->enabled()) { if (tracer->enabled()) {
@ -172,8 +170,7 @@ grpc_lb_subchannel_list* grpc_lb_subchannel_list_create(
return subchannel_list; return subchannel_list;
} }
static void subchannel_list_destroy(grpc_exec_ctx* exec_ctx, static void subchannel_list_destroy(grpc_lb_subchannel_list* subchannel_list) {
grpc_lb_subchannel_list* subchannel_list) {
if (subchannel_list->tracer->enabled()) { if (subchannel_list->tracer->enabled()) {
gpr_log(GPR_DEBUG, "[%s %p] Destroying subchannel_list %p", gpr_log(GPR_DEBUG, "[%s %p] Destroying subchannel_list %p",
subchannel_list->tracer->name(), subchannel_list->policy, subchannel_list->tracer->name(), subchannel_list->policy,
@ -181,8 +178,7 @@ static void subchannel_list_destroy(grpc_exec_ctx* exec_ctx,
} }
for (size_t i = 0; i < subchannel_list->num_subchannels; i++) { for (size_t i = 0; i < subchannel_list->num_subchannels; i++) {
grpc_lb_subchannel_data* sd = &subchannel_list->subchannels[i]; grpc_lb_subchannel_data* sd = &subchannel_list->subchannels[i];
grpc_lb_subchannel_data_unref_subchannel(exec_ctx, sd, grpc_lb_subchannel_data_unref_subchannel(sd, "subchannel_list_destroy");
"subchannel_list_destroy");
} }
gpr_free(subchannel_list->subchannels); gpr_free(subchannel_list->subchannels);
gpr_free(subchannel_list); gpr_free(subchannel_list);
@ -200,8 +196,7 @@ void grpc_lb_subchannel_list_ref(grpc_lb_subchannel_list* subchannel_list,
} }
} }
void grpc_lb_subchannel_list_unref(grpc_exec_ctx* exec_ctx, void grpc_lb_subchannel_list_unref(grpc_lb_subchannel_list* subchannel_list,
grpc_lb_subchannel_list* subchannel_list,
const char* reason) { const char* reason) {
const bool done = gpr_unref(&subchannel_list->refcount); const bool done = gpr_unref(&subchannel_list->refcount);
if (subchannel_list->tracer->enabled()) { if (subchannel_list->tracer->enabled()) {
@ -212,7 +207,7 @@ void grpc_lb_subchannel_list_unref(grpc_exec_ctx* exec_ctx,
reason); reason);
} }
if (done) { if (done) {
subchannel_list_destroy(exec_ctx, subchannel_list); subchannel_list_destroy(subchannel_list);
} }
} }
@ -223,14 +218,13 @@ void grpc_lb_subchannel_list_ref_for_connectivity_watch(
} }
void grpc_lb_subchannel_list_unref_for_connectivity_watch( void grpc_lb_subchannel_list_unref_for_connectivity_watch(
grpc_exec_ctx* exec_ctx, grpc_lb_subchannel_list* subchannel_list, grpc_lb_subchannel_list* subchannel_list, const char* reason) {
const char* reason) { GRPC_LB_POLICY_WEAK_UNREF(subchannel_list->policy, reason);
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, subchannel_list->policy, reason); grpc_lb_subchannel_list_unref(subchannel_list, reason);
grpc_lb_subchannel_list_unref(exec_ctx, subchannel_list, reason);
} }
static void subchannel_data_cancel_connectivity_watch( static void subchannel_data_cancel_connectivity_watch(
grpc_exec_ctx* exec_ctx, grpc_lb_subchannel_data* sd, const char* reason) { grpc_lb_subchannel_data* sd, const char* reason) {
if (sd->subchannel_list->tracer->enabled()) { if (sd->subchannel_list->tracer->enabled()) {
gpr_log(GPR_DEBUG, gpr_log(GPR_DEBUG,
"[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
@ -240,14 +234,12 @@ static void subchannel_data_cancel_connectivity_watch(
(size_t)(sd - sd->subchannel_list->subchannels), (size_t)(sd - sd->subchannel_list->subchannels),
sd->subchannel_list->num_subchannels, sd->subchannel, reason); sd->subchannel_list->num_subchannels, sd->subchannel, reason);
} }
grpc_subchannel_notify_on_state_change(exec_ctx, sd->subchannel, nullptr, grpc_subchannel_notify_on_state_change(sd->subchannel, nullptr, nullptr,
nullptr,
&sd->connectivity_changed_closure); &sd->connectivity_changed_closure);
} }
void grpc_lb_subchannel_list_shutdown_and_unref( void grpc_lb_subchannel_list_shutdown_and_unref(
grpc_exec_ctx* exec_ctx, grpc_lb_subchannel_list* subchannel_list, grpc_lb_subchannel_list* subchannel_list, const char* reason) {
const char* reason) {
if (subchannel_list->tracer->enabled()) { if (subchannel_list->tracer->enabled()) {
gpr_log(GPR_DEBUG, "[%s %p] Shutting down subchannel_list %p (%s)", gpr_log(GPR_DEBUG, "[%s %p] Shutting down subchannel_list %p (%s)",
subchannel_list->tracer->name(), subchannel_list->policy, subchannel_list->tracer->name(), subchannel_list->policy,
@ -261,10 +253,10 @@ void grpc_lb_subchannel_list_shutdown_and_unref(
// the callback is responsible for unreffing the subchannel. // the callback is responsible for unreffing the subchannel.
// Otherwise, unref the subchannel directly. // Otherwise, unref the subchannel directly.
if (sd->connectivity_notification_pending) { if (sd->connectivity_notification_pending) {
subchannel_data_cancel_connectivity_watch(exec_ctx, sd, reason); subchannel_data_cancel_connectivity_watch(sd, reason);
} else if (sd->subchannel != nullptr) { } else if (sd->subchannel != nullptr) {
grpc_lb_subchannel_data_unref_subchannel(exec_ctx, sd, reason); grpc_lb_subchannel_data_unref_subchannel(sd, reason);
} }
} }
grpc_lb_subchannel_list_unref(exec_ctx, subchannel_list, reason); grpc_lb_subchannel_list_unref(subchannel_list, reason);
} }

@ -65,8 +65,7 @@ typedef struct {
} grpc_lb_subchannel_data; } grpc_lb_subchannel_data;
/// Unrefs the subchannel contained in sd. /// Unrefs the subchannel contained in sd.
void grpc_lb_subchannel_data_unref_subchannel(grpc_exec_ctx* exec_ctx, void grpc_lb_subchannel_data_unref_subchannel(grpc_lb_subchannel_data* sd,
grpc_lb_subchannel_data* sd,
const char* reason); const char* reason);
/// Starts watching the connectivity state of the subchannel. /// Starts watching the connectivity state of the subchannel.
@ -74,11 +73,11 @@ void grpc_lb_subchannel_data_unref_subchannel(grpc_exec_ctx* exec_ctx,
/// grpc_lb_subchannel_data_stop_connectivity_watch() or again call /// grpc_lb_subchannel_data_stop_connectivity_watch() or again call
/// grpc_lb_subchannel_data_start_connectivity_watch(). /// grpc_lb_subchannel_data_start_connectivity_watch().
void grpc_lb_subchannel_data_start_connectivity_watch( void grpc_lb_subchannel_data_start_connectivity_watch(
grpc_exec_ctx* exec_ctx, grpc_lb_subchannel_data* sd); grpc_lb_subchannel_data* sd);
/// Stops watching the connectivity state of the subchannel. /// Stops watching the connectivity state of the subchannel.
void grpc_lb_subchannel_data_stop_connectivity_watch( void grpc_lb_subchannel_data_stop_connectivity_watch(
grpc_exec_ctx* exec_ctx, grpc_lb_subchannel_data* sd); grpc_lb_subchannel_data* sd);
struct grpc_lb_subchannel_list { struct grpc_lb_subchannel_list {
/** backpointer to owning policy */ /** backpointer to owning policy */
@ -117,15 +116,14 @@ struct grpc_lb_subchannel_list {
}; };
grpc_lb_subchannel_list* grpc_lb_subchannel_list_create( grpc_lb_subchannel_list* grpc_lb_subchannel_list_create(
grpc_exec_ctx* exec_ctx, grpc_lb_policy* p, grpc_core::TraceFlag* tracer, grpc_lb_policy* p, grpc_core::TraceFlag* tracer,
const grpc_lb_addresses* addresses, const grpc_lb_policy_args* args, const grpc_lb_addresses* addresses, const grpc_lb_policy_args* args,
grpc_iomgr_cb_func connectivity_changed_cb); grpc_iomgr_cb_func connectivity_changed_cb);
void grpc_lb_subchannel_list_ref(grpc_lb_subchannel_list* subchannel_list, void grpc_lb_subchannel_list_ref(grpc_lb_subchannel_list* subchannel_list,
const char* reason); const char* reason);
void grpc_lb_subchannel_list_unref(grpc_exec_ctx* exec_ctx, void grpc_lb_subchannel_list_unref(grpc_lb_subchannel_list* subchannel_list,
grpc_lb_subchannel_list* subchannel_list,
const char* reason); const char* reason);
/// Takes and releases refs needed for a connectivity notification. /// Takes and releases refs needed for a connectivity notification.
@ -133,13 +131,11 @@ void grpc_lb_subchannel_list_unref(grpc_exec_ctx* exec_ctx,
void grpc_lb_subchannel_list_ref_for_connectivity_watch( void grpc_lb_subchannel_list_ref_for_connectivity_watch(
grpc_lb_subchannel_list* subchannel_list, const char* reason); grpc_lb_subchannel_list* subchannel_list, const char* reason);
void grpc_lb_subchannel_list_unref_for_connectivity_watch( void grpc_lb_subchannel_list_unref_for_connectivity_watch(
grpc_exec_ctx* exec_ctx, grpc_lb_subchannel_list* subchannel_list, grpc_lb_subchannel_list* subchannel_list, const char* reason);
const char* reason);
/// Mark subchannel_list as discarded. Unsubscribes all its subchannels. The /// Mark subchannel_list as discarded. Unsubscribes all its subchannels. The
/// connectivity state notification callback will ultimately unref it. /// connectivity state notification callback will ultimately unref it.
void grpc_lb_subchannel_list_shutdown_and_unref( void grpc_lb_subchannel_list_shutdown_and_unref(
grpc_exec_ctx* exec_ctx, grpc_lb_subchannel_list* subchannel_list, grpc_lb_subchannel_list* subchannel_list, const char* reason);
const char* reason);
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_SUBCHANNEL_LIST_H */ #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_SUBCHANNEL_LIST_H */

@ -112,13 +112,11 @@ int grpc_lb_addresses_cmp(const grpc_lb_addresses* addresses1,
return 0; return 0;
} }
void grpc_lb_addresses_destroy(grpc_exec_ctx* exec_ctx, void grpc_lb_addresses_destroy(grpc_lb_addresses* addresses) {
grpc_lb_addresses* addresses) {
for (size_t i = 0; i < addresses->num_addresses; ++i) { for (size_t i = 0; i < addresses->num_addresses; ++i) {
gpr_free(addresses->addresses[i].balancer_name); gpr_free(addresses->addresses[i].balancer_name);
if (addresses->addresses[i].user_data != nullptr) { if (addresses->addresses[i].user_data != nullptr) {
addresses->user_data_vtable->destroy(exec_ctx, addresses->user_data_vtable->destroy(addresses->addresses[i].user_data);
addresses->addresses[i].user_data);
} }
} }
gpr_free(addresses->addresses); gpr_free(addresses->addresses);
@ -128,8 +126,8 @@ void grpc_lb_addresses_destroy(grpc_exec_ctx* exec_ctx,
static void* lb_addresses_copy(void* addresses) { static void* lb_addresses_copy(void* addresses) {
return grpc_lb_addresses_copy((grpc_lb_addresses*)addresses); return grpc_lb_addresses_copy((grpc_lb_addresses*)addresses);
} }
static void lb_addresses_destroy(grpc_exec_ctx* exec_ctx, void* addresses) { static void lb_addresses_destroy(void* addresses) {
grpc_lb_addresses_destroy(exec_ctx, (grpc_lb_addresses*)addresses); grpc_lb_addresses_destroy((grpc_lb_addresses*)addresses);
} }
static int lb_addresses_cmp(void* addresses1, void* addresses2) { static int lb_addresses_cmp(void* addresses1, void* addresses2) {
return grpc_lb_addresses_cmp((grpc_lb_addresses*)addresses1, return grpc_lb_addresses_cmp((grpc_lb_addresses*)addresses1,
@ -162,8 +160,7 @@ void grpc_lb_policy_factory_unref(grpc_lb_policy_factory* factory) {
} }
grpc_lb_policy* grpc_lb_policy_factory_create_lb_policy( grpc_lb_policy* grpc_lb_policy_factory_create_lb_policy(
grpc_exec_ctx* exec_ctx, grpc_lb_policy_factory* factory, grpc_lb_policy_factory* factory, grpc_lb_policy_args* args) {
grpc_lb_policy_args* args) {
if (factory == nullptr) return nullptr; if (factory == nullptr) return nullptr;
return factory->vtable->create_lb_policy(exec_ctx, factory, args); return factory->vtable->create_lb_policy(factory, args);
} }

@ -50,7 +50,7 @@ typedef struct grpc_lb_address {
typedef struct grpc_lb_user_data_vtable { typedef struct grpc_lb_user_data_vtable {
void* (*copy)(void*); void* (*copy)(void*);
void (*destroy)(grpc_exec_ctx* exec_ctx, void*); void (*destroy)(void*);
int (*cmp)(void*, void*); int (*cmp)(void*, void*);
} grpc_lb_user_data_vtable; } grpc_lb_user_data_vtable;
@ -91,8 +91,7 @@ int grpc_lb_addresses_cmp(const grpc_lb_addresses* addresses1,
const grpc_lb_addresses* addresses2); const grpc_lb_addresses* addresses2);
/** Destroys \a addresses. */ /** Destroys \a addresses. */
void grpc_lb_addresses_destroy(grpc_exec_ctx* exec_ctx, void grpc_lb_addresses_destroy(grpc_lb_addresses* addresses);
grpc_lb_addresses* addresses);
/** Returns a channel arg containing \a addresses. */ /** Returns a channel arg containing \a addresses. */
grpc_arg grpc_lb_addresses_create_channel_arg( grpc_arg grpc_lb_addresses_create_channel_arg(
@ -114,8 +113,7 @@ struct grpc_lb_policy_factory_vtable {
void (*unref)(grpc_lb_policy_factory* factory); void (*unref)(grpc_lb_policy_factory* factory);
/** Implementation of grpc_lb_policy_factory_create_lb_policy */ /** Implementation of grpc_lb_policy_factory_create_lb_policy */
grpc_lb_policy* (*create_lb_policy)(grpc_exec_ctx* exec_ctx, grpc_lb_policy* (*create_lb_policy)(grpc_lb_policy_factory* factory,
grpc_lb_policy_factory* factory,
grpc_lb_policy_args* args); grpc_lb_policy_args* args);
/** Name for the LB policy this factory implements */ /** Name for the LB policy this factory implements */
@ -127,7 +125,6 @@ void grpc_lb_policy_factory_unref(grpc_lb_policy_factory* factory);
/** Create a lb_policy instance. */ /** Create a lb_policy instance. */
grpc_lb_policy* grpc_lb_policy_factory_create_lb_policy( grpc_lb_policy* grpc_lb_policy_factory_create_lb_policy(
grpc_exec_ctx* exec_ctx, grpc_lb_policy_factory* factory, grpc_lb_policy_factory* factory, grpc_lb_policy_args* args);
grpc_lb_policy_args* args);
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_FACTORY_H */ #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_FACTORY_H */

@ -61,10 +61,10 @@ static grpc_lb_policy_factory* lookup_factory(const char* name) {
return nullptr; return nullptr;
} }
grpc_lb_policy* grpc_lb_policy_create(grpc_exec_ctx* exec_ctx, const char* name, grpc_lb_policy* grpc_lb_policy_create(const char* name,
grpc_lb_policy_args* args) { grpc_lb_policy_args* args) {
grpc_lb_policy_factory* factory = lookup_factory(name); grpc_lb_policy_factory* factory = lookup_factory(name);
grpc_lb_policy* lb_policy = grpc_lb_policy* lb_policy =
grpc_lb_policy_factory_create_lb_policy(exec_ctx, factory, args); grpc_lb_policy_factory_create_lb_policy(factory, args);
return lb_policy; return lb_policy;
} }

@ -34,7 +34,7 @@ void grpc_register_lb_policy(grpc_lb_policy_factory* factory);
* *
* If \a name is NULL, the default factory from \a grpc_lb_policy_registry_init * If \a name is NULL, the default factory from \a grpc_lb_policy_registry_init
* will be returned. */ * will be returned. */
grpc_lb_policy* grpc_lb_policy_create(grpc_exec_ctx* exec_ctx, const char* name, grpc_lb_policy* grpc_lb_policy_create(const char* name,
grpc_lb_policy_args* args); grpc_lb_policy_args* args);
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_REGISTRY_H */ #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_REGISTRY_H */

@ -23,24 +23,22 @@ void grpc_proxy_mapper_init(const grpc_proxy_mapper_vtable* vtable,
mapper->vtable = vtable; mapper->vtable = vtable;
} }
bool grpc_proxy_mapper_map_name(grpc_exec_ctx* exec_ctx, bool grpc_proxy_mapper_map_name(grpc_proxy_mapper* mapper,
grpc_proxy_mapper* mapper,
const char* server_uri, const char* server_uri,
const grpc_channel_args* args, const grpc_channel_args* args,
char** name_to_resolve, char** name_to_resolve,
grpc_channel_args** new_args) { grpc_channel_args** new_args) {
return mapper->vtable->map_name(exec_ctx, mapper, server_uri, args, return mapper->vtable->map_name(mapper, server_uri, args, name_to_resolve,
name_to_resolve, new_args); new_args);
} }
bool grpc_proxy_mapper_map_address(grpc_exec_ctx* exec_ctx, bool grpc_proxy_mapper_map_address(grpc_proxy_mapper* mapper,
grpc_proxy_mapper* mapper,
const grpc_resolved_address* address, const grpc_resolved_address* address,
const grpc_channel_args* args, const grpc_channel_args* args,
grpc_resolved_address** new_address, grpc_resolved_address** new_address,
grpc_channel_args** new_args) { grpc_channel_args** new_args) {
return mapper->vtable->map_address(exec_ctx, mapper, address, args, return mapper->vtable->map_address(mapper, address, args, new_address,
new_address, new_args); new_args);
} }
void grpc_proxy_mapper_destroy(grpc_proxy_mapper* mapper) { void grpc_proxy_mapper_destroy(grpc_proxy_mapper* mapper) {

@ -32,14 +32,14 @@ typedef struct {
/// If no proxy is needed, returns false. /// If no proxy is needed, returns false.
/// Otherwise, sets \a name_to_resolve, optionally sets \a new_args, /// Otherwise, sets \a name_to_resolve, optionally sets \a new_args,
/// and returns true. /// and returns true.
bool (*map_name)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper, bool (*map_name)(grpc_proxy_mapper* mapper, const char* server_uri,
const char* server_uri, const grpc_channel_args* args, const grpc_channel_args* args, char** name_to_resolve,
char** name_to_resolve, grpc_channel_args** new_args); grpc_channel_args** new_args);
/// Determines the proxy address to use to contact \a address. /// Determines the proxy address to use to contact \a address.
/// If no proxy is needed, returns false. /// If no proxy is needed, returns false.
/// Otherwise, sets \a new_address, optionally sets \a new_args, and /// Otherwise, sets \a new_address, optionally sets \a new_args, and
/// returns true. /// returns true.
bool (*map_address)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper, bool (*map_address)(grpc_proxy_mapper* mapper,
const grpc_resolved_address* address, const grpc_resolved_address* address,
const grpc_channel_args* args, const grpc_channel_args* args,
grpc_resolved_address** new_address, grpc_resolved_address** new_address,
@ -55,15 +55,13 @@ struct grpc_proxy_mapper {
void grpc_proxy_mapper_init(const grpc_proxy_mapper_vtable* vtable, void grpc_proxy_mapper_init(const grpc_proxy_mapper_vtable* vtable,
grpc_proxy_mapper* mapper); grpc_proxy_mapper* mapper);
bool grpc_proxy_mapper_map_name(grpc_exec_ctx* exec_ctx, bool grpc_proxy_mapper_map_name(grpc_proxy_mapper* mapper,
grpc_proxy_mapper* mapper,
const char* server_uri, const char* server_uri,
const grpc_channel_args* args, const grpc_channel_args* args,
char** name_to_resolve, char** name_to_resolve,
grpc_channel_args** new_args); grpc_channel_args** new_args);
bool grpc_proxy_mapper_map_address(grpc_exec_ctx* exec_ctx, bool grpc_proxy_mapper_map_address(grpc_proxy_mapper* mapper,
grpc_proxy_mapper* mapper,
const grpc_resolved_address* address, const grpc_resolved_address* address,
const grpc_channel_args* args, const grpc_channel_args* args,
grpc_resolved_address** new_address, grpc_resolved_address** new_address,

@ -46,14 +46,13 @@ static void grpc_proxy_mapper_list_register(grpc_proxy_mapper_list* list,
++list->num_mappers; ++list->num_mappers;
} }
static bool grpc_proxy_mapper_list_map_name(grpc_exec_ctx* exec_ctx, static bool grpc_proxy_mapper_list_map_name(grpc_proxy_mapper_list* list,
grpc_proxy_mapper_list* list,
const char* server_uri, const char* server_uri,
const grpc_channel_args* args, const grpc_channel_args* args,
char** name_to_resolve, char** name_to_resolve,
grpc_channel_args** new_args) { grpc_channel_args** new_args) {
for (size_t i = 0; i < list->num_mappers; ++i) { for (size_t i = 0; i < list->num_mappers; ++i) {
if (grpc_proxy_mapper_map_name(exec_ctx, list->list[i], server_uri, args, if (grpc_proxy_mapper_map_name(list->list[i], server_uri, args,
name_to_resolve, new_args)) { name_to_resolve, new_args)) {
return true; return true;
} }
@ -62,12 +61,12 @@ static bool grpc_proxy_mapper_list_map_name(grpc_exec_ctx* exec_ctx,
} }
static bool grpc_proxy_mapper_list_map_address( static bool grpc_proxy_mapper_list_map_address(
grpc_exec_ctx* exec_ctx, grpc_proxy_mapper_list* list, grpc_proxy_mapper_list* list, const grpc_resolved_address* address,
const grpc_resolved_address* address, const grpc_channel_args* args, const grpc_channel_args* args, grpc_resolved_address** new_address,
grpc_resolved_address** new_address, grpc_channel_args** new_args) { grpc_channel_args** new_args) {
for (size_t i = 0; i < list->num_mappers; ++i) { for (size_t i = 0; i < list->num_mappers; ++i) {
if (grpc_proxy_mapper_map_address(exec_ctx, list->list[i], address, args, if (grpc_proxy_mapper_map_address(list->list[i], address, args, new_address,
new_address, new_args)) { new_args)) {
return true; return true;
} }
} }
@ -105,20 +104,17 @@ void grpc_proxy_mapper_register(bool at_start, grpc_proxy_mapper* mapper) {
grpc_proxy_mapper_list_register(&g_proxy_mapper_list, at_start, mapper); grpc_proxy_mapper_list_register(&g_proxy_mapper_list, at_start, mapper);
} }
bool grpc_proxy_mappers_map_name(grpc_exec_ctx* exec_ctx, bool grpc_proxy_mappers_map_name(const char* server_uri,
const char* server_uri,
const grpc_channel_args* args, const grpc_channel_args* args,
char** name_to_resolve, char** name_to_resolve,
grpc_channel_args** new_args) { grpc_channel_args** new_args) {
return grpc_proxy_mapper_list_map_name(exec_ctx, &g_proxy_mapper_list, return grpc_proxy_mapper_list_map_name(&g_proxy_mapper_list, server_uri, args,
server_uri, args, name_to_resolve, name_to_resolve, new_args);
new_args);
} }
bool grpc_proxy_mappers_map_address(grpc_exec_ctx* exec_ctx, bool grpc_proxy_mappers_map_address(const grpc_resolved_address* address,
const grpc_resolved_address* address,
const grpc_channel_args* args, const grpc_channel_args* args,
grpc_resolved_address** new_address, grpc_resolved_address** new_address,
grpc_channel_args** new_args) { grpc_channel_args** new_args) {
return grpc_proxy_mapper_list_map_address( return grpc_proxy_mapper_list_map_address(&g_proxy_mapper_list, address, args,
exec_ctx, &g_proxy_mapper_list, address, args, new_address, new_args); new_address, new_args);
} }

@ -29,14 +29,12 @@ void grpc_proxy_mapper_registry_shutdown();
/// the list. Otherwise, it will be added to the end. /// the list. Otherwise, it will be added to the end.
void grpc_proxy_mapper_register(bool at_start, grpc_proxy_mapper* mapper); void grpc_proxy_mapper_register(bool at_start, grpc_proxy_mapper* mapper);
bool grpc_proxy_mappers_map_name(grpc_exec_ctx* exec_ctx, bool grpc_proxy_mappers_map_name(const char* server_uri,
const char* server_uri,
const grpc_channel_args* args, const grpc_channel_args* args,
char** name_to_resolve, char** name_to_resolve,
grpc_channel_args** new_args); grpc_channel_args** new_args);
bool grpc_proxy_mappers_map_address(grpc_exec_ctx* exec_ctx, bool grpc_proxy_mappers_map_address(const grpc_resolved_address* address,
const grpc_resolved_address* address,
const grpc_channel_args* args, const grpc_channel_args* args,
grpc_resolved_address** new_address, grpc_resolved_address** new_address,
grpc_channel_args** new_args); grpc_channel_args** new_args);

@ -46,8 +46,8 @@ void grpc_resolver_ref(grpc_resolver* resolver) {
} }
#ifndef NDEBUG #ifndef NDEBUG
void grpc_resolver_unref(grpc_exec_ctx* exec_ctx, grpc_resolver* resolver, void grpc_resolver_unref(grpc_resolver* resolver, const char* file, int line,
const char* file, int line, const char* reason) { const char* reason) {
if (grpc_trace_resolver_refcount.enabled()) { if (grpc_trace_resolver_refcount.enabled()) {
gpr_atm old_refs = gpr_atm_no_barrier_load(&resolver->refs.count); gpr_atm old_refs = gpr_atm_no_barrier_load(&resolver->refs.count);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
@ -55,27 +55,25 @@ void grpc_resolver_unref(grpc_exec_ctx* exec_ctx, grpc_resolver* resolver,
old_refs, old_refs - 1, reason); old_refs, old_refs - 1, reason);
} }
#else #else
void grpc_resolver_unref(grpc_exec_ctx* exec_ctx, grpc_resolver* resolver) { void grpc_resolver_unref(grpc_resolver* resolver) {
#endif #endif
if (gpr_unref(&resolver->refs)) { if (gpr_unref(&resolver->refs)) {
grpc_combiner* combiner = resolver->combiner; grpc_combiner* combiner = resolver->combiner;
resolver->vtable->destroy(exec_ctx, resolver); resolver->vtable->destroy(resolver);
GRPC_COMBINER_UNREF(exec_ctx, combiner, "resolver"); GRPC_COMBINER_UNREF(combiner, "resolver");
} }
} }
void grpc_resolver_shutdown_locked(grpc_exec_ctx* exec_ctx, void grpc_resolver_shutdown_locked(grpc_resolver* resolver) {
grpc_resolver* resolver) { resolver->vtable->shutdown_locked(resolver);
resolver->vtable->shutdown_locked(exec_ctx, resolver);
} }
void grpc_resolver_channel_saw_error_locked(grpc_exec_ctx* exec_ctx, void grpc_resolver_channel_saw_error_locked(grpc_resolver* resolver) {
grpc_resolver* resolver) { resolver->vtable->channel_saw_error_locked(resolver);
resolver->vtable->channel_saw_error_locked(exec_ctx, resolver);
} }
void grpc_resolver_next_locked(grpc_exec_ctx* exec_ctx, grpc_resolver* resolver, void grpc_resolver_next_locked(grpc_resolver* resolver,
grpc_channel_args** result, grpc_channel_args** result,
grpc_closure* on_complete) { grpc_closure* on_complete) {
resolver->vtable->next_locked(exec_ctx, resolver, result, on_complete); resolver->vtable->next_locked(resolver, result, on_complete);
} }

@ -35,43 +35,40 @@ struct grpc_resolver {
}; };
struct grpc_resolver_vtable { struct grpc_resolver_vtable {
void (*destroy)(grpc_exec_ctx* exec_ctx, grpc_resolver* resolver); void (*destroy)(grpc_resolver* resolver);
void (*shutdown_locked)(grpc_exec_ctx* exec_ctx, grpc_resolver* resolver); void (*shutdown_locked)(grpc_resolver* resolver);
void (*channel_saw_error_locked)(grpc_exec_ctx* exec_ctx, void (*channel_saw_error_locked)(grpc_resolver* resolver);
grpc_resolver* resolver); void (*next_locked)(grpc_resolver* resolver, grpc_channel_args** result,
void (*next_locked)(grpc_exec_ctx* exec_ctx, grpc_resolver* resolver, grpc_closure* on_complete);
grpc_channel_args** result, grpc_closure* on_complete);
}; };
#ifndef NDEBUG #ifndef NDEBUG
#define GRPC_RESOLVER_REF(p, r) grpc_resolver_ref((p), __FILE__, __LINE__, (r)) #define GRPC_RESOLVER_REF(p, r) grpc_resolver_ref((p), __FILE__, __LINE__, (r))
#define GRPC_RESOLVER_UNREF(e, p, r) \ #define GRPC_RESOLVER_UNREF(p, r) \
grpc_resolver_unref((e), (p), __FILE__, __LINE__, (r)) grpc_resolver_unref((p), __FILE__, __LINE__, (r))
void grpc_resolver_ref(grpc_resolver* policy, const char* file, int line, void grpc_resolver_ref(grpc_resolver* policy, const char* file, int line,
const char* reason); const char* reason);
void grpc_resolver_unref(grpc_exec_ctx* exec_ctx, grpc_resolver* policy, void grpc_resolver_unref(grpc_resolver* policy, const char* file, int line,
const char* file, int line, const char* reason); const char* reason);
#else #else
#define GRPC_RESOLVER_REF(p, r) grpc_resolver_ref((p)) #define GRPC_RESOLVER_REF(p, r) grpc_resolver_ref((p))
#define GRPC_RESOLVER_UNREF(e, p, r) grpc_resolver_unref((e), (p)) #define GRPC_RESOLVER_UNREF(p, r) grpc_resolver_unref((p))
void grpc_resolver_ref(grpc_resolver* policy); void grpc_resolver_ref(grpc_resolver* policy);
void grpc_resolver_unref(grpc_exec_ctx* exec_ctx, grpc_resolver* policy); void grpc_resolver_unref(grpc_resolver* policy);
#endif #endif
void grpc_resolver_init(grpc_resolver* resolver, void grpc_resolver_init(grpc_resolver* resolver,
const grpc_resolver_vtable* vtable, const grpc_resolver_vtable* vtable,
grpc_combiner* combiner); grpc_combiner* combiner);
void grpc_resolver_shutdown_locked(grpc_exec_ctx* exec_ctx, void grpc_resolver_shutdown_locked(grpc_resolver* resolver);
grpc_resolver* resolver);
/** Notification that the channel has seen an error on some address. /** Notification that the channel has seen an error on some address.
Can be used as a hint that re-resolution is desirable soon. Can be used as a hint that re-resolution is desirable soon.
Must be called from the combiner passed as a resolver_arg at construction Must be called from the combiner passed as a resolver_arg at construction
time.*/ time.*/
void grpc_resolver_channel_saw_error_locked(grpc_exec_ctx* exec_ctx, void grpc_resolver_channel_saw_error_locked(grpc_resolver* resolver);
grpc_resolver* resolver);
/** Get the next result from the resolver. Expected to set \a *result with /** Get the next result from the resolver. Expected to set \a *result with
new channel args and then schedule \a on_complete for execution. new channel args and then schedule \a on_complete for execution.
@ -81,7 +78,7 @@ void grpc_resolver_channel_saw_error_locked(grpc_exec_ctx* exec_ctx,
Must be called from the combiner passed as a resolver_arg at construction Must be called from the combiner passed as a resolver_arg at construction
time.*/ time.*/
void grpc_resolver_next_locked(grpc_exec_ctx* exec_ctx, grpc_resolver* resolver, void grpc_resolver_next_locked(grpc_resolver* resolver,
grpc_channel_args** result, grpc_channel_args** result,
grpc_closure* on_complete); grpc_closure* on_complete);

@ -97,17 +97,14 @@ typedef struct {
char* service_config_json; char* service_config_json;
} ares_dns_resolver; } ares_dns_resolver;
static void dns_ares_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* r); static void dns_ares_destroy(grpc_resolver* r);
static void dns_ares_start_resolving_locked(grpc_exec_ctx* exec_ctx, static void dns_ares_start_resolving_locked(ares_dns_resolver* r);
ares_dns_resolver* r); static void dns_ares_maybe_finish_next_locked(ares_dns_resolver* r);
static void dns_ares_maybe_finish_next_locked(grpc_exec_ctx* exec_ctx,
ares_dns_resolver* r);
static void dns_ares_shutdown_locked(grpc_exec_ctx* exec_ctx, grpc_resolver* r); static void dns_ares_shutdown_locked(grpc_resolver* r);
static void dns_ares_channel_saw_error_locked(grpc_exec_ctx* exec_ctx, static void dns_ares_channel_saw_error_locked(grpc_resolver* r);
grpc_resolver* r); static void dns_ares_next_locked(grpc_resolver* r,
static void dns_ares_next_locked(grpc_exec_ctx* exec_ctx, grpc_resolver* r,
grpc_channel_args** target_result, grpc_channel_args** target_result,
grpc_closure* on_complete); grpc_closure* on_complete);
@ -115,43 +112,39 @@ static const grpc_resolver_vtable dns_ares_resolver_vtable = {
dns_ares_destroy, dns_ares_shutdown_locked, dns_ares_destroy, dns_ares_shutdown_locked,
dns_ares_channel_saw_error_locked, dns_ares_next_locked}; dns_ares_channel_saw_error_locked, dns_ares_next_locked};
static void dns_ares_shutdown_locked(grpc_exec_ctx* exec_ctx, static void dns_ares_shutdown_locked(grpc_resolver* resolver) {
grpc_resolver* resolver) {
ares_dns_resolver* r = (ares_dns_resolver*)resolver; ares_dns_resolver* r = (ares_dns_resolver*)resolver;
if (r->have_retry_timer) { if (r->have_retry_timer) {
grpc_timer_cancel(exec_ctx, &r->retry_timer); grpc_timer_cancel(&r->retry_timer);
} }
if (r->pending_request != nullptr) { if (r->pending_request != nullptr) {
grpc_cancel_ares_request(exec_ctx, r->pending_request); grpc_cancel_ares_request(r->pending_request);
} }
if (r->next_completion != nullptr) { if (r->next_completion != nullptr) {
*r->target_result = nullptr; *r->target_result = nullptr;
GRPC_CLOSURE_SCHED( GRPC_CLOSURE_SCHED(r->next_completion, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
exec_ctx, r->next_completion, "Resolver Shutdown"));
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver Shutdown"));
r->next_completion = nullptr; r->next_completion = nullptr;
} }
} }
static void dns_ares_channel_saw_error_locked(grpc_exec_ctx* exec_ctx, static void dns_ares_channel_saw_error_locked(grpc_resolver* resolver) {
grpc_resolver* resolver) {
ares_dns_resolver* r = (ares_dns_resolver*)resolver; ares_dns_resolver* r = (ares_dns_resolver*)resolver;
if (!r->resolving) { if (!r->resolving) {
grpc_backoff_reset(&r->backoff_state); grpc_backoff_reset(&r->backoff_state);
dns_ares_start_resolving_locked(exec_ctx, r); dns_ares_start_resolving_locked(r);
} }
} }
static void dns_ares_on_retry_timer_locked(grpc_exec_ctx* exec_ctx, void* arg, static void dns_ares_on_retry_timer_locked(void* arg, grpc_error* error) {
grpc_error* error) {
ares_dns_resolver* r = (ares_dns_resolver*)arg; ares_dns_resolver* r = (ares_dns_resolver*)arg;
r->have_retry_timer = false; r->have_retry_timer = false;
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
if (!r->resolving) { if (!r->resolving) {
dns_ares_start_resolving_locked(exec_ctx, r); dns_ares_start_resolving_locked(r);
} }
} }
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "retry-timer"); GRPC_RESOLVER_UNREF(&r->base, "retry-timer");
} }
static bool value_in_json_array(grpc_json* array, const char* value) { static bool value_in_json_array(grpc_json* array, const char* value) {
@ -226,8 +219,7 @@ static char* choose_service_config(char* service_config_choice_json) {
return service_config; return service_config;
} }
static void dns_ares_on_resolved_locked(grpc_exec_ctx* exec_ctx, void* arg, static void dns_ares_on_resolved_locked(void* arg, grpc_error* error) {
grpc_error* error) {
ares_dns_resolver* r = (ares_dns_resolver*)arg; ares_dns_resolver* r = (ares_dns_resolver*)arg;
grpc_channel_args* result = nullptr; grpc_channel_args* result = nullptr;
GPR_ASSERT(r->resolving); GPR_ASSERT(r->resolving);
@ -268,13 +260,13 @@ static void dns_ares_on_resolved_locked(grpc_exec_ctx* exec_ctx, void* arg,
num_args_to_add); num_args_to_add);
if (service_config != nullptr) grpc_service_config_destroy(service_config); if (service_config != nullptr) grpc_service_config_destroy(service_config);
gpr_free(service_config_string); gpr_free(service_config_string);
grpc_lb_addresses_destroy(exec_ctx, r->lb_addresses); grpc_lb_addresses_destroy(r->lb_addresses);
} else { } else {
const char* msg = grpc_error_string(error); const char* msg = grpc_error_string(error);
gpr_log(GPR_DEBUG, "dns resolution failed: %s", msg); gpr_log(GPR_DEBUG, "dns resolution failed: %s", msg);
grpc_millis next_try = grpc_millis next_try =
grpc_backoff_step(exec_ctx, &r->backoff_state).next_attempt_start_time; grpc_backoff_step(&r->backoff_state).next_attempt_start_time;
grpc_millis timeout = next_try - grpc_exec_ctx_now(exec_ctx); grpc_millis timeout = next_try - grpc_core::ExecCtx::Get()->Now();
gpr_log(GPR_INFO, "dns resolution failed (will retry): %s", gpr_log(GPR_INFO, "dns resolution failed (will retry): %s",
grpc_error_string(error)); grpc_error_string(error));
GPR_ASSERT(!r->have_retry_timer); GPR_ASSERT(!r->have_retry_timer);
@ -285,20 +277,19 @@ static void dns_ares_on_resolved_locked(grpc_exec_ctx* exec_ctx, void* arg,
} else { } else {
gpr_log(GPR_DEBUG, "retrying immediately"); gpr_log(GPR_DEBUG, "retrying immediately");
} }
grpc_timer_init(exec_ctx, &r->retry_timer, next_try, grpc_timer_init(&r->retry_timer, next_try,
&r->dns_ares_on_retry_timer_locked); &r->dns_ares_on_retry_timer_locked);
} }
if (r->resolved_result != nullptr) { if (r->resolved_result != nullptr) {
grpc_channel_args_destroy(exec_ctx, r->resolved_result); grpc_channel_args_destroy(r->resolved_result);
} }
r->resolved_result = result; r->resolved_result = result;
r->resolved_version++; r->resolved_version++;
dns_ares_maybe_finish_next_locked(exec_ctx, r); dns_ares_maybe_finish_next_locked(r);
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving"); GRPC_RESOLVER_UNREF(&r->base, "dns-resolving");
} }
static void dns_ares_next_locked(grpc_exec_ctx* exec_ctx, static void dns_ares_next_locked(grpc_resolver* resolver,
grpc_resolver* resolver,
grpc_channel_args** target_result, grpc_channel_args** target_result,
grpc_closure* on_complete) { grpc_closure* on_complete) {
gpr_log(GPR_DEBUG, "dns_ares_next is called."); gpr_log(GPR_DEBUG, "dns_ares_next is called.");
@ -308,56 +299,53 @@ static void dns_ares_next_locked(grpc_exec_ctx* exec_ctx,
r->target_result = target_result; r->target_result = target_result;
if (r->resolved_version == 0 && !r->resolving) { if (r->resolved_version == 0 && !r->resolving) {
grpc_backoff_reset(&r->backoff_state); grpc_backoff_reset(&r->backoff_state);
dns_ares_start_resolving_locked(exec_ctx, r); dns_ares_start_resolving_locked(r);
} else { } else {
dns_ares_maybe_finish_next_locked(exec_ctx, r); dns_ares_maybe_finish_next_locked(r);
} }
} }
static void dns_ares_start_resolving_locked(grpc_exec_ctx* exec_ctx, static void dns_ares_start_resolving_locked(ares_dns_resolver* r) {
ares_dns_resolver* r) {
GRPC_RESOLVER_REF(&r->base, "dns-resolving"); GRPC_RESOLVER_REF(&r->base, "dns-resolving");
GPR_ASSERT(!r->resolving); GPR_ASSERT(!r->resolving);
r->resolving = true; r->resolving = true;
r->lb_addresses = nullptr; r->lb_addresses = nullptr;
r->service_config_json = nullptr; r->service_config_json = nullptr;
r->pending_request = grpc_dns_lookup_ares( r->pending_request = grpc_dns_lookup_ares(
exec_ctx, r->dns_server, r->name_to_resolve, r->default_port, r->dns_server, r->name_to_resolve, r->default_port, r->interested_parties,
r->interested_parties, &r->dns_ares_on_resolved_locked, &r->lb_addresses, &r->dns_ares_on_resolved_locked, &r->lb_addresses,
true /* check_grpclb */, true /* check_grpclb */,
r->request_service_config ? &r->service_config_json : nullptr); r->request_service_config ? &r->service_config_json : nullptr);
} }
static void dns_ares_maybe_finish_next_locked(grpc_exec_ctx* exec_ctx, static void dns_ares_maybe_finish_next_locked(ares_dns_resolver* r) {
ares_dns_resolver* r) {
if (r->next_completion != nullptr && if (r->next_completion != nullptr &&
r->resolved_version != r->published_version) { r->resolved_version != r->published_version) {
*r->target_result = r->resolved_result == nullptr *r->target_result = r->resolved_result == nullptr
? nullptr ? nullptr
: grpc_channel_args_copy(r->resolved_result); : grpc_channel_args_copy(r->resolved_result);
gpr_log(GPR_DEBUG, "dns_ares_maybe_finish_next_locked"); gpr_log(GPR_DEBUG, "dns_ares_maybe_finish_next_locked");
GRPC_CLOSURE_SCHED(exec_ctx, r->next_completion, GRPC_ERROR_NONE); GRPC_CLOSURE_SCHED(r->next_completion, GRPC_ERROR_NONE);
r->next_completion = nullptr; r->next_completion = nullptr;
r->published_version = r->resolved_version; r->published_version = r->resolved_version;
} }
} }
static void dns_ares_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* gr) { static void dns_ares_destroy(grpc_resolver* gr) {
gpr_log(GPR_DEBUG, "dns_ares_destroy"); gpr_log(GPR_DEBUG, "dns_ares_destroy");
ares_dns_resolver* r = (ares_dns_resolver*)gr; ares_dns_resolver* r = (ares_dns_resolver*)gr;
if (r->resolved_result != nullptr) { if (r->resolved_result != nullptr) {
grpc_channel_args_destroy(exec_ctx, r->resolved_result); grpc_channel_args_destroy(r->resolved_result);
} }
grpc_pollset_set_destroy(exec_ctx, r->interested_parties); grpc_pollset_set_destroy(r->interested_parties);
gpr_free(r->dns_server); gpr_free(r->dns_server);
gpr_free(r->name_to_resolve); gpr_free(r->name_to_resolve);
gpr_free(r->default_port); gpr_free(r->default_port);
grpc_channel_args_destroy(exec_ctx, r->channel_args); grpc_channel_args_destroy(r->channel_args);
gpr_free(r); gpr_free(r);
} }
static grpc_resolver* dns_ares_create(grpc_exec_ctx* exec_ctx, static grpc_resolver* dns_ares_create(grpc_resolver_args* args,
grpc_resolver_args* args,
const char* default_port) { const char* default_port) {
/* Get name from args. */ /* Get name from args. */
const char* path = args->uri->path; const char* path = args->uri->path;
@ -378,8 +366,7 @@ static grpc_resolver* dns_ares_create(grpc_exec_ctx* exec_ctx,
arg, (grpc_integer_options){false, false, true}); arg, (grpc_integer_options){false, false, true});
r->interested_parties = grpc_pollset_set_create(); r->interested_parties = grpc_pollset_set_create();
if (args->pollset_set != nullptr) { if (args->pollset_set != nullptr) {
grpc_pollset_set_add_pollset_set(exec_ctx, r->interested_parties, grpc_pollset_set_add_pollset_set(r->interested_parties, args->pollset_set);
args->pollset_set);
} }
grpc_backoff_init( grpc_backoff_init(
&r->backoff_state, GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS * 1000, &r->backoff_state, GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS * 1000,
@ -404,9 +391,8 @@ static void dns_ares_factory_ref(grpc_resolver_factory* factory) {}
static void dns_ares_factory_unref(grpc_resolver_factory* factory) {} static void dns_ares_factory_unref(grpc_resolver_factory* factory) {}
static grpc_resolver* dns_factory_create_resolver( static grpc_resolver* dns_factory_create_resolver(
grpc_exec_ctx* exec_ctx, grpc_resolver_factory* factory, grpc_resolver_factory* factory, grpc_resolver_args* args) {
grpc_resolver_args* args) { return dns_ares_create(args, "https");
return dns_ares_create(exec_ctx, args, "https");
} }
static char* dns_ares_factory_get_default_host_name( static char* dns_ares_factory_get_default_host_name(

@ -28,8 +28,7 @@ typedef struct grpc_ares_ev_driver grpc_ares_ev_driver;
/* Start \a ev_driver. It will keep working until all IO on its ares_channel is /* Start \a ev_driver. It will keep working until all IO on its ares_channel is
done, or grpc_ares_ev_driver_destroy() is called. It may notify the callbacks done, or grpc_ares_ev_driver_destroy() is called. It may notify the callbacks
bound to its ares_channel when necessary. */ bound to its ares_channel when necessary. */
void grpc_ares_ev_driver_start(grpc_exec_ctx* exec_ctx, void grpc_ares_ev_driver_start(grpc_ares_ev_driver* ev_driver);
grpc_ares_ev_driver* ev_driver);
/* Returns the ares_channel owned by \a ev_driver. To bind a c-ares query to /* Returns the ares_channel owned by \a ev_driver. To bind a c-ares query to
\a ev_driver, use the ares_channel owned by \a ev_driver as the arg of the \a ev_driver, use the ares_channel owned by \a ev_driver as the arg of the
@ -47,8 +46,7 @@ grpc_error* grpc_ares_ev_driver_create(grpc_ares_ev_driver** ev_driver,
void grpc_ares_ev_driver_destroy(grpc_ares_ev_driver* ev_driver); void grpc_ares_ev_driver_destroy(grpc_ares_ev_driver* ev_driver);
/* Shutdown all the grpc_fds used by \a ev_driver */ /* Shutdown all the grpc_fds used by \a ev_driver */
void grpc_ares_ev_driver_shutdown(grpc_exec_ctx* exec_ctx, void grpc_ares_ev_driver_shutdown(grpc_ares_ev_driver* ev_driver);
grpc_ares_ev_driver* ev_driver);
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_EV_DRIVER_H \ #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_EV_DRIVER_H \
*/ */

@ -77,8 +77,7 @@ struct grpc_ares_ev_driver {
bool shutting_down; bool shutting_down;
}; };
static void grpc_ares_notify_on_event_locked(grpc_exec_ctx* exec_ctx, static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver);
grpc_ares_ev_driver* ev_driver);
static grpc_ares_ev_driver* grpc_ares_ev_driver_ref( static grpc_ares_ev_driver* grpc_ares_ev_driver_ref(
grpc_ares_ev_driver* ev_driver) { grpc_ares_ev_driver* ev_driver) {
@ -98,7 +97,7 @@ static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver* ev_driver) {
} }
} }
static void fd_node_destroy(grpc_exec_ctx* exec_ctx, fd_node* fdn) { static void fd_node_destroy(fd_node* fdn) {
gpr_log(GPR_DEBUG, "delete fd: %d", grpc_fd_wrapped_fd(fdn->fd)); gpr_log(GPR_DEBUG, "delete fd: %d", grpc_fd_wrapped_fd(fdn->fd));
GPR_ASSERT(!fdn->readable_registered); GPR_ASSERT(!fdn->readable_registered);
GPR_ASSERT(!fdn->writable_registered); GPR_ASSERT(!fdn->writable_registered);
@ -106,21 +105,20 @@ static void fd_node_destroy(grpc_exec_ctx* exec_ctx, fd_node* fdn) {
/* c-ares library has closed the fd inside grpc_fd. This fd may be picked up /* c-ares library has closed the fd inside grpc_fd. This fd may be picked up
immediately by another thread, and should not be closed by the following immediately by another thread, and should not be closed by the following
grpc_fd_orphan. */ grpc_fd_orphan. */
grpc_fd_orphan(exec_ctx, fdn->fd, nullptr, nullptr, true /* already_closed */, grpc_fd_orphan(fdn->fd, nullptr, nullptr, true /* already_closed */,
"c-ares query finished"); "c-ares query finished");
gpr_free(fdn); gpr_free(fdn);
} }
static void fd_node_shutdown(grpc_exec_ctx* exec_ctx, fd_node* fdn) { static void fd_node_shutdown(fd_node* fdn) {
gpr_mu_lock(&fdn->mu); gpr_mu_lock(&fdn->mu);
fdn->shutting_down = true; fdn->shutting_down = true;
if (!fdn->readable_registered && !fdn->writable_registered) { if (!fdn->readable_registered && !fdn->writable_registered) {
gpr_mu_unlock(&fdn->mu); gpr_mu_unlock(&fdn->mu);
fd_node_destroy(exec_ctx, fdn); fd_node_destroy(fdn);
} else { } else {
grpc_fd_shutdown( grpc_fd_shutdown(
exec_ctx, fdn->fd, fdn->fd, GRPC_ERROR_CREATE_FROM_STATIC_STRING("c-ares fd shutdown"));
GRPC_ERROR_CREATE_FROM_STATIC_STRING("c-ares fd shutdown"));
gpr_mu_unlock(&fdn->mu); gpr_mu_unlock(&fdn->mu);
} }
} }
@ -160,15 +158,13 @@ void grpc_ares_ev_driver_destroy(grpc_ares_ev_driver* ev_driver) {
grpc_ares_ev_driver_unref(ev_driver); grpc_ares_ev_driver_unref(ev_driver);
} }
void grpc_ares_ev_driver_shutdown(grpc_exec_ctx* exec_ctx, void grpc_ares_ev_driver_shutdown(grpc_ares_ev_driver* ev_driver) {
grpc_ares_ev_driver* ev_driver) {
gpr_mu_lock(&ev_driver->mu); gpr_mu_lock(&ev_driver->mu);
ev_driver->shutting_down = true; ev_driver->shutting_down = true;
fd_node* fn = ev_driver->fds; fd_node* fn = ev_driver->fds;
while (fn != nullptr) { while (fn != nullptr) {
grpc_fd_shutdown( grpc_fd_shutdown(fn->fd, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
exec_ctx, fn->fd, "grpc_ares_ev_driver_shutdown"));
GRPC_ERROR_CREATE_FROM_STATIC_STRING("grpc_ares_ev_driver_shutdown"));
fn = fn->next; fn = fn->next;
} }
gpr_mu_unlock(&ev_driver->mu); gpr_mu_unlock(&ev_driver->mu);
@ -199,8 +195,7 @@ static bool grpc_ares_is_fd_still_readable(grpc_ares_ev_driver* ev_driver,
return ioctl(fd, FIONREAD, &bytes_available) == 0 && bytes_available > 0; return ioctl(fd, FIONREAD, &bytes_available) == 0 && bytes_available > 0;
} }
static void on_readable_cb(grpc_exec_ctx* exec_ctx, void* arg, static void on_readable_cb(void* arg, grpc_error* error) {
grpc_error* error) {
fd_node* fdn = (fd_node*)arg; fd_node* fdn = (fd_node*)arg;
grpc_ares_ev_driver* ev_driver = fdn->ev_driver; grpc_ares_ev_driver* ev_driver = fdn->ev_driver;
gpr_mu_lock(&fdn->mu); gpr_mu_lock(&fdn->mu);
@ -208,7 +203,7 @@ static void on_readable_cb(grpc_exec_ctx* exec_ctx, void* arg,
fdn->readable_registered = false; fdn->readable_registered = false;
if (fdn->shutting_down && !fdn->writable_registered) { if (fdn->shutting_down && !fdn->writable_registered) {
gpr_mu_unlock(&fdn->mu); gpr_mu_unlock(&fdn->mu);
fd_node_destroy(exec_ctx, fdn); fd_node_destroy(fdn);
grpc_ares_ev_driver_unref(ev_driver); grpc_ares_ev_driver_unref(ev_driver);
return; return;
} }
@ -229,13 +224,12 @@ static void on_readable_cb(grpc_exec_ctx* exec_ctx, void* arg,
ares_cancel(ev_driver->channel); ares_cancel(ev_driver->channel);
} }
gpr_mu_lock(&ev_driver->mu); gpr_mu_lock(&ev_driver->mu);
grpc_ares_notify_on_event_locked(exec_ctx, ev_driver); grpc_ares_notify_on_event_locked(ev_driver);
gpr_mu_unlock(&ev_driver->mu); gpr_mu_unlock(&ev_driver->mu);
grpc_ares_ev_driver_unref(ev_driver); grpc_ares_ev_driver_unref(ev_driver);
} }
static void on_writable_cb(grpc_exec_ctx* exec_ctx, void* arg, static void on_writable_cb(void* arg, grpc_error* error) {
grpc_error* error) {
fd_node* fdn = (fd_node*)arg; fd_node* fdn = (fd_node*)arg;
grpc_ares_ev_driver* ev_driver = fdn->ev_driver; grpc_ares_ev_driver* ev_driver = fdn->ev_driver;
gpr_mu_lock(&fdn->mu); gpr_mu_lock(&fdn->mu);
@ -243,7 +237,7 @@ static void on_writable_cb(grpc_exec_ctx* exec_ctx, void* arg,
fdn->writable_registered = false; fdn->writable_registered = false;
if (fdn->shutting_down && !fdn->readable_registered) { if (fdn->shutting_down && !fdn->readable_registered) {
gpr_mu_unlock(&fdn->mu); gpr_mu_unlock(&fdn->mu);
fd_node_destroy(exec_ctx, fdn); fd_node_destroy(fdn);
grpc_ares_ev_driver_unref(ev_driver); grpc_ares_ev_driver_unref(ev_driver);
return; return;
} }
@ -262,7 +256,7 @@ static void on_writable_cb(grpc_exec_ctx* exec_ctx, void* arg,
ares_cancel(ev_driver->channel); ares_cancel(ev_driver->channel);
} }
gpr_mu_lock(&ev_driver->mu); gpr_mu_lock(&ev_driver->mu);
grpc_ares_notify_on_event_locked(exec_ctx, ev_driver); grpc_ares_notify_on_event_locked(ev_driver);
gpr_mu_unlock(&ev_driver->mu); gpr_mu_unlock(&ev_driver->mu);
grpc_ares_ev_driver_unref(ev_driver); grpc_ares_ev_driver_unref(ev_driver);
} }
@ -273,8 +267,7 @@ ares_channel* grpc_ares_ev_driver_get_channel(grpc_ares_ev_driver* ev_driver) {
// Get the file descriptors used by the ev_driver's ares channel, register // Get the file descriptors used by the ev_driver's ares channel, register
// driver_closure with these filedescriptors. // driver_closure with these filedescriptors.
static void grpc_ares_notify_on_event_locked(grpc_exec_ctx* exec_ctx, static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver) {
grpc_ares_ev_driver* ev_driver) {
fd_node* new_list = nullptr; fd_node* new_list = nullptr;
if (!ev_driver->shutting_down) { if (!ev_driver->shutting_down) {
ares_socket_t socks[ARES_GETSOCK_MAXNUM]; ares_socket_t socks[ARES_GETSOCK_MAXNUM];
@ -300,7 +293,7 @@ static void grpc_ares_notify_on_event_locked(grpc_exec_ctx* exec_ctx,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&fdn->write_closure, on_writable_cb, fdn, GRPC_CLOSURE_INIT(&fdn->write_closure, on_writable_cb, fdn,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
grpc_pollset_set_add_fd(exec_ctx, ev_driver->pollset_set, fdn->fd); grpc_pollset_set_add_fd(ev_driver->pollset_set, fdn->fd);
gpr_free(fd_name); gpr_free(fd_name);
} }
fdn->next = new_list; fdn->next = new_list;
@ -312,7 +305,7 @@ static void grpc_ares_notify_on_event_locked(grpc_exec_ctx* exec_ctx,
!fdn->readable_registered) { !fdn->readable_registered) {
grpc_ares_ev_driver_ref(ev_driver); grpc_ares_ev_driver_ref(ev_driver);
gpr_log(GPR_DEBUG, "notify read on: %d", grpc_fd_wrapped_fd(fdn->fd)); gpr_log(GPR_DEBUG, "notify read on: %d", grpc_fd_wrapped_fd(fdn->fd));
grpc_fd_notify_on_read(exec_ctx, fdn->fd, &fdn->read_closure); grpc_fd_notify_on_read(fdn->fd, &fdn->read_closure);
fdn->readable_registered = true; fdn->readable_registered = true;
} }
// Register write_closure if the socket is writable and write_closure // Register write_closure if the socket is writable and write_closure
@ -322,7 +315,7 @@ static void grpc_ares_notify_on_event_locked(grpc_exec_ctx* exec_ctx,
gpr_log(GPR_DEBUG, "notify write on: %d", gpr_log(GPR_DEBUG, "notify write on: %d",
grpc_fd_wrapped_fd(fdn->fd)); grpc_fd_wrapped_fd(fdn->fd));
grpc_ares_ev_driver_ref(ev_driver); grpc_ares_ev_driver_ref(ev_driver);
grpc_fd_notify_on_write(exec_ctx, fdn->fd, &fdn->write_closure); grpc_fd_notify_on_write(fdn->fd, &fdn->write_closure);
fdn->writable_registered = true; fdn->writable_registered = true;
} }
gpr_mu_unlock(&fdn->mu); gpr_mu_unlock(&fdn->mu);
@ -335,7 +328,7 @@ static void grpc_ares_notify_on_event_locked(grpc_exec_ctx* exec_ctx,
while (ev_driver->fds != nullptr) { while (ev_driver->fds != nullptr) {
fd_node* cur = ev_driver->fds; fd_node* cur = ev_driver->fds;
ev_driver->fds = ev_driver->fds->next; ev_driver->fds = ev_driver->fds->next;
fd_node_shutdown(exec_ctx, cur); fd_node_shutdown(cur);
} }
ev_driver->fds = new_list; ev_driver->fds = new_list;
// If the ev driver has no working fd, all the tasks are done. // If the ev driver has no working fd, all the tasks are done.
@ -345,12 +338,11 @@ static void grpc_ares_notify_on_event_locked(grpc_exec_ctx* exec_ctx,
} }
} }
void grpc_ares_ev_driver_start(grpc_exec_ctx* exec_ctx, void grpc_ares_ev_driver_start(grpc_ares_ev_driver* ev_driver) {
grpc_ares_ev_driver* ev_driver) {
gpr_mu_lock(&ev_driver->mu); gpr_mu_lock(&ev_driver->mu);
if (!ev_driver->working) { if (!ev_driver->working) {
ev_driver->working = true; ev_driver->working = true;
grpc_ares_notify_on_event_locked(exec_ctx, ev_driver); grpc_ares_notify_on_event_locked(ev_driver);
} }
gpr_mu_unlock(&ev_driver->mu); gpr_mu_unlock(&ev_driver->mu);
} }

@ -96,24 +96,12 @@ static void grpc_ares_request_ref(grpc_ares_request* r) {
gpr_ref(&r->pending_queries); gpr_ref(&r->pending_queries);
} }
static void grpc_ares_request_unref(grpc_exec_ctx* exec_ctx, static void grpc_ares_request_unref(grpc_ares_request* r) {
grpc_ares_request* r) {
/* If there are no pending queries, invoke on_done callback and destroy the /* If there are no pending queries, invoke on_done callback and destroy the
request */ request */
if (gpr_unref(&r->pending_queries)) { if (gpr_unref(&r->pending_queries)) {
/* TODO(zyc): Sort results with RFC6724 before invoking on_done. */ /* TODO(zyc): Sort results with RFC6724 before invoking on_done. */
if (exec_ctx == nullptr) { GRPC_CLOSURE_SCHED(r->on_done, r->error);
/* A new exec_ctx is created here, as the c-ares interface does not
provide one in ares_host_callback. It's safe to schedule on_done with
the newly created exec_ctx, since the caller has been warned not to
acquire locks in on_done. ares_dns_resolver is using combiner to
protect resources needed by on_done. */
grpc_exec_ctx new_exec_ctx = GRPC_EXEC_CTX_INIT;
GRPC_CLOSURE_SCHED(&new_exec_ctx, r->on_done, r->error);
grpc_exec_ctx_finish(&new_exec_ctx);
} else {
GRPC_CLOSURE_SCHED(exec_ctx, r->on_done, r->error);
}
gpr_mu_destroy(&r->mu); gpr_mu_destroy(&r->mu);
grpc_ares_ev_driver_destroy(r->ev_driver); grpc_ares_ev_driver_destroy(r->ev_driver);
gpr_free(r); gpr_free(r);
@ -133,9 +121,8 @@ static grpc_ares_hostbyname_request* create_hostbyname_request(
return hr; return hr;
} }
static void destroy_hostbyname_request(grpc_exec_ctx* exec_ctx, static void destroy_hostbyname_request(grpc_ares_hostbyname_request* hr) {
grpc_ares_hostbyname_request* hr) { grpc_ares_request_unref(hr->parent_request);
grpc_ares_request_unref(exec_ctx, hr->parent_request);
gpr_free(hr->host); gpr_free(hr->host);
gpr_free(hr); gpr_free(hr);
} }
@ -220,13 +207,13 @@ static void on_hostbyname_done_cb(void* arg, int status, int timeouts,
} }
} }
gpr_mu_unlock(&r->mu); gpr_mu_unlock(&r->mu);
destroy_hostbyname_request(nullptr, hr); destroy_hostbyname_request(hr);
} }
static void on_srv_query_done_cb(void* arg, int status, int timeouts, static void on_srv_query_done_cb(void* arg, int status, int timeouts,
unsigned char* abuf, int alen) { unsigned char* abuf, int alen) {
grpc_ares_request* r = (grpc_ares_request*)arg; grpc_ares_request* r = (grpc_ares_request*)arg;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_core::ExecCtx exec_ctx;
gpr_log(GPR_DEBUG, "on_query_srv_done_cb"); gpr_log(GPR_DEBUG, "on_query_srv_done_cb");
if (status == ARES_SUCCESS) { if (status == ARES_SUCCESS) {
gpr_log(GPR_DEBUG, "on_query_srv_done_cb ARES_SUCCESS"); gpr_log(GPR_DEBUG, "on_query_srv_done_cb ARES_SUCCESS");
@ -246,7 +233,7 @@ static void on_srv_query_done_cb(void* arg, int status, int timeouts,
r, srv_it->host, htons(srv_it->port), true /* is_balancer */); r, srv_it->host, htons(srv_it->port), true /* is_balancer */);
ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_cb, ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_cb,
hr); hr);
grpc_ares_ev_driver_start(&exec_ctx, r->ev_driver); grpc_ares_ev_driver_start(r->ev_driver);
} }
} }
if (reply != nullptr) { if (reply != nullptr) {
@ -264,8 +251,7 @@ static void on_srv_query_done_cb(void* arg, int status, int timeouts,
r->error = grpc_error_add_child(error, r->error); r->error = grpc_error_add_child(error, r->error);
} }
} }
grpc_ares_request_unref(&exec_ctx, r); grpc_ares_request_unref(r);
grpc_exec_ctx_finish(&exec_ctx);
} }
static const char g_service_config_attribute_prefix[] = "grpc_config="; static const char g_service_config_attribute_prefix[] = "grpc_config=";
@ -323,14 +309,13 @@ fail:
} }
done: done:
gpr_mu_unlock(&r->mu); gpr_mu_unlock(&r->mu);
grpc_ares_request_unref(nullptr, r); grpc_ares_request_unref(r);
} }
static grpc_ares_request* grpc_dns_lookup_ares_impl( static grpc_ares_request* grpc_dns_lookup_ares_impl(
grpc_exec_ctx* exec_ctx, const char* dns_server, const char* name, const char* dns_server, const char* name, const char* default_port,
const char* default_port, grpc_pollset_set* interested_parties, grpc_pollset_set* interested_parties, grpc_closure* on_done,
grpc_closure* on_done, grpc_lb_addresses** addrs, bool check_grpclb, grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json) {
char** service_config_json) {
grpc_error* error = GRPC_ERROR_NONE; grpc_error* error = GRPC_ERROR_NONE;
grpc_ares_hostbyname_request* hr = nullptr; grpc_ares_hostbyname_request* hr = nullptr;
grpc_ares_request* r = nullptr; grpc_ares_request* r = nullptr;
@ -437,28 +422,28 @@ static grpc_ares_request* grpc_dns_lookup_ares_impl(
gpr_free(config_name); gpr_free(config_name);
} }
/* TODO(zyc): Handle CNAME records here. */ /* TODO(zyc): Handle CNAME records here. */
grpc_ares_ev_driver_start(exec_ctx, r->ev_driver); grpc_ares_ev_driver_start(r->ev_driver);
grpc_ares_request_unref(exec_ctx, r); grpc_ares_request_unref(r);
gpr_free(host); gpr_free(host);
gpr_free(port); gpr_free(port);
return r; return r;
error_cleanup: error_cleanup:
GRPC_CLOSURE_SCHED(exec_ctx, on_done, error); GRPC_CLOSURE_SCHED(on_done, error);
gpr_free(host); gpr_free(host);
gpr_free(port); gpr_free(port);
return nullptr; return nullptr;
} }
grpc_ares_request* (*grpc_dns_lookup_ares)( grpc_ares_request* (*grpc_dns_lookup_ares)(
grpc_exec_ctx* exec_ctx, const char* dns_server, const char* name, const char* dns_server, const char* name, const char* default_port,
const char* default_port, grpc_pollset_set* interested_parties, grpc_pollset_set* interested_parties, grpc_closure* on_done,
grpc_closure* on_done, grpc_lb_addresses** addrs, bool check_grpclb, grpc_lb_addresses** addrs, bool check_grpclb,
char** service_config_json) = grpc_dns_lookup_ares_impl; char** service_config_json) = grpc_dns_lookup_ares_impl;
void grpc_cancel_ares_request(grpc_exec_ctx* exec_ctx, grpc_ares_request* r) { void grpc_cancel_ares_request(grpc_ares_request* r) {
if (grpc_dns_lookup_ares == grpc_dns_lookup_ares_impl) { if (grpc_dns_lookup_ares == grpc_dns_lookup_ares_impl) {
grpc_ares_ev_driver_shutdown(exec_ctx, r->ev_driver); grpc_ares_ev_driver_shutdown(r->ev_driver);
} }
} }
@ -501,8 +486,7 @@ typedef struct grpc_resolve_address_ares_request {
grpc_closure on_dns_lookup_done; grpc_closure on_dns_lookup_done;
} grpc_resolve_address_ares_request; } grpc_resolve_address_ares_request;
static void on_dns_lookup_done_cb(grpc_exec_ctx* exec_ctx, void* arg, static void on_dns_lookup_done_cb(void* arg, grpc_error* error) {
grpc_error* error) {
grpc_resolve_address_ares_request* r = grpc_resolve_address_ares_request* r =
(grpc_resolve_address_ares_request*)arg; (grpc_resolve_address_ares_request*)arg;
grpc_resolved_addresses** resolved_addresses = r->addrs_out; grpc_resolved_addresses** resolved_addresses = r->addrs_out;
@ -520,14 +504,12 @@ static void on_dns_lookup_done_cb(grpc_exec_ctx* exec_ctx, void* arg,
&r->lb_addrs->addresses[i].address, sizeof(grpc_resolved_address)); &r->lb_addrs->addresses[i].address, sizeof(grpc_resolved_address));
} }
} }
GRPC_CLOSURE_SCHED(exec_ctx, r->on_resolve_address_done, GRPC_CLOSURE_SCHED(r->on_resolve_address_done, GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error)); grpc_lb_addresses_destroy(r->lb_addrs);
grpc_lb_addresses_destroy(exec_ctx, r->lb_addrs);
gpr_free(r); gpr_free(r);
} }
static void grpc_resolve_address_ares_impl(grpc_exec_ctx* exec_ctx, static void grpc_resolve_address_ares_impl(const char* name,
const char* name,
const char* default_port, const char* default_port,
grpc_pollset_set* interested_parties, grpc_pollset_set* interested_parties,
grpc_closure* on_done, grpc_closure* on_done,
@ -539,14 +521,14 @@ static void grpc_resolve_address_ares_impl(grpc_exec_ctx* exec_ctx,
r->on_resolve_address_done = on_done; r->on_resolve_address_done = on_done;
GRPC_CLOSURE_INIT(&r->on_dns_lookup_done, on_dns_lookup_done_cb, r, GRPC_CLOSURE_INIT(&r->on_dns_lookup_done, on_dns_lookup_done_cb, r,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
grpc_dns_lookup_ares(exec_ctx, nullptr /* dns_server */, name, default_port, grpc_dns_lookup_ares(nullptr /* dns_server */, name, default_port,
interested_parties, &r->on_dns_lookup_done, &r->lb_addrs, interested_parties, &r->on_dns_lookup_done, &r->lb_addrs,
false /* check_grpclb */, false /* check_grpclb */,
nullptr /* service_config_json */); nullptr /* service_config_json */);
} }
void (*grpc_resolve_address_ares)( void (*grpc_resolve_address_ares)(
grpc_exec_ctx* exec_ctx, const char* name, const char* default_port, const char* name, const char* default_port,
grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_pollset_set* interested_parties, grpc_closure* on_done,
grpc_resolved_addresses** addrs) = grpc_resolve_address_ares_impl; grpc_resolved_addresses** addrs) = grpc_resolve_address_ares_impl;

@ -32,8 +32,7 @@ typedef struct grpc_ares_request grpc_ares_request;
must be called at least once before this function. \a on_done may be must be called at least once before this function. \a on_done may be
called directly in this function without being scheduled with \a exec_ctx, called directly in this function without being scheduled with \a exec_ctx,
so it must not try to acquire locks that are being held by the caller. */ so it must not try to acquire locks that are being held by the caller. */
extern void (*grpc_resolve_address_ares)(grpc_exec_ctx* exec_ctx, extern void (*grpc_resolve_address_ares)(const char* name,
const char* name,
const char* default_port, const char* default_port,
grpc_pollset_set* interested_parties, grpc_pollset_set* interested_parties,
grpc_closure* on_done, grpc_closure* on_done,
@ -47,14 +46,13 @@ extern void (*grpc_resolve_address_ares)(grpc_exec_ctx* exec_ctx,
scheduled with \a exec_ctx, so it must not try to acquire locks that are scheduled with \a exec_ctx, so it must not try to acquire locks that are
being held by the caller. */ being held by the caller. */
extern grpc_ares_request* (*grpc_dns_lookup_ares)( extern grpc_ares_request* (*grpc_dns_lookup_ares)(
grpc_exec_ctx* exec_ctx, const char* dns_server, const char* name, const char* dns_server, const char* name, const char* default_port,
const char* default_port, grpc_pollset_set* interested_parties, grpc_pollset_set* interested_parties, grpc_closure* on_done,
grpc_closure* on_done, grpc_lb_addresses** addresses, bool check_grpclb, grpc_lb_addresses** addresses, bool check_grpclb,
char** service_config_json); char** service_config_json);
/* Cancel the pending grpc_ares_request \a request */ /* Cancel the pending grpc_ares_request \a request */
void grpc_cancel_ares_request(grpc_exec_ctx* exec_ctx, void grpc_cancel_ares_request(grpc_ares_request* request);
grpc_ares_request* request);
/* Initialize gRPC ares wrapper. Must be called at least once before /* Initialize gRPC ares wrapper. Must be called at least once before
grpc_resolve_address_ares(). */ grpc_resolve_address_ares(). */

@ -26,34 +26,32 @@ struct grpc_ares_request {
}; };
static grpc_ares_request* grpc_dns_lookup_ares_impl( static grpc_ares_request* grpc_dns_lookup_ares_impl(
grpc_exec_ctx* exec_ctx, const char* dns_server, const char* name, const char* dns_server, const char* name, const char* default_port,
const char* default_port, grpc_pollset_set* interested_parties, grpc_pollset_set* interested_parties, grpc_closure* on_done,
grpc_closure* on_done, grpc_lb_addresses** addrs, bool check_grpclb, grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json) {
char** service_config_json) {
return NULL; return NULL;
} }
grpc_ares_request* (*grpc_dns_lookup_ares)( grpc_ares_request* (*grpc_dns_lookup_ares)(
grpc_exec_ctx* exec_ctx, const char* dns_server, const char* name, const char* dns_server, const char* name, const char* default_port,
const char* default_port, grpc_pollset_set* interested_parties, grpc_pollset_set* interested_parties, grpc_closure* on_done,
grpc_closure* on_done, grpc_lb_addresses** addrs, bool check_grpclb, grpc_lb_addresses** addrs, bool check_grpclb,
char** service_config_json) = grpc_dns_lookup_ares_impl; char** service_config_json) = grpc_dns_lookup_ares_impl;
void grpc_cancel_ares_request(grpc_exec_ctx* exec_ctx, grpc_ares_request* r) {} void grpc_cancel_ares_request(grpc_ares_request* r) {}
grpc_error* grpc_ares_init(void) { return GRPC_ERROR_NONE; } grpc_error* grpc_ares_init(void) { return GRPC_ERROR_NONE; }
void grpc_ares_cleanup(void) {} void grpc_ares_cleanup(void) {}
static void grpc_resolve_address_ares_impl(grpc_exec_ctx* exec_ctx, static void grpc_resolve_address_ares_impl(const char* name,
const char* name,
const char* default_port, const char* default_port,
grpc_pollset_set* interested_parties, grpc_pollset_set* interested_parties,
grpc_closure* on_done, grpc_closure* on_done,
grpc_resolved_addresses** addrs) {} grpc_resolved_addresses** addrs) {}
void (*grpc_resolve_address_ares)( void (*grpc_resolve_address_ares)(
grpc_exec_ctx* exec_ctx, const char* name, const char* default_port, const char* name, const char* default_port,
grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_pollset_set* interested_parties, grpc_closure* on_done,
grpc_resolved_addresses** addrs) = grpc_resolve_address_ares_impl; grpc_resolved_addresses** addrs) = grpc_resolve_address_ares_impl;

@ -76,49 +76,42 @@ typedef struct {
grpc_resolved_addresses* addresses; grpc_resolved_addresses* addresses;
} dns_resolver; } dns_resolver;
static void dns_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* r); static void dns_destroy(grpc_resolver* r);
static void dns_start_resolving_locked(grpc_exec_ctx* exec_ctx, static void dns_start_resolving_locked(dns_resolver* r);
dns_resolver* r); static void dns_maybe_finish_next_locked(dns_resolver* r);
static void dns_maybe_finish_next_locked(grpc_exec_ctx* exec_ctx,
dns_resolver* r);
static void dns_shutdown_locked(grpc_exec_ctx* exec_ctx, grpc_resolver* r); static void dns_shutdown_locked(grpc_resolver* r);
static void dns_channel_saw_error_locked(grpc_exec_ctx* exec_ctx, static void dns_channel_saw_error_locked(grpc_resolver* r);
grpc_resolver* r); static void dns_next_locked(grpc_resolver* r, grpc_channel_args** target_result,
static void dns_next_locked(grpc_exec_ctx* exec_ctx, grpc_resolver* r,
grpc_channel_args** target_result,
grpc_closure* on_complete); grpc_closure* on_complete);
static const grpc_resolver_vtable dns_resolver_vtable = { static const grpc_resolver_vtable dns_resolver_vtable = {
dns_destroy, dns_shutdown_locked, dns_channel_saw_error_locked, dns_destroy, dns_shutdown_locked, dns_channel_saw_error_locked,
dns_next_locked}; dns_next_locked};
static void dns_shutdown_locked(grpc_exec_ctx* exec_ctx, static void dns_shutdown_locked(grpc_resolver* resolver) {
grpc_resolver* resolver) {
dns_resolver* r = (dns_resolver*)resolver; dns_resolver* r = (dns_resolver*)resolver;
if (r->have_retry_timer) { if (r->have_retry_timer) {
grpc_timer_cancel(exec_ctx, &r->retry_timer); grpc_timer_cancel(&r->retry_timer);
} }
if (r->next_completion != nullptr) { if (r->next_completion != nullptr) {
*r->target_result = nullptr; *r->target_result = nullptr;
GRPC_CLOSURE_SCHED( GRPC_CLOSURE_SCHED(r->next_completion, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
exec_ctx, r->next_completion, "Resolver Shutdown"));
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver Shutdown"));
r->next_completion = nullptr; r->next_completion = nullptr;
} }
} }
static void dns_channel_saw_error_locked(grpc_exec_ctx* exec_ctx, static void dns_channel_saw_error_locked(grpc_resolver* resolver) {
grpc_resolver* resolver) {
dns_resolver* r = (dns_resolver*)resolver; dns_resolver* r = (dns_resolver*)resolver;
if (!r->resolving) { if (!r->resolving) {
grpc_backoff_reset(&r->backoff_state); grpc_backoff_reset(&r->backoff_state);
dns_start_resolving_locked(exec_ctx, r); dns_start_resolving_locked(r);
} }
} }
static void dns_next_locked(grpc_exec_ctx* exec_ctx, grpc_resolver* resolver, static void dns_next_locked(grpc_resolver* resolver,
grpc_channel_args** target_result, grpc_channel_args** target_result,
grpc_closure* on_complete) { grpc_closure* on_complete) {
dns_resolver* r = (dns_resolver*)resolver; dns_resolver* r = (dns_resolver*)resolver;
@ -127,28 +120,26 @@ static void dns_next_locked(grpc_exec_ctx* exec_ctx, grpc_resolver* resolver,
r->target_result = target_result; r->target_result = target_result;
if (r->resolved_version == 0 && !r->resolving) { if (r->resolved_version == 0 && !r->resolving) {
grpc_backoff_reset(&r->backoff_state); grpc_backoff_reset(&r->backoff_state);
dns_start_resolving_locked(exec_ctx, r); dns_start_resolving_locked(r);
} else { } else {
dns_maybe_finish_next_locked(exec_ctx, r); dns_maybe_finish_next_locked(r);
} }
} }
static void dns_on_retry_timer_locked(grpc_exec_ctx* exec_ctx, void* arg, static void dns_on_retry_timer_locked(void* arg, grpc_error* error) {
grpc_error* error) {
dns_resolver* r = (dns_resolver*)arg; dns_resolver* r = (dns_resolver*)arg;
r->have_retry_timer = false; r->have_retry_timer = false;
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
if (!r->resolving) { if (!r->resolving) {
dns_start_resolving_locked(exec_ctx, r); dns_start_resolving_locked(r);
} }
} }
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "retry-timer"); GRPC_RESOLVER_UNREF(&r->base, "retry-timer");
} }
static void dns_on_resolved_locked(grpc_exec_ctx* exec_ctx, void* arg, static void dns_on_resolved_locked(void* arg, grpc_error* error) {
grpc_error* error) {
dns_resolver* r = (dns_resolver*)arg; dns_resolver* r = (dns_resolver*)arg;
grpc_channel_args* result = nullptr; grpc_channel_args* result = nullptr;
GPR_ASSERT(r->resolving); GPR_ASSERT(r->resolving);
@ -168,11 +159,11 @@ static void dns_on_resolved_locked(grpc_exec_ctx* exec_ctx, void* arg,
grpc_arg new_arg = grpc_lb_addresses_create_channel_arg(addresses); grpc_arg new_arg = grpc_lb_addresses_create_channel_arg(addresses);
result = grpc_channel_args_copy_and_add(r->channel_args, &new_arg, 1); result = grpc_channel_args_copy_and_add(r->channel_args, &new_arg, 1);
grpc_resolved_addresses_destroy(r->addresses); grpc_resolved_addresses_destroy(r->addresses);
grpc_lb_addresses_destroy(exec_ctx, addresses); grpc_lb_addresses_destroy(addresses);
} else { } else {
grpc_millis next_try = grpc_millis next_try =
grpc_backoff_step(exec_ctx, &r->backoff_state).next_attempt_start_time; grpc_backoff_step(&r->backoff_state).next_attempt_start_time;
grpc_millis timeout = next_try - grpc_exec_ctx_now(exec_ctx); grpc_millis timeout = next_try - grpc_core::ExecCtx::Get()->Now();
gpr_log(GPR_INFO, "dns resolution failed (will retry): %s", gpr_log(GPR_INFO, "dns resolution failed (will retry): %s",
grpc_error_string(error)); grpc_error_string(error));
GPR_ASSERT(!r->have_retry_timer); GPR_ASSERT(!r->have_retry_timer);
@ -185,59 +176,56 @@ static void dns_on_resolved_locked(grpc_exec_ctx* exec_ctx, void* arg,
} }
GRPC_CLOSURE_INIT(&r->on_retry, dns_on_retry_timer_locked, r, GRPC_CLOSURE_INIT(&r->on_retry, dns_on_retry_timer_locked, r,
grpc_combiner_scheduler(r->base.combiner)); grpc_combiner_scheduler(r->base.combiner));
grpc_timer_init(exec_ctx, &r->retry_timer, next_try, &r->on_retry); grpc_timer_init(&r->retry_timer, next_try, &r->on_retry);
} }
if (r->resolved_result != nullptr) { if (r->resolved_result != nullptr) {
grpc_channel_args_destroy(exec_ctx, r->resolved_result); grpc_channel_args_destroy(r->resolved_result);
} }
r->resolved_result = result; r->resolved_result = result;
r->resolved_version++; r->resolved_version++;
dns_maybe_finish_next_locked(exec_ctx, r); dns_maybe_finish_next_locked(r);
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving"); GRPC_RESOLVER_UNREF(&r->base, "dns-resolving");
} }
static void dns_start_resolving_locked(grpc_exec_ctx* exec_ctx, static void dns_start_resolving_locked(dns_resolver* r) {
dns_resolver* r) {
GRPC_RESOLVER_REF(&r->base, "dns-resolving"); GRPC_RESOLVER_REF(&r->base, "dns-resolving");
GPR_ASSERT(!r->resolving); GPR_ASSERT(!r->resolving);
r->resolving = true; r->resolving = true;
r->addresses = nullptr; r->addresses = nullptr;
grpc_resolve_address( grpc_resolve_address(
exec_ctx, r->name_to_resolve, r->default_port, r->interested_parties, r->name_to_resolve, r->default_port, r->interested_parties,
GRPC_CLOSURE_CREATE(dns_on_resolved_locked, r, GRPC_CLOSURE_CREATE(dns_on_resolved_locked, r,
grpc_combiner_scheduler(r->base.combiner)), grpc_combiner_scheduler(r->base.combiner)),
&r->addresses); &r->addresses);
} }
static void dns_maybe_finish_next_locked(grpc_exec_ctx* exec_ctx, static void dns_maybe_finish_next_locked(dns_resolver* r) {
dns_resolver* r) {
if (r->next_completion != nullptr && if (r->next_completion != nullptr &&
r->resolved_version != r->published_version) { r->resolved_version != r->published_version) {
*r->target_result = r->resolved_result == nullptr *r->target_result = r->resolved_result == nullptr
? nullptr ? nullptr
: grpc_channel_args_copy(r->resolved_result); : grpc_channel_args_copy(r->resolved_result);
GRPC_CLOSURE_SCHED(exec_ctx, r->next_completion, GRPC_ERROR_NONE); GRPC_CLOSURE_SCHED(r->next_completion, GRPC_ERROR_NONE);
r->next_completion = nullptr; r->next_completion = nullptr;
r->published_version = r->resolved_version; r->published_version = r->resolved_version;
} }
} }
static void dns_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* gr) { static void dns_destroy(grpc_resolver* gr) {
dns_resolver* r = (dns_resolver*)gr; dns_resolver* r = (dns_resolver*)gr;
if (r->resolved_result != nullptr) { if (r->resolved_result != nullptr) {
grpc_channel_args_destroy(exec_ctx, r->resolved_result); grpc_channel_args_destroy(r->resolved_result);
} }
grpc_pollset_set_destroy(exec_ctx, r->interested_parties); grpc_pollset_set_destroy(r->interested_parties);
gpr_free(r->name_to_resolve); gpr_free(r->name_to_resolve);
gpr_free(r->default_port); gpr_free(r->default_port);
grpc_channel_args_destroy(exec_ctx, r->channel_args); grpc_channel_args_destroy(r->channel_args);
gpr_free(r); gpr_free(r);
} }
static grpc_resolver* dns_create(grpc_exec_ctx* exec_ctx, static grpc_resolver* dns_create(grpc_resolver_args* args,
grpc_resolver_args* args,
const char* default_port) { const char* default_port) {
if (0 != strcmp(args->uri->authority, "")) { if (0 != strcmp(args->uri->authority, "")) {
gpr_log(GPR_ERROR, "authority based dns uri's not supported"); gpr_log(GPR_ERROR, "authority based dns uri's not supported");
@ -254,8 +242,7 @@ static grpc_resolver* dns_create(grpc_exec_ctx* exec_ctx,
r->channel_args = grpc_channel_args_copy(args->args); r->channel_args = grpc_channel_args_copy(args->args);
r->interested_parties = grpc_pollset_set_create(); r->interested_parties = grpc_pollset_set_create();
if (args->pollset_set != nullptr) { if (args->pollset_set != nullptr) {
grpc_pollset_set_add_pollset_set(exec_ctx, r->interested_parties, grpc_pollset_set_add_pollset_set(r->interested_parties, args->pollset_set);
args->pollset_set);
} }
grpc_backoff_init( grpc_backoff_init(
&r->backoff_state, GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS * 1000, &r->backoff_state, GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS * 1000,
@ -274,9 +261,8 @@ static void dns_factory_ref(grpc_resolver_factory* factory) {}
static void dns_factory_unref(grpc_resolver_factory* factory) {} static void dns_factory_unref(grpc_resolver_factory* factory) {}
static grpc_resolver* dns_factory_create_resolver( static grpc_resolver* dns_factory_create_resolver(
grpc_exec_ctx* exec_ctx, grpc_resolver_factory* factory, grpc_resolver_factory* factory, grpc_resolver_args* args) {
grpc_resolver_args* args) { return dns_create(args, "https");
return dns_create(exec_ctx, args, "https");
} }
static char* dns_factory_get_default_host_name(grpc_resolver_factory* factory, static char* dns_factory_get_default_host_name(grpc_resolver_factory* factory,

@ -67,57 +67,52 @@ typedef struct {
grpc_channel_args** target_result; grpc_channel_args** target_result;
} fake_resolver; } fake_resolver;
static void fake_resolver_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* gr) { static void fake_resolver_destroy(grpc_resolver* gr) {
fake_resolver* r = (fake_resolver*)gr; fake_resolver* r = (fake_resolver*)gr;
grpc_channel_args_destroy(exec_ctx, r->next_results); grpc_channel_args_destroy(r->next_results);
grpc_channel_args_destroy(exec_ctx, r->results_upon_error); grpc_channel_args_destroy(r->results_upon_error);
grpc_channel_args_destroy(exec_ctx, r->channel_args); grpc_channel_args_destroy(r->channel_args);
gpr_free(r); gpr_free(r);
} }
static void fake_resolver_shutdown_locked(grpc_exec_ctx* exec_ctx, static void fake_resolver_shutdown_locked(grpc_resolver* resolver) {
grpc_resolver* resolver) {
fake_resolver* r = (fake_resolver*)resolver; fake_resolver* r = (fake_resolver*)resolver;
if (r->next_completion != nullptr) { if (r->next_completion != nullptr) {
*r->target_result = nullptr; *r->target_result = nullptr;
GRPC_CLOSURE_SCHED( GRPC_CLOSURE_SCHED(r->next_completion, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
exec_ctx, r->next_completion, "Resolver Shutdown"));
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver Shutdown"));
r->next_completion = nullptr; r->next_completion = nullptr;
} }
} }
static void fake_resolver_maybe_finish_next_locked(grpc_exec_ctx* exec_ctx, static void fake_resolver_maybe_finish_next_locked(fake_resolver* r) {
fake_resolver* r) {
if (r->next_completion != nullptr && r->next_results != nullptr) { if (r->next_completion != nullptr && r->next_results != nullptr) {
*r->target_result = *r->target_result =
grpc_channel_args_union(r->next_results, r->channel_args); grpc_channel_args_union(r->next_results, r->channel_args);
grpc_channel_args_destroy(exec_ctx, r->next_results); grpc_channel_args_destroy(r->next_results);
r->next_results = nullptr; r->next_results = nullptr;
GRPC_CLOSURE_SCHED(exec_ctx, r->next_completion, GRPC_ERROR_NONE); GRPC_CLOSURE_SCHED(r->next_completion, GRPC_ERROR_NONE);
r->next_completion = nullptr; r->next_completion = nullptr;
} }
} }
static void fake_resolver_channel_saw_error_locked(grpc_exec_ctx* exec_ctx, static void fake_resolver_channel_saw_error_locked(grpc_resolver* resolver) {
grpc_resolver* resolver) {
fake_resolver* r = (fake_resolver*)resolver; fake_resolver* r = (fake_resolver*)resolver;
if (r->next_results == nullptr && r->results_upon_error != nullptr) { if (r->next_results == nullptr && r->results_upon_error != nullptr) {
// Pretend we re-resolved. // Pretend we re-resolved.
r->next_results = grpc_channel_args_copy(r->results_upon_error); r->next_results = grpc_channel_args_copy(r->results_upon_error);
} }
fake_resolver_maybe_finish_next_locked(exec_ctx, r); fake_resolver_maybe_finish_next_locked(r);
} }
static void fake_resolver_next_locked(grpc_exec_ctx* exec_ctx, static void fake_resolver_next_locked(grpc_resolver* resolver,
grpc_resolver* resolver,
grpc_channel_args** target_result, grpc_channel_args** target_result,
grpc_closure* on_complete) { grpc_closure* on_complete) {
fake_resolver* r = (fake_resolver*)resolver; fake_resolver* r = (fake_resolver*)resolver;
GPR_ASSERT(!r->next_completion); GPR_ASSERT(!r->next_completion);
r->next_completion = on_complete; r->next_completion = on_complete;
r->target_result = target_result; r->target_result = target_result;
fake_resolver_maybe_finish_next_locked(exec_ctx, r); fake_resolver_maybe_finish_next_locked(r);
} }
static const grpc_resolver_vtable fake_resolver_vtable = { static const grpc_resolver_vtable fake_resolver_vtable = {
@ -157,33 +152,31 @@ typedef struct set_response_closure_arg {
grpc_channel_args* next_response; grpc_channel_args* next_response;
} set_response_closure_arg; } set_response_closure_arg;
static void set_response_closure_fn(grpc_exec_ctx* exec_ctx, void* arg, static void set_response_closure_fn(void* arg, grpc_error* error) {
grpc_error* error) {
set_response_closure_arg* closure_arg = (set_response_closure_arg*)arg; set_response_closure_arg* closure_arg = (set_response_closure_arg*)arg;
grpc_fake_resolver_response_generator* generator = closure_arg->generator; grpc_fake_resolver_response_generator* generator = closure_arg->generator;
fake_resolver* r = generator->resolver; fake_resolver* r = generator->resolver;
if (r->next_results != nullptr) { if (r->next_results != nullptr) {
grpc_channel_args_destroy(exec_ctx, r->next_results); grpc_channel_args_destroy(r->next_results);
} }
r->next_results = closure_arg->next_response; r->next_results = closure_arg->next_response;
if (r->results_upon_error != nullptr) { if (r->results_upon_error != nullptr) {
grpc_channel_args_destroy(exec_ctx, r->results_upon_error); grpc_channel_args_destroy(r->results_upon_error);
} }
r->results_upon_error = grpc_channel_args_copy(closure_arg->next_response); r->results_upon_error = grpc_channel_args_copy(closure_arg->next_response);
gpr_free(closure_arg); gpr_free(closure_arg);
fake_resolver_maybe_finish_next_locked(exec_ctx, r); fake_resolver_maybe_finish_next_locked(r);
} }
void grpc_fake_resolver_response_generator_set_response( void grpc_fake_resolver_response_generator_set_response(
grpc_exec_ctx* exec_ctx, grpc_fake_resolver_response_generator* generator, grpc_fake_resolver_response_generator* generator,
grpc_channel_args* next_response) { grpc_channel_args* next_response) {
GPR_ASSERT(generator->resolver != nullptr); GPR_ASSERT(generator->resolver != nullptr);
set_response_closure_arg* closure_arg = set_response_closure_arg* closure_arg =
(set_response_closure_arg*)gpr_zalloc(sizeof(*closure_arg)); (set_response_closure_arg*)gpr_zalloc(sizeof(*closure_arg));
closure_arg->generator = generator; closure_arg->generator = generator;
closure_arg->next_response = grpc_channel_args_copy(next_response); closure_arg->next_response = grpc_channel_args_copy(next_response);
GRPC_CLOSURE_SCHED(exec_ctx, GRPC_CLOSURE_SCHED(GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
set_response_closure_fn, closure_arg, set_response_closure_fn, closure_arg,
grpc_combiner_scheduler( grpc_combiner_scheduler(
generator->resolver->base.combiner)), generator->resolver->base.combiner)),
@ -195,7 +188,7 @@ static void* response_generator_arg_copy(void* p) {
(grpc_fake_resolver_response_generator*)p); (grpc_fake_resolver_response_generator*)p);
} }
static void response_generator_arg_destroy(grpc_exec_ctx* exec_ctx, void* p) { static void response_generator_arg_destroy(void* p) {
grpc_fake_resolver_response_generator_unref( grpc_fake_resolver_response_generator_unref(
(grpc_fake_resolver_response_generator*)p); (grpc_fake_resolver_response_generator*)p);
} }
@ -232,8 +225,7 @@ static void fake_resolver_factory_ref(grpc_resolver_factory* factory) {}
static void fake_resolver_factory_unref(grpc_resolver_factory* factory) {} static void fake_resolver_factory_unref(grpc_resolver_factory* factory) {}
static grpc_resolver* fake_resolver_create(grpc_exec_ctx* exec_ctx, static grpc_resolver* fake_resolver_create(grpc_resolver_factory* factory,
grpc_resolver_factory* factory,
grpc_resolver_args* args) { grpc_resolver_args* args) {
fake_resolver* r = (fake_resolver*)gpr_zalloc(sizeof(*r)); fake_resolver* r = (fake_resolver*)gpr_zalloc(sizeof(*r));
r->channel_args = grpc_channel_args_copy(args->args); r->channel_args = grpc_channel_args_copy(args->args);

@ -39,7 +39,7 @@ grpc_fake_resolver_response_generator_create();
// Instruct the fake resolver associated with the \a response_generator instance // Instruct the fake resolver associated with the \a response_generator instance
// to trigger a new resolution for \a uri and \a args. // to trigger a new resolution for \a uri and \a args.
void grpc_fake_resolver_response_generator_set_response( void grpc_fake_resolver_response_generator_set_response(
grpc_exec_ctx* exec_ctx, grpc_fake_resolver_response_generator* generator, grpc_fake_resolver_response_generator* generator,
grpc_channel_args* next_response); grpc_channel_args* next_response);
// Return a \a grpc_arg for a \a grpc_fake_resolver_response_generator instance. // Return a \a grpc_arg for a \a grpc_fake_resolver_response_generator instance.

@ -52,15 +52,13 @@ typedef struct {
grpc_channel_args** target_result; grpc_channel_args** target_result;
} sockaddr_resolver; } sockaddr_resolver;
static void sockaddr_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* r); static void sockaddr_destroy(grpc_resolver* r);
static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx* exec_ctx, static void sockaddr_maybe_finish_next_locked(sockaddr_resolver* r);
sockaddr_resolver* r);
static void sockaddr_shutdown_locked(grpc_exec_ctx* exec_ctx, grpc_resolver* r); static void sockaddr_shutdown_locked(grpc_resolver* r);
static void sockaddr_channel_saw_error_locked(grpc_exec_ctx* exec_ctx, static void sockaddr_channel_saw_error_locked(grpc_resolver* r);
grpc_resolver* r); static void sockaddr_next_locked(grpc_resolver* r,
static void sockaddr_next_locked(grpc_exec_ctx* exec_ctx, grpc_resolver* r,
grpc_channel_args** target_result, grpc_channel_args** target_result,
grpc_closure* on_complete); grpc_closure* on_complete);
@ -68,52 +66,47 @@ static const grpc_resolver_vtable sockaddr_resolver_vtable = {
sockaddr_destroy, sockaddr_shutdown_locked, sockaddr_destroy, sockaddr_shutdown_locked,
sockaddr_channel_saw_error_locked, sockaddr_next_locked}; sockaddr_channel_saw_error_locked, sockaddr_next_locked};
static void sockaddr_shutdown_locked(grpc_exec_ctx* exec_ctx, static void sockaddr_shutdown_locked(grpc_resolver* resolver) {
grpc_resolver* resolver) {
sockaddr_resolver* r = (sockaddr_resolver*)resolver; sockaddr_resolver* r = (sockaddr_resolver*)resolver;
if (r->next_completion != nullptr) { if (r->next_completion != nullptr) {
*r->target_result = nullptr; *r->target_result = nullptr;
GRPC_CLOSURE_SCHED( GRPC_CLOSURE_SCHED(r->next_completion, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
exec_ctx, r->next_completion, "Resolver Shutdown"));
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver Shutdown"));
r->next_completion = nullptr; r->next_completion = nullptr;
} }
} }
static void sockaddr_channel_saw_error_locked(grpc_exec_ctx* exec_ctx, static void sockaddr_channel_saw_error_locked(grpc_resolver* resolver) {
grpc_resolver* resolver) {
sockaddr_resolver* r = (sockaddr_resolver*)resolver; sockaddr_resolver* r = (sockaddr_resolver*)resolver;
r->published = false; r->published = false;
sockaddr_maybe_finish_next_locked(exec_ctx, r); sockaddr_maybe_finish_next_locked(r);
} }
static void sockaddr_next_locked(grpc_exec_ctx* exec_ctx, static void sockaddr_next_locked(grpc_resolver* resolver,
grpc_resolver* resolver,
grpc_channel_args** target_result, grpc_channel_args** target_result,
grpc_closure* on_complete) { grpc_closure* on_complete) {
sockaddr_resolver* r = (sockaddr_resolver*)resolver; sockaddr_resolver* r = (sockaddr_resolver*)resolver;
GPR_ASSERT(!r->next_completion); GPR_ASSERT(!r->next_completion);
r->next_completion = on_complete; r->next_completion = on_complete;
r->target_result = target_result; r->target_result = target_result;
sockaddr_maybe_finish_next_locked(exec_ctx, r); sockaddr_maybe_finish_next_locked(r);
} }
static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx* exec_ctx, static void sockaddr_maybe_finish_next_locked(sockaddr_resolver* r) {
sockaddr_resolver* r) {
if (r->next_completion != nullptr && !r->published) { if (r->next_completion != nullptr && !r->published) {
r->published = true; r->published = true;
grpc_arg arg = grpc_lb_addresses_create_channel_arg(r->addresses); grpc_arg arg = grpc_lb_addresses_create_channel_arg(r->addresses);
*r->target_result = *r->target_result =
grpc_channel_args_copy_and_add(r->channel_args, &arg, 1); grpc_channel_args_copy_and_add(r->channel_args, &arg, 1);
GRPC_CLOSURE_SCHED(exec_ctx, r->next_completion, GRPC_ERROR_NONE); GRPC_CLOSURE_SCHED(r->next_completion, GRPC_ERROR_NONE);
r->next_completion = nullptr; r->next_completion = nullptr;
} }
} }
static void sockaddr_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* gr) { static void sockaddr_destroy(grpc_resolver* gr) {
sockaddr_resolver* r = (sockaddr_resolver*)gr; sockaddr_resolver* r = (sockaddr_resolver*)gr;
grpc_lb_addresses_destroy(exec_ctx, r->addresses); grpc_lb_addresses_destroy(r->addresses);
grpc_channel_args_destroy(exec_ctx, r->channel_args); grpc_channel_args_destroy(r->channel_args);
gpr_free(r); gpr_free(r);
} }
@ -142,8 +135,7 @@ char* unix_get_default_authority(grpc_resolver_factory* factory,
static void do_nothing(void* ignored) {} static void do_nothing(void* ignored) {}
static grpc_resolver* sockaddr_create(grpc_exec_ctx* exec_ctx, static grpc_resolver* sockaddr_create(grpc_resolver_args* args,
grpc_resolver_args* args,
bool parse(const grpc_uri* uri, bool parse(const grpc_uri* uri,
grpc_resolved_address* dst)) { grpc_resolved_address* dst)) {
if (0 != strcmp(args->uri->authority, "")) { if (0 != strcmp(args->uri->authority, "")) {
@ -170,10 +162,10 @@ static grpc_resolver* sockaddr_create(grpc_exec_ctx* exec_ctx,
gpr_free(part_str); gpr_free(part_str);
if (errors_found) break; if (errors_found) break;
} }
grpc_slice_buffer_destroy_internal(exec_ctx, &path_parts); grpc_slice_buffer_destroy_internal(&path_parts);
grpc_slice_unref_internal(exec_ctx, path_slice); grpc_slice_unref_internal(path_slice);
if (errors_found) { if (errors_found) {
grpc_lb_addresses_destroy(exec_ctx, addresses); grpc_lb_addresses_destroy(addresses);
return nullptr; return nullptr;
} }
/* Instantiate resolver. */ /* Instantiate resolver. */
@ -195,9 +187,8 @@ static void sockaddr_factory_unref(grpc_resolver_factory* factory) {}
#define DECL_FACTORY(name) \ #define DECL_FACTORY(name) \
static grpc_resolver* name##_factory_create_resolver( \ static grpc_resolver* name##_factory_create_resolver( \
grpc_exec_ctx* exec_ctx, grpc_resolver_factory* factory, \ grpc_resolver_factory* factory, grpc_resolver_args* args) { \
grpc_resolver_args* args) { \ return sockaddr_create(args, grpc_parse_##name); \
return sockaddr_create(exec_ctx, args, grpc_parse_##name); \
} \ } \
static const grpc_resolver_factory_vtable name##_factory_vtable = { \ static const grpc_resolver_factory_vtable name##_factory_vtable = { \
sockaddr_factory_ref, sockaddr_factory_unref, \ sockaddr_factory_ref, sockaddr_factory_unref, \

@ -28,10 +28,9 @@ void grpc_resolver_factory_unref(grpc_resolver_factory* factory) {
/** Create a resolver instance for a name */ /** Create a resolver instance for a name */
grpc_resolver* grpc_resolver_factory_create_resolver( grpc_resolver* grpc_resolver_factory_create_resolver(
grpc_exec_ctx* exec_ctx, grpc_resolver_factory* factory, grpc_resolver_factory* factory, grpc_resolver_args* args) {
grpc_resolver_args* args) {
if (factory == nullptr) return nullptr; if (factory == nullptr) return nullptr;
return factory->vtable->create_resolver(exec_ctx, factory, args); return factory->vtable->create_resolver(factory, args);
} }
char* grpc_resolver_factory_get_default_authority( char* grpc_resolver_factory_get_default_authority(

@ -43,8 +43,7 @@ struct grpc_resolver_factory_vtable {
void (*unref)(grpc_resolver_factory* factory); void (*unref)(grpc_resolver_factory* factory);
/** Implementation of grpc_resolver_factory_create_resolver */ /** Implementation of grpc_resolver_factory_create_resolver */
grpc_resolver* (*create_resolver)(grpc_exec_ctx* exec_ctx, grpc_resolver* (*create_resolver)(grpc_resolver_factory* factory,
grpc_resolver_factory* factory,
grpc_resolver_args* args); grpc_resolver_args* args);
/** Implementation of grpc_resolver_factory_get_default_authority */ /** Implementation of grpc_resolver_factory_get_default_authority */
@ -59,8 +58,7 @@ void grpc_resolver_factory_unref(grpc_resolver_factory* resolver);
/** Create a resolver instance for a name */ /** Create a resolver instance for a name */
grpc_resolver* grpc_resolver_factory_create_resolver( grpc_resolver* grpc_resolver_factory_create_resolver(
grpc_exec_ctx* exec_ctx, grpc_resolver_factory* factory, grpc_resolver_factory* factory, grpc_resolver_args* args);
grpc_resolver_args* args);
/** Return a (freshly allocated with gpr_malloc) string representing /** Return a (freshly allocated with gpr_malloc) string representing
the default authority to use for this scheme. */ the default authority to use for this scheme. */

@ -92,23 +92,22 @@ static grpc_resolver_factory* lookup_factory_by_uri(grpc_uri* uri) {
return lookup_factory(uri->scheme); return lookup_factory(uri->scheme);
} }
static grpc_resolver_factory* resolve_factory(grpc_exec_ctx* exec_ctx, static grpc_resolver_factory* resolve_factory(const char* target,
const char* target,
grpc_uri** uri, grpc_uri** uri,
char** canonical_target) { char** canonical_target) {
grpc_resolver_factory* factory = nullptr; grpc_resolver_factory* factory = nullptr;
GPR_ASSERT(uri != nullptr); GPR_ASSERT(uri != nullptr);
*uri = grpc_uri_parse(exec_ctx, target, 1); *uri = grpc_uri_parse(target, 1);
factory = lookup_factory_by_uri(*uri); factory = lookup_factory_by_uri(*uri);
if (factory == nullptr) { if (factory == nullptr) {
grpc_uri_destroy(*uri); grpc_uri_destroy(*uri);
gpr_asprintf(canonical_target, "%s%s", g_default_resolver_prefix, target); gpr_asprintf(canonical_target, "%s%s", g_default_resolver_prefix, target);
*uri = grpc_uri_parse(exec_ctx, *canonical_target, 1); *uri = grpc_uri_parse(*canonical_target, 1);
factory = lookup_factory_by_uri(*uri); factory = lookup_factory_by_uri(*uri);
if (factory == nullptr) { if (factory == nullptr) {
grpc_uri_destroy(grpc_uri_parse(exec_ctx, target, 0)); grpc_uri_destroy(grpc_uri_parse(target, 0));
grpc_uri_destroy(grpc_uri_parse(exec_ctx, *canonical_target, 0)); grpc_uri_destroy(grpc_uri_parse(*canonical_target, 0));
gpr_log(GPR_ERROR, "don't know how to resolve '%s' or '%s'", target, gpr_log(GPR_ERROR, "don't know how to resolve '%s' or '%s'", target,
*canonical_target); *canonical_target);
} }
@ -116,14 +115,14 @@ static grpc_resolver_factory* resolve_factory(grpc_exec_ctx* exec_ctx,
return factory; return factory;
} }
grpc_resolver* grpc_resolver_create(grpc_exec_ctx* exec_ctx, const char* target, grpc_resolver* grpc_resolver_create(const char* target,
const grpc_channel_args* args, const grpc_channel_args* args,
grpc_pollset_set* pollset_set, grpc_pollset_set* pollset_set,
grpc_combiner* combiner) { grpc_combiner* combiner) {
grpc_uri* uri = nullptr; grpc_uri* uri = nullptr;
char* canonical_target = nullptr; char* canonical_target = nullptr;
grpc_resolver_factory* factory = grpc_resolver_factory* factory =
resolve_factory(exec_ctx, target, &uri, &canonical_target); resolve_factory(target, &uri, &canonical_target);
grpc_resolver* resolver; grpc_resolver* resolver;
grpc_resolver_args resolver_args; grpc_resolver_args resolver_args;
memset(&resolver_args, 0, sizeof(resolver_args)); memset(&resolver_args, 0, sizeof(resolver_args));
@ -131,29 +130,27 @@ grpc_resolver* grpc_resolver_create(grpc_exec_ctx* exec_ctx, const char* target,
resolver_args.args = args; resolver_args.args = args;
resolver_args.pollset_set = pollset_set; resolver_args.pollset_set = pollset_set;
resolver_args.combiner = combiner; resolver_args.combiner = combiner;
resolver = resolver = grpc_resolver_factory_create_resolver(factory, &resolver_args);
grpc_resolver_factory_create_resolver(exec_ctx, factory, &resolver_args);
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
gpr_free(canonical_target); gpr_free(canonical_target);
return resolver; return resolver;
} }
char* grpc_get_default_authority(grpc_exec_ctx* exec_ctx, const char* target) { char* grpc_get_default_authority(const char* target) {
grpc_uri* uri = nullptr; grpc_uri* uri = nullptr;
char* canonical_target = nullptr; char* canonical_target = nullptr;
grpc_resolver_factory* factory = grpc_resolver_factory* factory =
resolve_factory(exec_ctx, target, &uri, &canonical_target); resolve_factory(target, &uri, &canonical_target);
char* authority = grpc_resolver_factory_get_default_authority(factory, uri); char* authority = grpc_resolver_factory_get_default_authority(factory, uri);
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
gpr_free(canonical_target); gpr_free(canonical_target);
return authority; return authority;
} }
char* grpc_resolver_factory_add_default_prefix_if_needed( char* grpc_resolver_factory_add_default_prefix_if_needed(const char* target) {
grpc_exec_ctx* exec_ctx, const char* target) {
grpc_uri* uri = nullptr; grpc_uri* uri = nullptr;
char* canonical_target = nullptr; char* canonical_target = nullptr;
resolve_factory(exec_ctx, target, &uri, &canonical_target); resolve_factory(target, &uri, &canonical_target);
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
return canonical_target == nullptr ? gpr_strdup(target) : canonical_target; return canonical_target == nullptr ? gpr_strdup(target) : canonical_target;
} }

@ -48,7 +48,7 @@ void grpc_register_resolver_type(grpc_resolver_factory* factory);
(typically the set of arguments passed in from the client API). (typically the set of arguments passed in from the client API).
\a pollset_set is used to drive IO in the name resolution process, it \a pollset_set is used to drive IO in the name resolution process, it
should not be NULL. */ should not be NULL. */
grpc_resolver* grpc_resolver_create(grpc_exec_ctx* exec_ctx, const char* target, grpc_resolver* grpc_resolver_create(const char* target,
const grpc_channel_args* args, const grpc_channel_args* args,
grpc_pollset_set* pollset_set, grpc_pollset_set* pollset_set,
grpc_combiner* combiner); grpc_combiner* combiner);
@ -59,11 +59,10 @@ grpc_resolver_factory* grpc_resolver_factory_lookup(const char* name);
/** Given a target, return a (freshly allocated with gpr_malloc) string /** Given a target, return a (freshly allocated with gpr_malloc) string
representing the default authority to pass from a client. */ representing the default authority to pass from a client. */
char* grpc_get_default_authority(grpc_exec_ctx* exec_ctx, const char* target); char* grpc_get_default_authority(const char* target);
/** Returns a newly allocated string containing \a target, adding the /** Returns a newly allocated string containing \a target, adding the
default prefix if needed. */ default prefix if needed. */
char* grpc_resolver_factory_add_default_prefix_if_needed( char* grpc_resolver_factory_add_default_prefix_if_needed(const char* target);
grpc_exec_ctx* exec_ctx, const char* target);
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_REGISTRY_H */ #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_REGISTRY_H */

@ -139,8 +139,7 @@ struct grpc_subchannel_call {
#define CALLSTACK_TO_SUBCHANNEL_CALL(callstack) \ #define CALLSTACK_TO_SUBCHANNEL_CALL(callstack) \
(((grpc_subchannel_call*)(callstack)) - 1) (((grpc_subchannel_call*)(callstack)) - 1)
static void subchannel_connected(grpc_exec_ctx* exec_ctx, void* subchannel, static void subchannel_connected(void* subchannel, grpc_error* error);
grpc_error* error);
#ifndef NDEBUG #ifndef NDEBUG
#define REF_REASON reason #define REF_REASON reason
@ -157,10 +156,9 @@ static void subchannel_connected(grpc_exec_ctx* exec_ctx, void* subchannel,
* connection implementation * connection implementation
*/ */
static void connection_destroy(grpc_exec_ctx* exec_ctx, void* arg, static void connection_destroy(void* arg, grpc_error* error) {
grpc_error* error) {
grpc_connected_subchannel* c = (grpc_connected_subchannel*)arg; grpc_connected_subchannel* c = (grpc_connected_subchannel*)arg;
grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CONNECTION(c)); grpc_channel_stack_destroy(CHANNEL_STACK_FROM_CONNECTION(c));
gpr_free(c); gpr_free(c);
} }
@ -170,26 +168,23 @@ grpc_connected_subchannel* grpc_connected_subchannel_ref(
return c; return c;
} }
void grpc_connected_subchannel_unref(grpc_exec_ctx* exec_ctx, void grpc_connected_subchannel_unref(
grpc_connected_subchannel* c grpc_connected_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { GRPC_CHANNEL_STACK_UNREF(CHANNEL_STACK_FROM_CONNECTION(c), REF_REASON);
GRPC_CHANNEL_STACK_UNREF(exec_ctx, CHANNEL_STACK_FROM_CONNECTION(c),
REF_REASON);
} }
/* /*
* grpc_subchannel implementation * grpc_subchannel implementation
*/ */
static void subchannel_destroy(grpc_exec_ctx* exec_ctx, void* arg, static void subchannel_destroy(void* arg, grpc_error* error) {
grpc_error* error) {
grpc_subchannel* c = (grpc_subchannel*)arg; grpc_subchannel* c = (grpc_subchannel*)arg;
gpr_free((void*)c->filters); gpr_free((void*)c->filters);
grpc_channel_args_destroy(exec_ctx, c->args); grpc_channel_args_destroy(c->args);
grpc_connectivity_state_destroy(exec_ctx, &c->state_tracker); grpc_connectivity_state_destroy(&c->state_tracker);
grpc_connector_unref(exec_ctx, c->connector); grpc_connector_unref(c->connector);
grpc_pollset_set_destroy(exec_ctx, c->pollset_set); grpc_pollset_set_destroy(c->pollset_set);
grpc_subchannel_key_destroy(exec_ctx, c->key); grpc_subchannel_key_destroy(c->key);
gpr_mu_destroy(&c->mu); gpr_mu_destroy(&c->mu);
gpr_free(c); gpr_free(c);
} }
@ -241,59 +236,54 @@ grpc_subchannel* grpc_subchannel_ref_from_weak_ref(
} }
} }
static void disconnect(grpc_exec_ctx* exec_ctx, grpc_subchannel* c) { static void disconnect(grpc_subchannel* c) {
grpc_connected_subchannel* con; grpc_connected_subchannel* con;
grpc_subchannel_index_unregister(exec_ctx, c->key, c); grpc_subchannel_index_unregister(c->key, c);
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
GPR_ASSERT(!c->disconnected); GPR_ASSERT(!c->disconnected);
c->disconnected = true; c->disconnected = true;
grpc_connector_shutdown( grpc_connector_shutdown(c->connector, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
exec_ctx, c->connector, "Subchannel disconnected"));
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Subchannel disconnected"));
con = GET_CONNECTED_SUBCHANNEL(c, no_barrier); con = GET_CONNECTED_SUBCHANNEL(c, no_barrier);
if (con != nullptr) { if (con != nullptr) {
GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, con, "connection"); GRPC_CONNECTED_SUBCHANNEL_UNREF(con, "connection");
gpr_atm_no_barrier_store(&c->connected_subchannel, (gpr_atm)0xdeadbeef); gpr_atm_no_barrier_store(&c->connected_subchannel, (gpr_atm)0xdeadbeef);
} }
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
} }
void grpc_subchannel_unref(grpc_exec_ctx* exec_ctx, void grpc_subchannel_unref(grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
gpr_atm old_refs; gpr_atm old_refs;
// add a weak ref and subtract a strong ref (atomically) // add a weak ref and subtract a strong ref (atomically)
old_refs = ref_mutate(c, (gpr_atm)1 - (gpr_atm)(1 << INTERNAL_REF_BITS), old_refs = ref_mutate(c, (gpr_atm)1 - (gpr_atm)(1 << INTERNAL_REF_BITS),
1 REF_MUTATE_PURPOSE("STRONG_UNREF")); 1 REF_MUTATE_PURPOSE("STRONG_UNREF"));
if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) { if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) {
disconnect(exec_ctx, c); disconnect(c);
} }
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "strong-unref"); GRPC_SUBCHANNEL_WEAK_UNREF(c, "strong-unref");
} }
void grpc_subchannel_weak_unref(grpc_exec_ctx* exec_ctx, void grpc_subchannel_weak_unref(
grpc_subchannel* c grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
gpr_atm old_refs; gpr_atm old_refs;
old_refs = ref_mutate(c, -(gpr_atm)1, 1 REF_MUTATE_PURPOSE("WEAK_UNREF")); old_refs = ref_mutate(c, -(gpr_atm)1, 1 REF_MUTATE_PURPOSE("WEAK_UNREF"));
if (old_refs == 1) { if (old_refs == 1) {
GRPC_CLOSURE_SCHED( GRPC_CLOSURE_SCHED(
exec_ctx,
GRPC_CLOSURE_CREATE(subchannel_destroy, c, grpc_schedule_on_exec_ctx), GRPC_CLOSURE_CREATE(subchannel_destroy, c, grpc_schedule_on_exec_ctx),
GRPC_ERROR_NONE); GRPC_ERROR_NONE);
} }
} }
grpc_subchannel* grpc_subchannel_create(grpc_exec_ctx* exec_ctx, grpc_subchannel* grpc_subchannel_create(grpc_connector* connector,
grpc_connector* connector,
const grpc_subchannel_args* args) { const grpc_subchannel_args* args) {
grpc_subchannel_key* key = grpc_subchannel_key_create(args); grpc_subchannel_key* key = grpc_subchannel_key_create(args);
grpc_subchannel* c = grpc_subchannel_index_find(exec_ctx, key); grpc_subchannel* c = grpc_subchannel_index_find(key);
if (c) { if (c) {
grpc_subchannel_key_destroy(exec_ctx, key); grpc_subchannel_key_destroy(key);
return c; return c;
} }
GRPC_STATS_INC_CLIENT_SUBCHANNELS_CREATED(exec_ctx); GRPC_STATS_INC_CLIENT_SUBCHANNELS_CREATED();
c = (grpc_subchannel*)gpr_zalloc(sizeof(*c)); c = (grpc_subchannel*)gpr_zalloc(sizeof(*c));
c->key = key; c->key = key;
gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS); gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS);
@ -311,10 +301,10 @@ grpc_subchannel* grpc_subchannel_create(grpc_exec_ctx* exec_ctx,
c->pollset_set = grpc_pollset_set_create(); c->pollset_set = grpc_pollset_set_create();
grpc_resolved_address* addr = grpc_resolved_address* addr =
(grpc_resolved_address*)gpr_malloc(sizeof(*addr)); (grpc_resolved_address*)gpr_malloc(sizeof(*addr));
grpc_get_subchannel_address_arg(exec_ctx, args->args, addr); grpc_get_subchannel_address_arg(args->args, addr);
grpc_resolved_address* new_address = nullptr; grpc_resolved_address* new_address = nullptr;
grpc_channel_args* new_args = nullptr; grpc_channel_args* new_args = nullptr;
if (grpc_proxy_mappers_map_address(exec_ctx, addr, args->args, &new_address, if (grpc_proxy_mappers_map_address(addr, args->args, &new_address,
&new_args)) { &new_args)) {
GPR_ASSERT(new_address != nullptr); GPR_ASSERT(new_address != nullptr);
gpr_free(addr); gpr_free(addr);
@ -327,7 +317,7 @@ grpc_subchannel* grpc_subchannel_create(grpc_exec_ctx* exec_ctx,
new_args != nullptr ? new_args : args->args, keys_to_remove, new_args != nullptr ? new_args : args->args, keys_to_remove,
GPR_ARRAY_SIZE(keys_to_remove), &new_arg, 1); GPR_ARRAY_SIZE(keys_to_remove), &new_arg, 1);
gpr_free(new_arg.value.string); gpr_free(new_arg.value.string);
if (new_args != nullptr) grpc_channel_args_destroy(exec_ctx, new_args); if (new_args != nullptr) grpc_channel_args_destroy(new_args);
c->root_external_state_watcher.next = c->root_external_state_watcher.prev = c->root_external_state_watcher.next = c->root_external_state_watcher.prev =
&c->root_external_state_watcher; &c->root_external_state_watcher;
GRPC_CLOSURE_INIT(&c->connected, subchannel_connected, c, GRPC_CLOSURE_INIT(&c->connected, subchannel_connected, c,
@ -373,21 +363,19 @@ grpc_subchannel* grpc_subchannel_create(grpc_exec_ctx* exec_ctx,
min_backoff_ms, max_backoff_ms); min_backoff_ms, max_backoff_ms);
gpr_mu_init(&c->mu); gpr_mu_init(&c->mu);
return grpc_subchannel_index_register(exec_ctx, key, c); return grpc_subchannel_index_register(key, c);
} }
static void continue_connect_locked(grpc_exec_ctx* exec_ctx, static void continue_connect_locked(grpc_subchannel* c) {
grpc_subchannel* c) {
grpc_connect_in_args args; grpc_connect_in_args args;
args.interested_parties = c->pollset_set; args.interested_parties = c->pollset_set;
args.deadline = c->backoff_result.current_deadline; args.deadline = c->backoff_result.current_deadline;
args.channel_args = c->args; args.channel_args = c->args;
grpc_connectivity_state_set(exec_ctx, &c->state_tracker, grpc_connectivity_state_set(&c->state_tracker, GRPC_CHANNEL_CONNECTING,
GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, GRPC_ERROR_NONE, "state_change");
"state_change"); grpc_connector_connect(c->connector, &args, &c->connecting_result,
grpc_connector_connect(exec_ctx, c->connector, &args, &c->connecting_result,
&c->connected); &c->connected);
} }
@ -400,24 +388,23 @@ grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel* c,
return state; return state;
} }
static void on_external_state_watcher_done(grpc_exec_ctx* exec_ctx, void* arg, static void on_external_state_watcher_done(void* arg, grpc_error* error) {
grpc_error* error) {
external_state_watcher* w = (external_state_watcher*)arg; external_state_watcher* w = (external_state_watcher*)arg;
grpc_closure* follow_up = w->notify; grpc_closure* follow_up = w->notify;
if (w->pollset_set != nullptr) { if (w->pollset_set != nullptr) {
grpc_pollset_set_del_pollset_set(exec_ctx, w->subchannel->pollset_set, grpc_pollset_set_del_pollset_set(w->subchannel->pollset_set,
w->pollset_set); w->pollset_set);
} }
gpr_mu_lock(&w->subchannel->mu); gpr_mu_lock(&w->subchannel->mu);
w->next->prev = w->prev; w->next->prev = w->prev;
w->prev->next = w->next; w->prev->next = w->next;
gpr_mu_unlock(&w->subchannel->mu); gpr_mu_unlock(&w->subchannel->mu);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, w->subchannel, "external_state_watcher"); GRPC_SUBCHANNEL_WEAK_UNREF(w->subchannel, "external_state_watcher");
gpr_free(w); gpr_free(w);
GRPC_CLOSURE_RUN(exec_ctx, follow_up, GRPC_ERROR_REF(error)); GRPC_CLOSURE_RUN(follow_up, GRPC_ERROR_REF(error));
} }
static void on_alarm(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { static void on_alarm(void* arg, grpc_error* error) {
grpc_subchannel* c = (grpc_subchannel*)arg; grpc_subchannel* c = (grpc_subchannel*)arg;
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
c->have_alarm = false; c->have_alarm = false;
@ -429,18 +416,17 @@ static void on_alarm(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) {
} }
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
gpr_log(GPR_INFO, "Failed to connect to channel, retrying"); gpr_log(GPR_INFO, "Failed to connect to channel, retrying");
c->backoff_result = grpc_backoff_step(exec_ctx, &c->backoff_state); c->backoff_result = grpc_backoff_step(&c->backoff_state);
continue_connect_locked(exec_ctx, c); continue_connect_locked(c);
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
} else { } else {
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
} }
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
static void maybe_start_connecting_locked(grpc_exec_ctx* exec_ctx, static void maybe_start_connecting_locked(grpc_subchannel* c) {
grpc_subchannel* c) {
if (c->disconnected) { if (c->disconnected) {
/* Don't try to connect if we're already disconnected */ /* Don't try to connect if we're already disconnected */
return; return;
@ -466,28 +452,28 @@ static void maybe_start_connecting_locked(grpc_exec_ctx* exec_ctx,
if (!c->backoff_begun) { if (!c->backoff_begun) {
c->backoff_begun = true; c->backoff_begun = true;
c->backoff_result = grpc_backoff_begin(exec_ctx, &c->backoff_state); c->backoff_result = grpc_backoff_begin(&c->backoff_state);
continue_connect_locked(exec_ctx, c); continue_connect_locked(c);
} else { } else {
GPR_ASSERT(!c->have_alarm); GPR_ASSERT(!c->have_alarm);
c->have_alarm = true; c->have_alarm = true;
const grpc_millis time_til_next = const grpc_millis time_til_next =
c->backoff_result.next_attempt_start_time - grpc_exec_ctx_now(exec_ctx); c->backoff_result.next_attempt_start_time -
grpc_core::ExecCtx::Get()->Now();
if (time_til_next <= 0) { if (time_til_next <= 0) {
gpr_log(GPR_INFO, "Retry immediately"); gpr_log(GPR_INFO, "Retry immediately");
} else { } else {
gpr_log(GPR_INFO, "Retry in %" PRIdPTR " milliseconds", time_til_next); gpr_log(GPR_INFO, "Retry in %" PRIdPTR " milliseconds", time_til_next);
} }
GRPC_CLOSURE_INIT(&c->on_alarm, on_alarm, c, grpc_schedule_on_exec_ctx); GRPC_CLOSURE_INIT(&c->on_alarm, on_alarm, c, grpc_schedule_on_exec_ctx);
grpc_timer_init(exec_ctx, &c->alarm, grpc_timer_init(&c->alarm, c->backoff_result.next_attempt_start_time,
c->backoff_result.next_attempt_start_time, &c->on_alarm); &c->on_alarm);
} }
} }
void grpc_subchannel_notify_on_state_change( void grpc_subchannel_notify_on_state_change(
grpc_exec_ctx* exec_ctx, grpc_subchannel* c, grpc_subchannel* c, grpc_pollset_set* interested_parties,
grpc_pollset_set* interested_parties, grpc_connectivity_state* state, grpc_connectivity_state* state, grpc_closure* notify) {
grpc_closure* notify) {
external_state_watcher* w; external_state_watcher* w;
if (state == nullptr) { if (state == nullptr) {
@ -495,8 +481,8 @@ void grpc_subchannel_notify_on_state_change(
for (w = c->root_external_state_watcher.next; for (w = c->root_external_state_watcher.next;
w != &c->root_external_state_watcher; w = w->next) { w != &c->root_external_state_watcher; w = w->next) {
if (w->notify == notify) { if (w->notify == notify) {
grpc_connectivity_state_notify_on_state_change( grpc_connectivity_state_notify_on_state_change(&c->state_tracker,
exec_ctx, &c->state_tracker, nullptr, &w->closure); nullptr, &w->closure);
} }
} }
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
@ -508,31 +494,28 @@ void grpc_subchannel_notify_on_state_change(
GRPC_CLOSURE_INIT(&w->closure, on_external_state_watcher_done, w, GRPC_CLOSURE_INIT(&w->closure, on_external_state_watcher_done, w,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
if (interested_parties != nullptr) { if (interested_parties != nullptr) {
grpc_pollset_set_add_pollset_set(exec_ctx, c->pollset_set, grpc_pollset_set_add_pollset_set(c->pollset_set, interested_parties);
interested_parties);
} }
GRPC_SUBCHANNEL_WEAK_REF(c, "external_state_watcher"); GRPC_SUBCHANNEL_WEAK_REF(c, "external_state_watcher");
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
w->next = &c->root_external_state_watcher; w->next = &c->root_external_state_watcher;
w->prev = w->next->prev; w->prev = w->next->prev;
w->next->prev = w->prev->next = w; w->next->prev = w->prev->next = w;
grpc_connectivity_state_notify_on_state_change(exec_ctx, &c->state_tracker, grpc_connectivity_state_notify_on_state_change(&c->state_tracker, state,
state, &w->closure); &w->closure);
maybe_start_connecting_locked(exec_ctx, c); maybe_start_connecting_locked(c);
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
} }
} }
void grpc_connected_subchannel_process_transport_op( void grpc_connected_subchannel_process_transport_op(
grpc_exec_ctx* exec_ctx, grpc_connected_subchannel* con, grpc_connected_subchannel* con, grpc_transport_op* op) {
grpc_transport_op* op) {
grpc_channel_stack* channel_stack = CHANNEL_STACK_FROM_CONNECTION(con); grpc_channel_stack* channel_stack = CHANNEL_STACK_FROM_CONNECTION(con);
grpc_channel_element* top_elem = grpc_channel_stack_element(channel_stack, 0); grpc_channel_element* top_elem = grpc_channel_stack_element(channel_stack, 0);
top_elem->filter->start_transport_op(exec_ctx, top_elem, op); top_elem->filter->start_transport_op(top_elem, op);
} }
static void subchannel_on_child_state_changed(grpc_exec_ctx* exec_ctx, void* p, static void subchannel_on_child_state_changed(void* p, grpc_error* error) {
grpc_error* error) {
state_watcher* sw = (state_watcher*)p; state_watcher* sw = (state_watcher*)p;
grpc_subchannel* c = sw->subchannel; grpc_subchannel* c = sw->subchannel;
gpr_mu* mu = &c->mu; gpr_mu* mu = &c->mu;
@ -544,24 +527,22 @@ static void subchannel_on_child_state_changed(grpc_exec_ctx* exec_ctx, void* p,
/* any errors on a subchannel ==> we're done, create a new one */ /* any errors on a subchannel ==> we're done, create a new one */
sw->connectivity_state = GRPC_CHANNEL_SHUTDOWN; sw->connectivity_state = GRPC_CHANNEL_SHUTDOWN;
} }
grpc_connectivity_state_set(exec_ctx, &c->state_tracker, grpc_connectivity_state_set(&c->state_tracker, sw->connectivity_state,
sw->connectivity_state, GRPC_ERROR_REF(error), GRPC_ERROR_REF(error), "reflect_child");
"reflect_child");
if (sw->connectivity_state != GRPC_CHANNEL_SHUTDOWN) { if (sw->connectivity_state != GRPC_CHANNEL_SHUTDOWN) {
grpc_connected_subchannel_notify_on_state_change( grpc_connected_subchannel_notify_on_state_change(
exec_ctx, GET_CONNECTED_SUBCHANNEL(c, no_barrier), nullptr, GET_CONNECTED_SUBCHANNEL(c, no_barrier), nullptr,
&sw->connectivity_state, &sw->closure); &sw->connectivity_state, &sw->closure);
GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher"); GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
sw = nullptr; sw = nullptr;
} }
gpr_mu_unlock(mu); gpr_mu_unlock(mu);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "state_watcher"); GRPC_SUBCHANNEL_WEAK_UNREF(c, "state_watcher");
gpr_free(sw); gpr_free(sw);
} }
static void connected_subchannel_state_op(grpc_exec_ctx* exec_ctx, static void connected_subchannel_state_op(grpc_connected_subchannel* con,
grpc_connected_subchannel* con,
grpc_pollset_set* interested_parties, grpc_pollset_set* interested_parties,
grpc_connectivity_state* state, grpc_connectivity_state* state,
grpc_closure* closure) { grpc_closure* closure) {
@ -571,29 +552,25 @@ static void connected_subchannel_state_op(grpc_exec_ctx* exec_ctx,
op->on_connectivity_state_change = closure; op->on_connectivity_state_change = closure;
op->bind_pollset_set = interested_parties; op->bind_pollset_set = interested_parties;
elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0); elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0);
elem->filter->start_transport_op(exec_ctx, elem, op); elem->filter->start_transport_op(elem, op);
} }
void grpc_connected_subchannel_notify_on_state_change( void grpc_connected_subchannel_notify_on_state_change(
grpc_exec_ctx* exec_ctx, grpc_connected_subchannel* con, grpc_connected_subchannel* con, grpc_pollset_set* interested_parties,
grpc_pollset_set* interested_parties, grpc_connectivity_state* state, grpc_connectivity_state* state, grpc_closure* closure) {
grpc_closure* closure) { connected_subchannel_state_op(con, interested_parties, state, closure);
connected_subchannel_state_op(exec_ctx, con, interested_parties, state,
closure);
} }
void grpc_connected_subchannel_ping(grpc_exec_ctx* exec_ctx, void grpc_connected_subchannel_ping(grpc_connected_subchannel* con,
grpc_connected_subchannel* con,
grpc_closure* closure) { grpc_closure* closure) {
grpc_transport_op* op = grpc_make_transport_op(nullptr); grpc_transport_op* op = grpc_make_transport_op(nullptr);
grpc_channel_element* elem; grpc_channel_element* elem;
op->send_ping = closure; op->send_ping = closure;
elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0); elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0);
elem->filter->start_transport_op(exec_ctx, elem, op); elem->filter->start_transport_op(elem, op);
} }
static bool publish_transport_locked(grpc_exec_ctx* exec_ctx, static bool publish_transport_locked(grpc_subchannel* c) {
grpc_subchannel* c) {
grpc_connected_subchannel* con; grpc_connected_subchannel* con;
grpc_channel_stack* stk; grpc_channel_stack* stk;
state_watcher* sw_subchannel; state_watcher* sw_subchannel;
@ -601,19 +578,18 @@ static bool publish_transport_locked(grpc_exec_ctx* exec_ctx,
/* construct channel stack */ /* construct channel stack */
grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create(); grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create();
grpc_channel_stack_builder_set_channel_arguments( grpc_channel_stack_builder_set_channel_arguments(
exec_ctx, builder, c->connecting_result.channel_args); builder, c->connecting_result.channel_args);
grpc_channel_stack_builder_set_transport(builder, grpc_channel_stack_builder_set_transport(builder,
c->connecting_result.transport); c->connecting_result.transport);
if (!grpc_channel_init_create_stack(exec_ctx, builder, if (!grpc_channel_init_create_stack(builder, GRPC_CLIENT_SUBCHANNEL)) {
GRPC_CLIENT_SUBCHANNEL)) { grpc_channel_stack_builder_destroy(builder);
grpc_channel_stack_builder_destroy(exec_ctx, builder);
return false; return false;
} }
grpc_error* error = grpc_channel_stack_builder_finish( grpc_error* error = grpc_channel_stack_builder_finish(
exec_ctx, builder, 0, 1, connection_destroy, nullptr, (void**)&con); builder, 0, 1, connection_destroy, nullptr, (void**)&con);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
grpc_transport_destroy(exec_ctx, c->connecting_result.transport); grpc_transport_destroy(c->connecting_result.transport);
gpr_log(GPR_ERROR, "error initializing subchannel stack: %s", gpr_log(GPR_ERROR, "error initializing subchannel stack: %s",
grpc_error_string(error)); grpc_error_string(error));
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
@ -631,7 +607,7 @@ static bool publish_transport_locked(grpc_exec_ctx* exec_ctx,
if (c->disconnected) { if (c->disconnected) {
gpr_free(sw_subchannel); gpr_free(sw_subchannel);
grpc_channel_stack_destroy(exec_ctx, stk); grpc_channel_stack_destroy(stk);
gpr_free(con); gpr_free(con);
return false; return false;
} }
@ -647,19 +623,18 @@ static bool publish_transport_locked(grpc_exec_ctx* exec_ctx,
/* setup subchannel watching connected subchannel for changes; subchannel /* setup subchannel watching connected subchannel for changes; subchannel
ref for connecting is donated to the state watcher */ ref for connecting is donated to the state watcher */
GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher"); GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
grpc_connected_subchannel_notify_on_state_change( grpc_connected_subchannel_notify_on_state_change(
exec_ctx, con, c->pollset_set, &sw_subchannel->connectivity_state, con, c->pollset_set, &sw_subchannel->connectivity_state,
&sw_subchannel->closure); &sw_subchannel->closure);
/* signal completion */ /* signal completion */
grpc_connectivity_state_set(exec_ctx, &c->state_tracker, GRPC_CHANNEL_READY, grpc_connectivity_state_set(&c->state_tracker, GRPC_CHANNEL_READY,
GRPC_ERROR_NONE, "connected"); GRPC_ERROR_NONE, "connected");
return true; return true;
} }
static void subchannel_connected(grpc_exec_ctx* exec_ctx, void* arg, static void subchannel_connected(void* arg, grpc_error* error) {
grpc_error* error) {
grpc_subchannel* c = (grpc_subchannel*)arg; grpc_subchannel* c = (grpc_subchannel*)arg;
grpc_channel_args* delete_channel_args = c->connecting_result.channel_args; grpc_channel_args* delete_channel_args = c->connecting_result.channel_args;
@ -667,13 +642,13 @@ static void subchannel_connected(grpc_exec_ctx* exec_ctx, void* arg,
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
c->connecting = false; c->connecting = false;
if (c->connecting_result.transport != nullptr && if (c->connecting_result.transport != nullptr &&
publish_transport_locked(exec_ctx, c)) { publish_transport_locked(c)) {
/* do nothing, transport was published */ /* do nothing, transport was published */
} else if (c->disconnected) { } else if (c->disconnected) {
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
} else { } else {
grpc_connectivity_state_set( grpc_connectivity_state_set(
exec_ctx, &c->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, &c->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Connect Failed", &error, 1), "Connect Failed", &error, 1),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE),
@ -682,27 +657,26 @@ static void subchannel_connected(grpc_exec_ctx* exec_ctx, void* arg,
const char* errmsg = grpc_error_string(error); const char* errmsg = grpc_error_string(error);
gpr_log(GPR_INFO, "Connect failed: %s", errmsg); gpr_log(GPR_INFO, "Connect failed: %s", errmsg);
maybe_start_connecting_locked(exec_ctx, c); maybe_start_connecting_locked(c);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
} }
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connected"); GRPC_SUBCHANNEL_WEAK_UNREF(c, "connected");
grpc_channel_args_destroy(exec_ctx, delete_channel_args); grpc_channel_args_destroy(delete_channel_args);
} }
/* /*
* grpc_subchannel_call implementation * grpc_subchannel_call implementation
*/ */
static void subchannel_call_destroy(grpc_exec_ctx* exec_ctx, void* call, static void subchannel_call_destroy(void* call, grpc_error* error) {
grpc_error* error) {
grpc_subchannel_call* c = (grpc_subchannel_call*)call; grpc_subchannel_call* c = (grpc_subchannel_call*)call;
GPR_ASSERT(c->schedule_closure_after_destroy != nullptr); GPR_ASSERT(c->schedule_closure_after_destroy != nullptr);
GPR_TIMER_BEGIN("grpc_subchannel_call_unref.destroy", 0); GPR_TIMER_BEGIN("grpc_subchannel_call_unref.destroy", 0);
grpc_connected_subchannel* connection = c->connection; grpc_connected_subchannel* connection = c->connection;
grpc_call_stack_destroy(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c), nullptr, grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(c), nullptr,
c->schedule_closure_after_destroy); c->schedule_closure_after_destroy);
GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, connection, "subchannel_call"); GRPC_CONNECTED_SUBCHANNEL_UNREF(connection, "subchannel_call");
GPR_TIMER_END("grpc_subchannel_call_unref.destroy", 0); GPR_TIMER_END("grpc_subchannel_call_unref.destroy", 0);
} }
@ -718,20 +692,18 @@ void grpc_subchannel_call_ref(
GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON); GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON);
} }
void grpc_subchannel_call_unref(grpc_exec_ctx* exec_ctx, void grpc_subchannel_call_unref(
grpc_subchannel_call* c grpc_subchannel_call* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON);
GRPC_CALL_STACK_UNREF(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON);
} }
void grpc_subchannel_call_process_op(grpc_exec_ctx* exec_ctx, void grpc_subchannel_call_process_op(grpc_subchannel_call* call,
grpc_subchannel_call* call,
grpc_transport_stream_op_batch* batch) { grpc_transport_stream_op_batch* batch) {
GPR_TIMER_BEGIN("grpc_subchannel_call_process_op", 0); GPR_TIMER_BEGIN("grpc_subchannel_call_process_op", 0);
grpc_call_stack* call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call); grpc_call_stack* call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
grpc_call_element* top_elem = grpc_call_stack_element(call_stack, 0); grpc_call_element* top_elem = grpc_call_stack_element(call_stack, 0);
GRPC_CALL_LOG_OP(GPR_INFO, top_elem, batch); GRPC_CALL_LOG_OP(GPR_INFO, top_elem, batch);
top_elem->filter->start_transport_stream_op_batch(exec_ctx, top_elem, batch); top_elem->filter->start_transport_stream_op_batch(top_elem, batch);
GPR_TIMER_END("grpc_subchannel_call_process_op", 0); GPR_TIMER_END("grpc_subchannel_call_process_op", 0);
} }
@ -746,7 +718,7 @@ const grpc_subchannel_key* grpc_subchannel_get_key(
} }
grpc_error* grpc_connected_subchannel_create_call( grpc_error* grpc_connected_subchannel_create_call(
grpc_exec_ctx* exec_ctx, grpc_connected_subchannel* con, grpc_connected_subchannel* con,
const grpc_connected_subchannel_call_args* args, const grpc_connected_subchannel_call_args* args,
grpc_subchannel_call** call) { grpc_subchannel_call** call) {
grpc_channel_stack* chanstk = CHANNEL_STACK_FROM_CONNECTION(con); grpc_channel_stack* chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
@ -764,14 +736,14 @@ grpc_error* grpc_connected_subchannel_create_call(
args->arena, /* arena */ args->arena, /* arena */
args->call_combiner /* call_combiner */ args->call_combiner /* call_combiner */
}; };
grpc_error* error = grpc_call_stack_init( grpc_error* error = grpc_call_stack_init(chanstk, 1, subchannel_call_destroy,
exec_ctx, chanstk, 1, subchannel_call_destroy, *call, &call_args); *call, &call_args);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
const char* error_string = grpc_error_string(error); const char* error_string = grpc_error_string(error);
gpr_log(GPR_ERROR, "error: %s", error_string); gpr_log(GPR_ERROR, "error: %s", error_string);
return error; return error;
} }
grpc_call_stack_set_pollset_or_pollset_set(exec_ctx, callstk, args->pollent); grpc_call_stack_set_pollset_or_pollset_set(callstk, args->pollent);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
@ -780,21 +752,20 @@ grpc_call_stack* grpc_subchannel_call_get_call_stack(
return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call); return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call);
} }
static void grpc_uri_to_sockaddr(grpc_exec_ctx* exec_ctx, const char* uri_str, static void grpc_uri_to_sockaddr(const char* uri_str,
grpc_resolved_address* addr) { grpc_resolved_address* addr) {
grpc_uri* uri = grpc_uri_parse(exec_ctx, uri_str, 0 /* suppress_errors */); grpc_uri* uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */);
GPR_ASSERT(uri != nullptr); GPR_ASSERT(uri != nullptr);
if (!grpc_parse_uri(uri, addr)) memset(addr, 0, sizeof(*addr)); if (!grpc_parse_uri(uri, addr)) memset(addr, 0, sizeof(*addr));
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
} }
void grpc_get_subchannel_address_arg(grpc_exec_ctx* exec_ctx, void grpc_get_subchannel_address_arg(const grpc_channel_args* args,
const grpc_channel_args* args,
grpc_resolved_address* addr) { grpc_resolved_address* addr) {
const char* addr_uri_str = grpc_get_subchannel_address_uri_arg(args); const char* addr_uri_str = grpc_get_subchannel_address_uri_arg(args);
memset(addr, 0, sizeof(*addr)); memset(addr, 0, sizeof(*addr));
if (*addr_uri_str != '\0') { if (*addr_uri_str != '\0') {
grpc_uri_to_sockaddr(exec_ctx, addr_uri_str, addr); grpc_uri_to_sockaddr(addr_uri_str, addr);
} }
} }

@ -42,36 +42,34 @@ typedef struct grpc_subchannel_key grpc_subchannel_key;
grpc_subchannel_ref((p), __FILE__, __LINE__, (r)) grpc_subchannel_ref((p), __FILE__, __LINE__, (r))
#define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \ #define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \
grpc_subchannel_ref_from_weak_ref((p), __FILE__, __LINE__, (r)) grpc_subchannel_ref_from_weak_ref((p), __FILE__, __LINE__, (r))
#define GRPC_SUBCHANNEL_UNREF(cl, p, r) \ #define GRPC_SUBCHANNEL_UNREF(p, r) \
grpc_subchannel_unref((cl), (p), __FILE__, __LINE__, (r)) grpc_subchannel_unref((p), __FILE__, __LINE__, (r))
#define GRPC_SUBCHANNEL_WEAK_REF(p, r) \ #define GRPC_SUBCHANNEL_WEAK_REF(p, r) \
grpc_subchannel_weak_ref((p), __FILE__, __LINE__, (r)) grpc_subchannel_weak_ref((p), __FILE__, __LINE__, (r))
#define GRPC_SUBCHANNEL_WEAK_UNREF(cl, p, r) \ #define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) \
grpc_subchannel_weak_unref((cl), (p), __FILE__, __LINE__, (r)) grpc_subchannel_weak_unref((p), __FILE__, __LINE__, (r))
#define GRPC_CONNECTED_SUBCHANNEL_REF(p, r) \ #define GRPC_CONNECTED_SUBCHANNEL_REF(p, r) \
grpc_connected_subchannel_ref((p), __FILE__, __LINE__, (r)) grpc_connected_subchannel_ref((p), __FILE__, __LINE__, (r))
#define GRPC_CONNECTED_SUBCHANNEL_UNREF(cl, p, r) \ #define GRPC_CONNECTED_SUBCHANNEL_UNREF(p, r) \
grpc_connected_subchannel_unref((cl), (p), __FILE__, __LINE__, (r)) grpc_connected_subchannel_unref((p), __FILE__, __LINE__, (r))
#define GRPC_SUBCHANNEL_CALL_REF(p, r) \ #define GRPC_SUBCHANNEL_CALL_REF(p, r) \
grpc_subchannel_call_ref((p), __FILE__, __LINE__, (r)) grpc_subchannel_call_ref((p), __FILE__, __LINE__, (r))
#define GRPC_SUBCHANNEL_CALL_UNREF(cl, p, r) \ #define GRPC_SUBCHANNEL_CALL_UNREF(p, r) \
grpc_subchannel_call_unref((cl), (p), __FILE__, __LINE__, (r)) grpc_subchannel_call_unref((p), __FILE__, __LINE__, (r))
#define GRPC_SUBCHANNEL_REF_EXTRA_ARGS \ #define GRPC_SUBCHANNEL_REF_EXTRA_ARGS \
, const char *file, int line, const char *reason , const char *file, int line, const char *reason
#else #else
#define GRPC_SUBCHANNEL_REF(p, r) grpc_subchannel_ref((p)) #define GRPC_SUBCHANNEL_REF(p, r) grpc_subchannel_ref((p))
#define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \ #define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \
grpc_subchannel_ref_from_weak_ref((p)) grpc_subchannel_ref_from_weak_ref((p))
#define GRPC_SUBCHANNEL_UNREF(cl, p, r) grpc_subchannel_unref((cl), (p)) #define GRPC_SUBCHANNEL_UNREF(p, r) grpc_subchannel_unref((p))
#define GRPC_SUBCHANNEL_WEAK_REF(p, r) grpc_subchannel_weak_ref((p)) #define GRPC_SUBCHANNEL_WEAK_REF(p, r) grpc_subchannel_weak_ref((p))
#define GRPC_SUBCHANNEL_WEAK_UNREF(cl, p, r) \ #define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) grpc_subchannel_weak_unref((p))
grpc_subchannel_weak_unref((cl), (p))
#define GRPC_CONNECTED_SUBCHANNEL_REF(p, r) grpc_connected_subchannel_ref((p)) #define GRPC_CONNECTED_SUBCHANNEL_REF(p, r) grpc_connected_subchannel_ref((p))
#define GRPC_CONNECTED_SUBCHANNEL_UNREF(cl, p, r) \ #define GRPC_CONNECTED_SUBCHANNEL_UNREF(p, r) \
grpc_connected_subchannel_unref((cl), (p)) grpc_connected_subchannel_unref((p))
#define GRPC_SUBCHANNEL_CALL_REF(p, r) grpc_subchannel_call_ref((p)) #define GRPC_SUBCHANNEL_CALL_REF(p, r) grpc_subchannel_call_ref((p))
#define GRPC_SUBCHANNEL_CALL_UNREF(cl, p, r) \ #define GRPC_SUBCHANNEL_CALL_UNREF(p, r) grpc_subchannel_call_unref((p))
grpc_subchannel_call_unref((cl), (p))
#define GRPC_SUBCHANNEL_REF_EXTRA_ARGS #define GRPC_SUBCHANNEL_REF_EXTRA_ARGS
#endif #endif
@ -79,24 +77,20 @@ grpc_subchannel* grpc_subchannel_ref(
grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
grpc_subchannel* grpc_subchannel_ref_from_weak_ref( grpc_subchannel* grpc_subchannel_ref_from_weak_ref(
grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
void grpc_subchannel_unref(grpc_exec_ctx* exec_ctx, void grpc_subchannel_unref(
grpc_subchannel* channel grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
grpc_subchannel* grpc_subchannel_weak_ref( grpc_subchannel* grpc_subchannel_weak_ref(
grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
void grpc_subchannel_weak_unref(grpc_exec_ctx* exec_ctx, void grpc_subchannel_weak_unref(
grpc_subchannel* channel grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
grpc_connected_subchannel* grpc_connected_subchannel_ref( grpc_connected_subchannel* grpc_connected_subchannel_ref(
grpc_connected_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); grpc_connected_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
void grpc_connected_subchannel_unref(grpc_exec_ctx* exec_ctx, void grpc_connected_subchannel_unref(
grpc_connected_subchannel* channel grpc_connected_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
void grpc_subchannel_call_ref( void grpc_subchannel_call_ref(
grpc_subchannel_call* call GRPC_SUBCHANNEL_REF_EXTRA_ARGS); grpc_subchannel_call* call GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
void grpc_subchannel_call_unref(grpc_exec_ctx* exec_ctx, void grpc_subchannel_call_unref(
grpc_subchannel_call* call grpc_subchannel_call* call GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
/** construct a subchannel call */ /** construct a subchannel call */
typedef struct { typedef struct {
@ -110,14 +104,13 @@ typedef struct {
} grpc_connected_subchannel_call_args; } grpc_connected_subchannel_call_args;
grpc_error* grpc_connected_subchannel_create_call( grpc_error* grpc_connected_subchannel_create_call(
grpc_exec_ctx* exec_ctx, grpc_connected_subchannel* connected_subchannel, grpc_connected_subchannel* connected_subchannel,
const grpc_connected_subchannel_call_args* args, const grpc_connected_subchannel_call_args* args,
grpc_subchannel_call** subchannel_call); grpc_subchannel_call** subchannel_call);
/** process a transport level op */ /** process a transport level op */
void grpc_connected_subchannel_process_transport_op( void grpc_connected_subchannel_process_transport_op(
grpc_exec_ctx* exec_ctx, grpc_connected_subchannel* subchannel, grpc_connected_subchannel* subchannel, grpc_transport_op* op);
grpc_transport_op* op);
/** poll the current connectivity state of a channel */ /** poll the current connectivity state of a channel */
grpc_connectivity_state grpc_subchannel_check_connectivity( grpc_connectivity_state grpc_subchannel_check_connectivity(
@ -126,15 +119,12 @@ grpc_connectivity_state grpc_subchannel_check_connectivity(
/** Calls notify when the connectivity state of a channel becomes different /** Calls notify when the connectivity state of a channel becomes different
from *state. Updates *state with the new state of the channel. */ from *state. Updates *state with the new state of the channel. */
void grpc_subchannel_notify_on_state_change( void grpc_subchannel_notify_on_state_change(
grpc_exec_ctx* exec_ctx, grpc_subchannel* channel, grpc_subchannel* channel, grpc_pollset_set* interested_parties,
grpc_pollset_set* interested_parties, grpc_connectivity_state* state, grpc_connectivity_state* state, grpc_closure* notify);
grpc_closure* notify);
void grpc_connected_subchannel_notify_on_state_change( void grpc_connected_subchannel_notify_on_state_change(
grpc_exec_ctx* exec_ctx, grpc_connected_subchannel* channel, grpc_connected_subchannel* channel, grpc_pollset_set* interested_parties,
grpc_pollset_set* interested_parties, grpc_connectivity_state* state, grpc_connectivity_state* state, grpc_closure* notify);
grpc_closure* notify); void grpc_connected_subchannel_ping(grpc_connected_subchannel* channel,
void grpc_connected_subchannel_ping(grpc_exec_ctx* exec_ctx,
grpc_connected_subchannel* channel,
grpc_closure* notify); grpc_closure* notify);
/** retrieve the grpc_connected_subchannel - or NULL if called before /** retrieve the grpc_connected_subchannel - or NULL if called before
@ -147,8 +137,7 @@ const grpc_subchannel_key* grpc_subchannel_get_key(
const grpc_subchannel* subchannel); const grpc_subchannel* subchannel);
/** continue processing a transport op */ /** continue processing a transport op */
void grpc_subchannel_call_process_op(grpc_exec_ctx* exec_ctx, void grpc_subchannel_call_process_op(grpc_subchannel_call* subchannel_call,
grpc_subchannel_call* subchannel_call,
grpc_transport_stream_op_batch* op); grpc_transport_stream_op_batch* op);
/** Must be called once per call. Sets the 'then_schedule_closure' argument for /** Must be called once per call. Sets the 'then_schedule_closure' argument for
@ -172,13 +161,11 @@ struct grpc_subchannel_args {
}; };
/** create a subchannel given a connector */ /** create a subchannel given a connector */
grpc_subchannel* grpc_subchannel_create(grpc_exec_ctx* exec_ctx, grpc_subchannel* grpc_subchannel_create(grpc_connector* connector,
grpc_connector* connector,
const grpc_subchannel_args* args); const grpc_subchannel_args* args);
/// Sets \a addr from \a args. /// Sets \a addr from \a args.
void grpc_get_subchannel_address_arg(grpc_exec_ctx* exec_ctx, void grpc_get_subchannel_address_arg(const grpc_channel_args* args,
const grpc_channel_args* args,
grpc_resolved_address* addr); grpc_resolved_address* addr);
/// Returns the URI string for the address to connect to. /// Returns the URI string for the address to connect to.

@ -81,16 +81,14 @@ int grpc_subchannel_key_compare(const grpc_subchannel_key* a,
return grpc_channel_args_compare(a->args.args, b->args.args); return grpc_channel_args_compare(a->args.args, b->args.args);
} }
void grpc_subchannel_key_destroy(grpc_exec_ctx* exec_ctx, void grpc_subchannel_key_destroy(grpc_subchannel_key* k) {
grpc_subchannel_key* k) {
gpr_free((grpc_channel_args*)k->args.filters); gpr_free((grpc_channel_args*)k->args.filters);
grpc_channel_args_destroy(exec_ctx, (grpc_channel_args*)k->args.args); grpc_channel_args_destroy((grpc_channel_args*)k->args.args);
gpr_free(k); gpr_free(k);
} }
static void sck_avl_destroy(void* p, void* user_data) { static void sck_avl_destroy(void* p, void* user_data) {
grpc_exec_ctx* exec_ctx = (grpc_exec_ctx*)user_data; grpc_subchannel_key_destroy((grpc_subchannel_key*)p);
grpc_subchannel_key_destroy(exec_ctx, (grpc_subchannel_key*)p);
} }
static void* sck_avl_copy(void* p, void* unused) { static void* sck_avl_copy(void* p, void* unused) {
@ -103,8 +101,7 @@ static long sck_avl_compare(void* a, void* b, void* unused) {
} }
static void scv_avl_destroy(void* p, void* user_data) { static void scv_avl_destroy(void* p, void* user_data) {
grpc_exec_ctx* exec_ctx = (grpc_exec_ctx*)user_data; GRPC_SUBCHANNEL_WEAK_UNREF((grpc_subchannel*)p, "subchannel_index");
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, (grpc_subchannel*)p, "subchannel_index");
} }
static void* scv_avl_copy(void* p, void* unused) { static void* scv_avl_copy(void* p, void* unused) {
@ -135,32 +132,29 @@ void grpc_subchannel_index_shutdown(void) {
void grpc_subchannel_index_unref(void) { void grpc_subchannel_index_unref(void) {
if (gpr_unref(&g_refcount)) { if (gpr_unref(&g_refcount)) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
gpr_mu_destroy(&g_mu); gpr_mu_destroy(&g_mu);
gpr_avl_unref(g_subchannel_index, &exec_ctx); gpr_avl_unref(g_subchannel_index, grpc_core::ExecCtx::Get());
grpc_exec_ctx_finish(&exec_ctx);
} }
} }
void grpc_subchannel_index_ref(void) { gpr_ref_non_zero(&g_refcount); } void grpc_subchannel_index_ref(void) { gpr_ref_non_zero(&g_refcount); }
grpc_subchannel* grpc_subchannel_index_find(grpc_exec_ctx* exec_ctx, grpc_subchannel* grpc_subchannel_index_find(grpc_subchannel_key* key) {
grpc_subchannel_key* key) {
// Lock, and take a reference to the subchannel index. // Lock, and take a reference to the subchannel index.
// We don't need to do the search under a lock as avl's are immutable. // We don't need to do the search under a lock as avl's are immutable.
gpr_mu_lock(&g_mu); gpr_mu_lock(&g_mu);
gpr_avl index = gpr_avl_ref(g_subchannel_index, exec_ctx); gpr_avl index = gpr_avl_ref(g_subchannel_index, grpc_core::ExecCtx::Get());
gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_mu);
grpc_subchannel* c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF( grpc_subchannel* c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(
(grpc_subchannel*)gpr_avl_get(index, key, exec_ctx), "index_find"); (grpc_subchannel*)gpr_avl_get(index, key, grpc_core::ExecCtx::Get()),
gpr_avl_unref(index, exec_ctx); "index_find");
gpr_avl_unref(index, grpc_core::ExecCtx::Get());
return c; return c;
} }
grpc_subchannel* grpc_subchannel_index_register(grpc_exec_ctx* exec_ctx, grpc_subchannel* grpc_subchannel_index_register(grpc_subchannel_key* key,
grpc_subchannel_key* key,
grpc_subchannel* constructed) { grpc_subchannel* constructed) {
grpc_subchannel* c = nullptr; grpc_subchannel* c = nullptr;
bool need_to_unref_constructed = false; bool need_to_unref_constructed = false;
@ -171,11 +165,11 @@ grpc_subchannel* grpc_subchannel_index_register(grpc_exec_ctx* exec_ctx,
// Compare and swap loop: // Compare and swap loop:
// - take a reference to the current index // - take a reference to the current index
gpr_mu_lock(&g_mu); gpr_mu_lock(&g_mu);
gpr_avl index = gpr_avl_ref(g_subchannel_index, exec_ctx); gpr_avl index = gpr_avl_ref(g_subchannel_index, grpc_core::ExecCtx::Get());
gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_mu);
// - Check to see if a subchannel already exists // - Check to see if a subchannel already exists
c = (grpc_subchannel*)gpr_avl_get(index, key, exec_ctx); c = (grpc_subchannel*)gpr_avl_get(index, key, grpc_core::ExecCtx::Get());
if (c != nullptr) { if (c != nullptr) {
c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "index_register"); c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "index_register");
} }
@ -184,9 +178,11 @@ grpc_subchannel* grpc_subchannel_index_register(grpc_exec_ctx* exec_ctx,
need_to_unref_constructed = true; need_to_unref_constructed = true;
} else { } else {
// no -> update the avl and compare/swap // no -> update the avl and compare/swap
gpr_avl updated = gpr_avl_add( gpr_avl updated =
gpr_avl_ref(index, exec_ctx), subchannel_key_copy(key), gpr_avl_add(gpr_avl_ref(index, grpc_core::ExecCtx::Get()),
GRPC_SUBCHANNEL_WEAK_REF(constructed, "index_register"), exec_ctx); subchannel_key_copy(key),
GRPC_SUBCHANNEL_WEAK_REF(constructed, "index_register"),
grpc_core::ExecCtx::Get());
// it may happen (but it's expected to be unlikely) // it may happen (but it's expected to be unlikely)
// that some other thread has changed the index: // that some other thread has changed the index:
@ -198,41 +194,42 @@ grpc_subchannel* grpc_subchannel_index_register(grpc_exec_ctx* exec_ctx,
} }
gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_mu);
gpr_avl_unref(updated, exec_ctx); gpr_avl_unref(updated, grpc_core::ExecCtx::Get());
} }
gpr_avl_unref(index, exec_ctx); gpr_avl_unref(index, grpc_core::ExecCtx::Get());
} }
if (need_to_unref_constructed) { if (need_to_unref_constructed) {
GRPC_SUBCHANNEL_UNREF(exec_ctx, constructed, "index_register"); GRPC_SUBCHANNEL_UNREF(constructed, "index_register");
} }
return c; return c;
} }
void grpc_subchannel_index_unregister(grpc_exec_ctx* exec_ctx, void grpc_subchannel_index_unregister(grpc_subchannel_key* key,
grpc_subchannel_key* key,
grpc_subchannel* constructed) { grpc_subchannel* constructed) {
bool done = false; bool done = false;
while (!done) { while (!done) {
// Compare and swap loop: // Compare and swap loop:
// - take a reference to the current index // - take a reference to the current index
gpr_mu_lock(&g_mu); gpr_mu_lock(&g_mu);
gpr_avl index = gpr_avl_ref(g_subchannel_index, exec_ctx); gpr_avl index = gpr_avl_ref(g_subchannel_index, grpc_core::ExecCtx::Get());
gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_mu);
// Check to see if this key still refers to the previously // Check to see if this key still refers to the previously
// registered subchannel // registered subchannel
grpc_subchannel* c = (grpc_subchannel*)gpr_avl_get(index, key, exec_ctx); grpc_subchannel* c =
(grpc_subchannel*)gpr_avl_get(index, key, grpc_core::ExecCtx::Get());
if (c != constructed) { if (c != constructed) {
gpr_avl_unref(index, exec_ctx); gpr_avl_unref(index, grpc_core::ExecCtx::Get());
break; break;
} }
// compare and swap the update (some other thread may have // compare and swap the update (some other thread may have
// mutated the index behind us) // mutated the index behind us)
gpr_avl updated = gpr_avl updated =
gpr_avl_remove(gpr_avl_ref(index, exec_ctx), key, exec_ctx); gpr_avl_remove(gpr_avl_ref(index, grpc_core::ExecCtx::Get()), key,
grpc_core::ExecCtx::Get());
gpr_mu_lock(&g_mu); gpr_mu_lock(&g_mu);
if (index.root == g_subchannel_index.root) { if (index.root == g_subchannel_index.root) {
@ -241,8 +238,8 @@ void grpc_subchannel_index_unregister(grpc_exec_ctx* exec_ctx,
} }
gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_mu);
gpr_avl_unref(updated, exec_ctx); gpr_avl_unref(updated, grpc_core::ExecCtx::Get());
gpr_avl_unref(index, exec_ctx); gpr_avl_unref(index, grpc_core::ExecCtx::Get());
} }
} }

@ -29,26 +29,22 @@ grpc_subchannel_key* grpc_subchannel_key_create(
const grpc_subchannel_args* args); const grpc_subchannel_args* args);
/** Destroy a subchannel key */ /** Destroy a subchannel key */
void grpc_subchannel_key_destroy(grpc_exec_ctx* exec_ctx, void grpc_subchannel_key_destroy(grpc_subchannel_key* key);
grpc_subchannel_key* key);
/** Given a subchannel key, find the subchannel registered for it. /** Given a subchannel key, find the subchannel registered for it.
Returns NULL if no such channel exists. Returns NULL if no such channel exists.
Thread-safe. */ Thread-safe. */
grpc_subchannel* grpc_subchannel_index_find(grpc_exec_ctx* exec_ctx, grpc_subchannel* grpc_subchannel_index_find(grpc_subchannel_key* key);
grpc_subchannel_key* key);
/** Register a subchannel against a key. /** Register a subchannel against a key.
Takes ownership of \a constructed. Takes ownership of \a constructed.
Returns the registered subchannel. This may be different from Returns the registered subchannel. This may be different from
\a constructed in the case of a registration race. */ \a constructed in the case of a registration race. */
grpc_subchannel* grpc_subchannel_index_register(grpc_exec_ctx* exec_ctx, grpc_subchannel* grpc_subchannel_index_register(grpc_subchannel_key* key,
grpc_subchannel_key* key,
grpc_subchannel* constructed); grpc_subchannel* constructed);
/** Remove \a constructed as the registered subchannel for \a key. */ /** Remove \a constructed as the registered subchannel for \a key. */
void grpc_subchannel_index_unregister(grpc_exec_ctx* exec_ctx, void grpc_subchannel_index_unregister(grpc_subchannel_key* key,
grpc_subchannel_key* key,
grpc_subchannel* constructed); grpc_subchannel* constructed);
int grpc_subchannel_key_compare(const grpc_subchannel_key* a, int grpc_subchannel_key_compare(const grpc_subchannel_key* a,

@ -56,8 +56,8 @@ static grpc_uri* bad_uri(const char* uri_text, size_t pos, const char* section,
} }
/** Returns a copy of percent decoded \a src[begin, end) */ /** Returns a copy of percent decoded \a src[begin, end) */
static char* decode_and_copy_component(grpc_exec_ctx* exec_ctx, const char* src, static char* decode_and_copy_component(const char* src, size_t begin,
size_t begin, size_t end) { size_t end) {
grpc_slice component = grpc_slice component =
(begin == NOT_SET || end == NOT_SET) (begin == NOT_SET || end == NOT_SET)
? grpc_empty_slice() ? grpc_empty_slice()
@ -65,8 +65,8 @@ static char* decode_and_copy_component(grpc_exec_ctx* exec_ctx, const char* src,
grpc_slice decoded_component = grpc_slice decoded_component =
grpc_permissive_percent_decode_slice(component); grpc_permissive_percent_decode_slice(component);
char* out = grpc_dump_slice(decoded_component, GPR_DUMP_ASCII); char* out = grpc_dump_slice(decoded_component, GPR_DUMP_ASCII);
grpc_slice_unref_internal(exec_ctx, component); grpc_slice_unref_internal(component);
grpc_slice_unref_internal(exec_ctx, decoded_component); grpc_slice_unref_internal(decoded_component);
return out; return out;
} }
@ -184,8 +184,7 @@ static void parse_query_parts(grpc_uri* uri) {
} }
} }
grpc_uri* grpc_uri_parse(grpc_exec_ctx* exec_ctx, const char* uri_text, grpc_uri* grpc_uri_parse(const char* uri_text, bool suppress_errors) {
bool suppress_errors) {
grpc_uri* uri; grpc_uri* uri;
size_t scheme_begin = 0; size_t scheme_begin = 0;
size_t scheme_end = NOT_SET; size_t scheme_end = NOT_SET;
@ -273,16 +272,13 @@ grpc_uri* grpc_uri_parse(grpc_exec_ctx* exec_ctx, const char* uri_text,
} }
uri = (grpc_uri*)gpr_zalloc(sizeof(*uri)); uri = (grpc_uri*)gpr_zalloc(sizeof(*uri));
uri->scheme = uri->scheme = decode_and_copy_component(uri_text, scheme_begin, scheme_end);
decode_and_copy_component(exec_ctx, uri_text, scheme_begin, scheme_end); uri->authority =
uri->authority = decode_and_copy_component(exec_ctx, uri_text, decode_and_copy_component(uri_text, authority_begin, authority_end);
authority_begin, authority_end); uri->path = decode_and_copy_component(uri_text, path_begin, path_end);
uri->path = uri->query = decode_and_copy_component(uri_text, query_begin, query_end);
decode_and_copy_component(exec_ctx, uri_text, path_begin, path_end); uri->fragment =
uri->query = decode_and_copy_component(uri_text, fragment_begin, fragment_end);
decode_and_copy_component(exec_ctx, uri_text, query_begin, query_end);
uri->fragment = decode_and_copy_component(exec_ctx, uri_text, fragment_begin,
fragment_end);
parse_query_parts(uri); parse_query_parts(uri);
return uri; return uri;

@ -37,8 +37,7 @@ typedef struct {
} grpc_uri; } grpc_uri;
/** parse a uri, return NULL on failure */ /** parse a uri, return NULL on failure */
grpc_uri* grpc_uri_parse(grpc_exec_ctx* exec_ctx, const char* uri_text, grpc_uri* grpc_uri_parse(const char* uri_text, bool suppress_errors);
bool suppress_errors);
/** return the part of a query string after the '=' in "?key=xxx&...", or NULL /** return the part of a query string after the '=' in "?key=xxx&...", or NULL
* if key is not present */ * if key is not present */

@ -36,18 +36,16 @@
// The on_complete callback used when sending a cancel_error batch down the // The on_complete callback used when sending a cancel_error batch down the
// filter stack. Yields the call combiner when the batch returns. // filter stack. Yields the call combiner when the batch returns.
static void yield_call_combiner(grpc_exec_ctx* exec_ctx, void* arg, static void yield_call_combiner(void* arg, grpc_error* ignored) {
grpc_error* ignored) {
grpc_deadline_state* deadline_state = (grpc_deadline_state*)arg; grpc_deadline_state* deadline_state = (grpc_deadline_state*)arg;
GRPC_CALL_COMBINER_STOP(exec_ctx, deadline_state->call_combiner, GRPC_CALL_COMBINER_STOP(deadline_state->call_combiner,
"got on_complete from cancel_stream batch"); "got on_complete from cancel_stream batch");
GRPC_CALL_STACK_UNREF(exec_ctx, deadline_state->call_stack, "deadline_timer"); GRPC_CALL_STACK_UNREF(deadline_state->call_stack, "deadline_timer");
} }
// This is called via the call combiner, so access to deadline_state is // This is called via the call combiner, so access to deadline_state is
// synchronized. // synchronized.
static void send_cancel_op_in_call_combiner(grpc_exec_ctx* exec_ctx, void* arg, static void send_cancel_op_in_call_combiner(void* arg, grpc_error* error) {
grpc_error* error) {
grpc_call_element* elem = (grpc_call_element*)arg; grpc_call_element* elem = (grpc_call_element*)arg;
grpc_deadline_state* deadline_state = (grpc_deadline_state*)elem->call_data; grpc_deadline_state* deadline_state = (grpc_deadline_state*)elem->call_data;
grpc_transport_stream_op_batch* batch = grpc_make_transport_stream_op( grpc_transport_stream_op_batch* batch = grpc_make_transport_stream_op(
@ -55,37 +53,34 @@ static void send_cancel_op_in_call_combiner(grpc_exec_ctx* exec_ctx, void* arg,
deadline_state, grpc_schedule_on_exec_ctx)); deadline_state, grpc_schedule_on_exec_ctx));
batch->cancel_stream = true; batch->cancel_stream = true;
batch->payload->cancel_stream.cancel_error = GRPC_ERROR_REF(error); batch->payload->cancel_stream.cancel_error = GRPC_ERROR_REF(error);
elem->filter->start_transport_stream_op_batch(exec_ctx, elem, batch); elem->filter->start_transport_stream_op_batch(elem, batch);
} }
// Timer callback. // Timer callback.
static void timer_callback(grpc_exec_ctx* exec_ctx, void* arg, static void timer_callback(void* arg, grpc_error* error) {
grpc_error* error) {
grpc_call_element* elem = (grpc_call_element*)arg; grpc_call_element* elem = (grpc_call_element*)arg;
grpc_deadline_state* deadline_state = (grpc_deadline_state*)elem->call_data; grpc_deadline_state* deadline_state = (grpc_deadline_state*)elem->call_data;
if (error != GRPC_ERROR_CANCELLED) { if (error != GRPC_ERROR_CANCELLED) {
error = grpc_error_set_int( error = grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Deadline Exceeded"), GRPC_ERROR_CREATE_FROM_STATIC_STRING("Deadline Exceeded"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_DEADLINE_EXCEEDED); GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_DEADLINE_EXCEEDED);
grpc_call_combiner_cancel(exec_ctx, deadline_state->call_combiner, grpc_call_combiner_cancel(deadline_state->call_combiner,
GRPC_ERROR_REF(error)); GRPC_ERROR_REF(error));
GRPC_CLOSURE_INIT(&deadline_state->timer_callback, GRPC_CLOSURE_INIT(&deadline_state->timer_callback,
send_cancel_op_in_call_combiner, elem, send_cancel_op_in_call_combiner, elem,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
GRPC_CALL_COMBINER_START(exec_ctx, deadline_state->call_combiner, GRPC_CALL_COMBINER_START(deadline_state->call_combiner,
&deadline_state->timer_callback, error, &deadline_state->timer_callback, error,
"deadline exceeded -- sending cancel_stream op"); "deadline exceeded -- sending cancel_stream op");
} else { } else {
GRPC_CALL_STACK_UNREF(exec_ctx, deadline_state->call_stack, GRPC_CALL_STACK_UNREF(deadline_state->call_stack, "deadline_timer");
"deadline_timer");
} }
} }
// Starts the deadline timer. // Starts the deadline timer.
// This is called via the call combiner, so access to deadline_state is // This is called via the call combiner, so access to deadline_state is
// synchronized. // synchronized.
static void start_timer_if_needed(grpc_exec_ctx* exec_ctx, static void start_timer_if_needed(grpc_call_element* elem,
grpc_call_element* elem,
grpc_millis deadline) { grpc_millis deadline) {
if (deadline == GRPC_MILLIS_INF_FUTURE) { if (deadline == GRPC_MILLIS_INF_FUTURE) {
return; return;
@ -113,17 +108,16 @@ static void start_timer_if_needed(grpc_exec_ctx* exec_ctx,
} }
GPR_ASSERT(closure != nullptr); GPR_ASSERT(closure != nullptr);
GRPC_CALL_STACK_REF(deadline_state->call_stack, "deadline_timer"); GRPC_CALL_STACK_REF(deadline_state->call_stack, "deadline_timer");
grpc_timer_init(exec_ctx, &deadline_state->timer, deadline, closure); grpc_timer_init(&deadline_state->timer, deadline, closure);
} }
// Cancels the deadline timer. // Cancels the deadline timer.
// This is called via the call combiner, so access to deadline_state is // This is called via the call combiner, so access to deadline_state is
// synchronized. // synchronized.
static void cancel_timer_if_needed(grpc_exec_ctx* exec_ctx, static void cancel_timer_if_needed(grpc_deadline_state* deadline_state) {
grpc_deadline_state* deadline_state) {
if (deadline_state->timer_state == GRPC_DEADLINE_STATE_PENDING) { if (deadline_state->timer_state == GRPC_DEADLINE_STATE_PENDING) {
deadline_state->timer_state = GRPC_DEADLINE_STATE_FINISHED; deadline_state->timer_state = GRPC_DEADLINE_STATE_FINISHED;
grpc_timer_cancel(exec_ctx, &deadline_state->timer); grpc_timer_cancel(&deadline_state->timer);
} else { } else {
// timer was either in STATE_INITAL (nothing to cancel) // timer was either in STATE_INITAL (nothing to cancel)
// OR in STATE_FINISHED (again nothing to cancel) // OR in STATE_FINISHED (again nothing to cancel)
@ -131,12 +125,11 @@ static void cancel_timer_if_needed(grpc_exec_ctx* exec_ctx,
} }
// Callback run when the call is complete. // Callback run when the call is complete.
static void on_complete(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { static void on_complete(void* arg, grpc_error* error) {
grpc_deadline_state* deadline_state = (grpc_deadline_state*)arg; grpc_deadline_state* deadline_state = (grpc_deadline_state*)arg;
cancel_timer_if_needed(exec_ctx, deadline_state); cancel_timer_if_needed(deadline_state);
// Invoke the next callback. // Invoke the next callback.
GRPC_CLOSURE_RUN(exec_ctx, deadline_state->next_on_complete, GRPC_CLOSURE_RUN(deadline_state->next_on_complete, GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error));
} }
// Inject our own on_complete callback into op. // Inject our own on_complete callback into op.
@ -156,8 +149,7 @@ struct start_timer_after_init_state {
grpc_millis deadline; grpc_millis deadline;
grpc_closure closure; grpc_closure closure;
}; };
static void start_timer_after_init(grpc_exec_ctx* exec_ctx, void* arg, static void start_timer_after_init(void* arg, grpc_error* error) {
grpc_error* error) {
struct start_timer_after_init_state* state = struct start_timer_after_init_state* state =
(struct start_timer_after_init_state*)arg; (struct start_timer_after_init_state*)arg;
grpc_deadline_state* deadline_state = grpc_deadline_state* deadline_state =
@ -166,18 +158,18 @@ static void start_timer_after_init(grpc_exec_ctx* exec_ctx, void* arg,
// We are initially called without holding the call combiner, so we // We are initially called without holding the call combiner, so we
// need to bounce ourselves into it. // need to bounce ourselves into it.
state->in_call_combiner = true; state->in_call_combiner = true;
GRPC_CALL_COMBINER_START(exec_ctx, deadline_state->call_combiner, GRPC_CALL_COMBINER_START(deadline_state->call_combiner, &state->closure,
&state->closure, GRPC_ERROR_REF(error), GRPC_ERROR_REF(error),
"scheduling deadline timer"); "scheduling deadline timer");
return; return;
} }
start_timer_if_needed(exec_ctx, state->elem, state->deadline); start_timer_if_needed(state->elem, state->deadline);
gpr_free(state); gpr_free(state);
GRPC_CALL_COMBINER_STOP(exec_ctx, deadline_state->call_combiner, GRPC_CALL_COMBINER_STOP(deadline_state->call_combiner,
"done scheduling deadline timer"); "done scheduling deadline timer");
} }
void grpc_deadline_state_init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, void grpc_deadline_state_init(grpc_call_element* elem,
grpc_call_stack* call_stack, grpc_call_stack* call_stack,
grpc_call_combiner* call_combiner, grpc_call_combiner* call_combiner,
grpc_millis deadline) { grpc_millis deadline) {
@ -200,29 +192,27 @@ void grpc_deadline_state_init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
state->deadline = deadline; state->deadline = deadline;
GRPC_CLOSURE_INIT(&state->closure, start_timer_after_init, state, GRPC_CLOSURE_INIT(&state->closure, start_timer_after_init, state,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_SCHED(exec_ctx, &state->closure, GRPC_ERROR_NONE); GRPC_CLOSURE_SCHED(&state->closure, GRPC_ERROR_NONE);
} }
} }
void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx, void grpc_deadline_state_destroy(grpc_call_element* elem) {
grpc_call_element* elem) {
grpc_deadline_state* deadline_state = (grpc_deadline_state*)elem->call_data; grpc_deadline_state* deadline_state = (grpc_deadline_state*)elem->call_data;
cancel_timer_if_needed(exec_ctx, deadline_state); cancel_timer_if_needed(deadline_state);
} }
void grpc_deadline_state_reset(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, void grpc_deadline_state_reset(grpc_call_element* elem,
grpc_millis new_deadline) { grpc_millis new_deadline) {
grpc_deadline_state* deadline_state = (grpc_deadline_state*)elem->call_data; grpc_deadline_state* deadline_state = (grpc_deadline_state*)elem->call_data;
cancel_timer_if_needed(exec_ctx, deadline_state); cancel_timer_if_needed(deadline_state);
start_timer_if_needed(exec_ctx, elem, new_deadline); start_timer_if_needed(elem, new_deadline);
} }
void grpc_deadline_state_client_start_transport_stream_op_batch( void grpc_deadline_state_client_start_transport_stream_op_batch(
grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_element* elem, grpc_transport_stream_op_batch* op) {
grpc_transport_stream_op_batch* op) {
grpc_deadline_state* deadline_state = (grpc_deadline_state*)elem->call_data; grpc_deadline_state* deadline_state = (grpc_deadline_state*)elem->call_data;
if (op->cancel_stream) { if (op->cancel_stream) {
cancel_timer_if_needed(exec_ctx, deadline_state); cancel_timer_if_needed(deadline_state);
} else { } else {
// Make sure we know when the call is complete, so that we can cancel // Make sure we know when the call is complete, so that we can cancel
// the timer. // the timer.
@ -237,16 +227,14 @@ void grpc_deadline_state_client_start_transport_stream_op_batch(
// //
// Constructor for channel_data. Used for both client and server filters. // Constructor for channel_data. Used for both client and server filters.
static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_channel_elem(grpc_channel_element* elem,
grpc_channel_element* elem,
grpc_channel_element_args* args) { grpc_channel_element_args* args) {
GPR_ASSERT(!args->is_last); GPR_ASSERT(!args->is_last);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
// Destructor for channel_data. Used for both client and server filters. // Destructor for channel_data. Used for both client and server filters.
static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, static void destroy_channel_elem(grpc_channel_element* elem) {}
grpc_channel_element* elem) {}
// Call data used for both client and server filter. // Call data used for both client and server filter.
typedef struct base_call_data { typedef struct base_call_data {
@ -266,50 +254,45 @@ typedef struct server_call_data {
} server_call_data; } server_call_data;
// Constructor for call_data. Used for both client and server filters. // Constructor for call_data. Used for both client and server filters.
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_call_elem(grpc_call_element* elem,
grpc_call_element* elem,
const grpc_call_element_args* args) { const grpc_call_element_args* args) {
grpc_deadline_state_init(exec_ctx, elem, args->call_stack, grpc_deadline_state_init(elem, args->call_stack, args->call_combiner,
args->call_combiner, args->deadline); args->deadline);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
// Destructor for call_data. Used for both client and server filters. // Destructor for call_data. Used for both client and server filters.
static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, static void destroy_call_elem(grpc_call_element* elem,
const grpc_call_final_info* final_info, const grpc_call_final_info* final_info,
grpc_closure* ignored) { grpc_closure* ignored) {
grpc_deadline_state_destroy(exec_ctx, elem); grpc_deadline_state_destroy(elem);
} }
// Method for starting a call op for client filter. // Method for starting a call op for client filter.
static void client_start_transport_stream_op_batch( static void client_start_transport_stream_op_batch(
grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_element* elem, grpc_transport_stream_op_batch* op) {
grpc_transport_stream_op_batch* op) { grpc_deadline_state_client_start_transport_stream_op_batch(elem, op);
grpc_deadline_state_client_start_transport_stream_op_batch(exec_ctx, elem,
op);
// Chain to next filter. // Chain to next filter.
grpc_call_next_op(exec_ctx, elem, op); grpc_call_next_op(elem, op);
} }
// Callback for receiving initial metadata on the server. // Callback for receiving initial metadata on the server.
static void recv_initial_metadata_ready(grpc_exec_ctx* exec_ctx, void* arg, static void recv_initial_metadata_ready(void* arg, grpc_error* error) {
grpc_error* error) {
grpc_call_element* elem = (grpc_call_element*)arg; grpc_call_element* elem = (grpc_call_element*)arg;
server_call_data* calld = (server_call_data*)elem->call_data; server_call_data* calld = (server_call_data*)elem->call_data;
// Get deadline from metadata and start the timer if needed. // Get deadline from metadata and start the timer if needed.
start_timer_if_needed(exec_ctx, elem, calld->recv_initial_metadata->deadline); start_timer_if_needed(elem, calld->recv_initial_metadata->deadline);
// Invoke the next callback. // Invoke the next callback.
calld->next_recv_initial_metadata_ready->cb( calld->next_recv_initial_metadata_ready->cb(
exec_ctx, calld->next_recv_initial_metadata_ready->cb_arg, error); calld->next_recv_initial_metadata_ready->cb_arg, error);
} }
// Method for starting a call op for server filter. // Method for starting a call op for server filter.
static void server_start_transport_stream_op_batch( static void server_start_transport_stream_op_batch(
grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_element* elem, grpc_transport_stream_op_batch* op) {
grpc_transport_stream_op_batch* op) {
server_call_data* calld = (server_call_data*)elem->call_data; server_call_data* calld = (server_call_data*)elem->call_data;
if (op->cancel_stream) { if (op->cancel_stream) {
cancel_timer_if_needed(exec_ctx, &calld->base.deadline_state); cancel_timer_if_needed(&calld->base.deadline_state);
} else { } else {
// If we're receiving initial metadata, we need to get the deadline // If we're receiving initial metadata, we need to get the deadline
// from the recv_initial_metadata_ready callback. So we inject our // from the recv_initial_metadata_ready callback. So we inject our
@ -335,7 +318,7 @@ static void server_start_transport_stream_op_batch(
} }
} }
// Chain to next filter. // Chain to next filter.
grpc_call_next_op(exec_ctx, elem, op); grpc_call_next_op(elem, op);
} }
const grpc_channel_filter grpc_client_deadline_filter = { const grpc_channel_filter grpc_client_deadline_filter = {
@ -372,8 +355,7 @@ bool grpc_deadline_checking_enabled(const grpc_channel_args* channel_args) {
!grpc_channel_args_want_minimal_stack(channel_args)); !grpc_channel_args_want_minimal_stack(channel_args));
} }
static bool maybe_add_deadline_filter(grpc_exec_ctx* exec_ctx, static bool maybe_add_deadline_filter(grpc_channel_stack_builder* builder,
grpc_channel_stack_builder* builder,
void* arg) { void* arg) {
return grpc_deadline_checking_enabled( return grpc_deadline_checking_enabled(
grpc_channel_stack_builder_get_channel_arguments(builder)) grpc_channel_stack_builder_get_channel_arguments(builder))

@ -49,13 +49,12 @@ typedef struct grpc_deadline_state {
// //
// assumes elem->call_data is zero'd // assumes elem->call_data is zero'd
void grpc_deadline_state_init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, void grpc_deadline_state_init(grpc_call_element* elem,
grpc_call_stack* call_stack, grpc_call_stack* call_stack,
grpc_call_combiner* call_combiner, grpc_call_combiner* call_combiner,
grpc_millis deadline); grpc_millis deadline);
void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx, void grpc_deadline_state_destroy(grpc_call_element* elem);
grpc_call_element* elem);
// Cancels the existing timer and starts a new one with new_deadline. // Cancels the existing timer and starts a new one with new_deadline.
// //
@ -66,7 +65,7 @@ void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx,
// deadline may result in the timer being called twice. // deadline may result in the timer being called twice.
// //
// Note: Must be called while holding the call combiner. // Note: Must be called while holding the call combiner.
void grpc_deadline_state_reset(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, void grpc_deadline_state_reset(grpc_call_element* elem,
grpc_millis new_deadline); grpc_millis new_deadline);
// To be called from the client-side filter's start_transport_stream_op_batch() // To be called from the client-side filter's start_transport_stream_op_batch()
@ -78,8 +77,7 @@ void grpc_deadline_state_reset(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
// //
// Note: Must be called while holding the call combiner. // Note: Must be called while holding the call combiner.
void grpc_deadline_state_client_start_transport_stream_op_batch( void grpc_deadline_state_client_start_transport_stream_op_batch(
grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_element* elem, grpc_transport_stream_op_batch* op);
grpc_transport_stream_op_batch* op);
// Should deadline checking be performed (according to channel args) // Should deadline checking be performed (according to channel args)
bool grpc_deadline_checking_enabled(const grpc_channel_args* args); bool grpc_deadline_checking_enabled(const grpc_channel_args* args);

@ -68,12 +68,11 @@ typedef struct channel_data {
size_t max_payload_size_for_get; size_t max_payload_size_for_get;
} channel_data; } channel_data;
static grpc_error* client_filter_incoming_metadata(grpc_exec_ctx* exec_ctx, static grpc_error* client_filter_incoming_metadata(grpc_call_element* elem,
grpc_call_element* elem,
grpc_metadata_batch* b) { grpc_metadata_batch* b) {
if (b->idx.named.status != nullptr) { if (b->idx.named.status != nullptr) {
if (grpc_mdelem_eq(b->idx.named.status->md, GRPC_MDELEM_STATUS_200)) { if (grpc_mdelem_eq(b->idx.named.status->md, GRPC_MDELEM_STATUS_200)) {
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.status); grpc_metadata_batch_remove(b, b->idx.named.status);
} else { } else {
char* val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.status->md), char* val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.status->md),
GPR_DUMP_ASCII); GPR_DUMP_ASCII);
@ -98,10 +97,9 @@ static grpc_error* client_filter_incoming_metadata(grpc_exec_ctx* exec_ctx,
GRPC_MDVALUE(b->idx.named.grpc_message->md)); GRPC_MDVALUE(b->idx.named.grpc_message->md));
if (grpc_slice_is_equivalent(pct_decoded_msg, if (grpc_slice_is_equivalent(pct_decoded_msg,
GRPC_MDVALUE(b->idx.named.grpc_message->md))) { GRPC_MDVALUE(b->idx.named.grpc_message->md))) {
grpc_slice_unref_internal(exec_ctx, pct_decoded_msg); grpc_slice_unref_internal(pct_decoded_msg);
} else { } else {
grpc_metadata_batch_set_value(exec_ctx, b->idx.named.grpc_message, grpc_metadata_batch_set_value(b->idx.named.grpc_message, pct_decoded_msg);
pct_decoded_msg);
} }
} }
@ -131,60 +129,53 @@ static grpc_error* client_filter_incoming_metadata(grpc_exec_ctx* exec_ctx,
gpr_free(val); gpr_free(val);
} }
} }
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.content_type); grpc_metadata_batch_remove(b, b->idx.named.content_type);
} }
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
static void recv_initial_metadata_ready(grpc_exec_ctx* exec_ctx, static void recv_initial_metadata_ready(void* user_data, grpc_error* error) {
void* user_data, grpc_error* error) {
grpc_call_element* elem = (grpc_call_element*)user_data; grpc_call_element* elem = (grpc_call_element*)user_data;
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
error = client_filter_incoming_metadata(exec_ctx, elem, error = client_filter_incoming_metadata(elem, calld->recv_initial_metadata);
calld->recv_initial_metadata);
} else { } else {
GRPC_ERROR_REF(error); GRPC_ERROR_REF(error);
} }
GRPC_CLOSURE_RUN(exec_ctx, calld->original_recv_initial_metadata_ready, GRPC_CLOSURE_RUN(calld->original_recv_initial_metadata_ready, error);
error);
} }
static void recv_trailing_metadata_on_complete(grpc_exec_ctx* exec_ctx, static void recv_trailing_metadata_on_complete(void* user_data,
void* user_data,
grpc_error* error) { grpc_error* error) {
grpc_call_element* elem = (grpc_call_element*)user_data; grpc_call_element* elem = (grpc_call_element*)user_data;
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
error = client_filter_incoming_metadata(exec_ctx, elem, error =
calld->recv_trailing_metadata); client_filter_incoming_metadata(elem, calld->recv_trailing_metadata);
} else { } else {
GRPC_ERROR_REF(error); GRPC_ERROR_REF(error);
} }
GRPC_CLOSURE_RUN(exec_ctx, calld->original_recv_trailing_metadata_on_complete, GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_on_complete, error);
error);
} }
static void send_message_on_complete(grpc_exec_ctx* exec_ctx, void* arg, static void send_message_on_complete(void* arg, grpc_error* error) {
grpc_error* error) {
grpc_call_element* elem = (grpc_call_element*)arg; grpc_call_element* elem = (grpc_call_element*)arg;
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
grpc_byte_stream_cache_destroy(exec_ctx, &calld->send_message_cache); grpc_byte_stream_cache_destroy(&calld->send_message_cache);
GRPC_CLOSURE_RUN(exec_ctx, calld->original_send_message_on_complete, GRPC_CLOSURE_RUN(calld->original_send_message_on_complete,
GRPC_ERROR_REF(error)); GRPC_ERROR_REF(error));
} }
// Pulls a slice from the send_message byte stream, updating // Pulls a slice from the send_message byte stream, updating
// calld->send_message_bytes_read. // calld->send_message_bytes_read.
static grpc_error* pull_slice_from_send_message(grpc_exec_ctx* exec_ctx, static grpc_error* pull_slice_from_send_message(call_data* calld) {
call_data* calld) {
grpc_slice incoming_slice; grpc_slice incoming_slice;
grpc_error* error = grpc_byte_stream_pull( grpc_error* error = grpc_byte_stream_pull(
exec_ctx, &calld->send_message_caching_stream.base, &incoming_slice); &calld->send_message_caching_stream.base, &incoming_slice);
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
calld->send_message_bytes_read += GRPC_SLICE_LENGTH(incoming_slice); calld->send_message_bytes_read += GRPC_SLICE_LENGTH(incoming_slice);
grpc_slice_unref_internal(exec_ctx, incoming_slice); grpc_slice_unref_internal(incoming_slice);
} }
return error; return error;
} }
@ -194,12 +185,10 @@ static grpc_error* pull_slice_from_send_message(grpc_exec_ctx* exec_ctx,
// calld->send_message_caching_stream.base.length, then we have completed // calld->send_message_caching_stream.base.length, then we have completed
// reading from the byte stream; otherwise, an async read has been dispatched // reading from the byte stream; otherwise, an async read has been dispatched
// and on_send_message_next_done() will be invoked when it is complete. // and on_send_message_next_done() will be invoked when it is complete.
static grpc_error* read_all_available_send_message_data(grpc_exec_ctx* exec_ctx, static grpc_error* read_all_available_send_message_data(call_data* calld) {
call_data* calld) { while (grpc_byte_stream_next(&calld->send_message_caching_stream.base,
while (grpc_byte_stream_next(exec_ctx,
&calld->send_message_caching_stream.base,
~(size_t)0, &calld->on_send_message_next_done)) { ~(size_t)0, &calld->on_send_message_next_done)) {
grpc_error* error = pull_slice_from_send_message(exec_ctx, calld); grpc_error* error = pull_slice_from_send_message(calld);
if (error != GRPC_ERROR_NONE) return error; if (error != GRPC_ERROR_NONE) return error;
if (calld->send_message_bytes_read == if (calld->send_message_bytes_read ==
calld->send_message_caching_stream.base.length) { calld->send_message_caching_stream.base.length) {
@ -210,19 +199,18 @@ static grpc_error* read_all_available_send_message_data(grpc_exec_ctx* exec_ctx,
} }
// Async callback for grpc_byte_stream_next(). // Async callback for grpc_byte_stream_next().
static void on_send_message_next_done(grpc_exec_ctx* exec_ctx, void* arg, static void on_send_message_next_done(void* arg, grpc_error* error) {
grpc_error* error) {
grpc_call_element* elem = (grpc_call_element*)arg; grpc_call_element* elem = (grpc_call_element*)arg;
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
grpc_transport_stream_op_batch_finish_with_failure( grpc_transport_stream_op_batch_finish_with_failure(
exec_ctx, calld->send_message_batch, error, calld->call_combiner); calld->send_message_batch, error, calld->call_combiner);
return; return;
} }
error = pull_slice_from_send_message(exec_ctx, calld); error = pull_slice_from_send_message(calld);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
grpc_transport_stream_op_batch_finish_with_failure( grpc_transport_stream_op_batch_finish_with_failure(
exec_ctx, calld->send_message_batch, error, calld->call_combiner); calld->send_message_batch, error, calld->call_combiner);
return; return;
} }
// There may or may not be more to read, but we don't care. If we got // There may or may not be more to read, but we don't care. If we got
@ -230,7 +218,7 @@ static void on_send_message_next_done(grpc_exec_ctx* exec_ctx, void* arg,
// synchronously, so we were not able to do a cached call. Instead, // synchronously, so we were not able to do a cached call. Instead,
// we just reset the byte stream and then send down the batch as-is. // we just reset the byte stream and then send down the batch as-is.
grpc_caching_byte_stream_reset(&calld->send_message_caching_stream); grpc_caching_byte_stream_reset(&calld->send_message_caching_stream);
grpc_call_next_op(exec_ctx, elem, calld->send_message_batch); grpc_call_next_op(elem, calld->send_message_batch);
} }
static char* slice_buffer_to_string(grpc_slice_buffer* slice_buffer) { static char* slice_buffer_to_string(grpc_slice_buffer* slice_buffer) {
@ -248,8 +236,7 @@ static char* slice_buffer_to_string(grpc_slice_buffer* slice_buffer) {
// Modifies the path entry in the batch's send_initial_metadata to // Modifies the path entry in the batch's send_initial_metadata to
// append the base64-encoded query for a GET request. // append the base64-encoded query for a GET request.
static grpc_error* update_path_for_get(grpc_exec_ctx* exec_ctx, static grpc_error* update_path_for_get(grpc_call_element* elem,
grpc_call_element* elem,
grpc_transport_stream_op_batch* batch) { grpc_transport_stream_op_batch* batch) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
grpc_slice path_slice = grpc_slice path_slice =
@ -282,24 +269,22 @@ static grpc_error* update_path_for_get(grpc_exec_ctx* exec_ctx,
grpc_slice_sub_no_ref(path_with_query_slice, 0, strlen(t)); grpc_slice_sub_no_ref(path_with_query_slice, 0, strlen(t));
/* substitute previous path with the new path+query */ /* substitute previous path with the new path+query */
grpc_mdelem mdelem_path_and_query = grpc_mdelem mdelem_path_and_query =
grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_PATH, path_with_query_slice); grpc_mdelem_from_slices(GRPC_MDSTR_PATH, path_with_query_slice);
grpc_metadata_batch* b = grpc_metadata_batch* b =
batch->payload->send_initial_metadata.send_initial_metadata; batch->payload->send_initial_metadata.send_initial_metadata;
return grpc_metadata_batch_substitute(exec_ctx, b, b->idx.named.path, return grpc_metadata_batch_substitute(b, b->idx.named.path,
mdelem_path_and_query); mdelem_path_and_query);
} }
static void remove_if_present(grpc_exec_ctx* exec_ctx, static void remove_if_present(grpc_metadata_batch* batch,
grpc_metadata_batch* batch,
grpc_metadata_batch_callouts_index idx) { grpc_metadata_batch_callouts_index idx) {
if (batch->idx.array[idx] != nullptr) { if (batch->idx.array[idx] != nullptr) {
grpc_metadata_batch_remove(exec_ctx, batch, batch->idx.array[idx]); grpc_metadata_batch_remove(batch, batch->idx.array[idx]);
} }
} }
static void hc_start_transport_stream_op_batch( static void hc_start_transport_stream_op_batch(
grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_element* elem, grpc_transport_stream_op_batch* batch) {
grpc_transport_stream_op_batch* batch) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
channel_data* channeld = (channel_data*)elem->channel_data; channel_data* channeld = (channel_data*)elem->channel_data;
GPR_TIMER_BEGIN("hc_start_transport_stream_op_batch", 0); GPR_TIMER_BEGIN("hc_start_transport_stream_op_batch", 0);
@ -345,17 +330,16 @@ static void hc_start_transport_stream_op_batch(
calld->original_send_message_on_complete = batch->on_complete; calld->original_send_message_on_complete = batch->on_complete;
batch->on_complete = &calld->send_message_on_complete; batch->on_complete = &calld->send_message_on_complete;
calld->send_message_batch = batch; calld->send_message_batch = batch;
error = read_all_available_send_message_data(exec_ctx, calld); error = read_all_available_send_message_data(calld);
if (error != GRPC_ERROR_NONE) goto done; if (error != GRPC_ERROR_NONE) goto done;
// If all the data has been read, then we can use GET. // If all the data has been read, then we can use GET.
if (calld->send_message_bytes_read == if (calld->send_message_bytes_read ==
calld->send_message_caching_stream.base.length) { calld->send_message_caching_stream.base.length) {
method = GRPC_MDELEM_METHOD_GET; method = GRPC_MDELEM_METHOD_GET;
error = update_path_for_get(exec_ctx, elem, batch); error = update_path_for_get(elem, batch);
if (error != GRPC_ERROR_NONE) goto done; if (error != GRPC_ERROR_NONE) goto done;
batch->send_message = false; batch->send_message = false;
grpc_byte_stream_destroy(exec_ctx, grpc_byte_stream_destroy(&calld->send_message_caching_stream.base);
&calld->send_message_caching_stream.base);
} else { } else {
// Not all data is available. The batch will be sent down // Not all data is available. The batch will be sent down
// asynchronously in on_send_message_next_done(). // asynchronously in on_send_message_next_done().
@ -372,41 +356,41 @@ static void hc_start_transport_stream_op_batch(
} }
remove_if_present( remove_if_present(
exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata, batch->payload->send_initial_metadata.send_initial_metadata,
GRPC_BATCH_METHOD); GRPC_BATCH_METHOD);
remove_if_present( remove_if_present(
exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata, batch->payload->send_initial_metadata.send_initial_metadata,
GRPC_BATCH_SCHEME); GRPC_BATCH_SCHEME);
remove_if_present( remove_if_present(
exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata, batch->payload->send_initial_metadata.send_initial_metadata,
GRPC_BATCH_TE); GRPC_BATCH_TE);
remove_if_present( remove_if_present(
exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata, batch->payload->send_initial_metadata.send_initial_metadata,
GRPC_BATCH_CONTENT_TYPE); GRPC_BATCH_CONTENT_TYPE);
remove_if_present( remove_if_present(
exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata, batch->payload->send_initial_metadata.send_initial_metadata,
GRPC_BATCH_USER_AGENT); GRPC_BATCH_USER_AGENT);
/* Send : prefixed headers, which have to be before any application /* Send : prefixed headers, which have to be before any application
layer headers. */ layer headers. */
error = grpc_metadata_batch_add_head( error = grpc_metadata_batch_add_head(
exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata, batch->payload->send_initial_metadata.send_initial_metadata,
&calld->method, method); &calld->method, method);
if (error != GRPC_ERROR_NONE) goto done; if (error != GRPC_ERROR_NONE) goto done;
error = grpc_metadata_batch_add_head( error = grpc_metadata_batch_add_head(
exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata, batch->payload->send_initial_metadata.send_initial_metadata,
&calld->scheme, channeld->static_scheme); &calld->scheme, channeld->static_scheme);
if (error != GRPC_ERROR_NONE) goto done; if (error != GRPC_ERROR_NONE) goto done;
error = grpc_metadata_batch_add_tail( error = grpc_metadata_batch_add_tail(
exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata, batch->payload->send_initial_metadata.send_initial_metadata,
&calld->te_trailers, GRPC_MDELEM_TE_TRAILERS); &calld->te_trailers, GRPC_MDELEM_TE_TRAILERS);
if (error != GRPC_ERROR_NONE) goto done; if (error != GRPC_ERROR_NONE) goto done;
error = grpc_metadata_batch_add_tail( error = grpc_metadata_batch_add_tail(
exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata, batch->payload->send_initial_metadata.send_initial_metadata,
&calld->content_type, GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC); &calld->content_type, GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC);
if (error != GRPC_ERROR_NONE) goto done; if (error != GRPC_ERROR_NONE) goto done;
error = grpc_metadata_batch_add_tail( error = grpc_metadata_batch_add_tail(
exec_ctx, batch->payload->send_initial_metadata.send_initial_metadata, batch->payload->send_initial_metadata.send_initial_metadata,
&calld->user_agent, GRPC_MDELEM_REF(channeld->user_agent)); &calld->user_agent, GRPC_MDELEM_REF(channeld->user_agent));
if (error != GRPC_ERROR_NONE) goto done; if (error != GRPC_ERROR_NONE) goto done;
} }
@ -414,16 +398,15 @@ static void hc_start_transport_stream_op_batch(
done: done:
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
grpc_transport_stream_op_batch_finish_with_failure( grpc_transport_stream_op_batch_finish_with_failure(
exec_ctx, calld->send_message_batch, error, calld->call_combiner); calld->send_message_batch, error, calld->call_combiner);
} else if (!batch_will_be_handled_asynchronously) { } else if (!batch_will_be_handled_asynchronously) {
grpc_call_next_op(exec_ctx, elem, batch); grpc_call_next_op(elem, batch);
} }
GPR_TIMER_END("hc_start_transport_stream_op_batch", 0); GPR_TIMER_END("hc_start_transport_stream_op_batch", 0);
} }
/* Constructor for call_data */ /* Constructor for call_data */
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_call_elem(grpc_call_element* elem,
grpc_call_element* elem,
const grpc_call_element_args* args) { const grpc_call_element_args* args) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
calld->call_combiner = args->call_combiner; calld->call_combiner = args->call_combiner;
@ -441,7 +424,7 @@ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
} }
/* Destructor for call_data */ /* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, static void destroy_call_elem(grpc_call_element* elem,
const grpc_call_final_info* final_info, const grpc_call_final_info* final_info,
grpc_closure* ignored) {} grpc_closure* ignored) {}
@ -533,8 +516,7 @@ static grpc_slice user_agent_from_args(const grpc_channel_args* args,
} }
/* Constructor for channel_data */ /* Constructor for channel_data */
static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_channel_elem(grpc_channel_element* elem,
grpc_channel_element* elem,
grpc_channel_element_args* args) { grpc_channel_element_args* args) {
channel_data* chand = (channel_data*)elem->channel_data; channel_data* chand = (channel_data*)elem->channel_data;
GPR_ASSERT(!args->is_last); GPR_ASSERT(!args->is_last);
@ -543,17 +525,16 @@ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
chand->max_payload_size_for_get = chand->max_payload_size_for_get =
max_payload_size_from_args(args->channel_args); max_payload_size_from_args(args->channel_args);
chand->user_agent = grpc_mdelem_from_slices( chand->user_agent = grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_USER_AGENT, GRPC_MDSTR_USER_AGENT,
user_agent_from_args(args->channel_args, user_agent_from_args(args->channel_args,
args->optional_transport->vtable->name)); args->optional_transport->vtable->name));
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
/* Destructor for channel data */ /* Destructor for channel data */
static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, static void destroy_channel_elem(grpc_channel_element* elem) {
grpc_channel_element* elem) {
channel_data* chand = (channel_data*)elem->channel_data; channel_data* chand = (channel_data*)elem->channel_data;
GRPC_MDELEM_UNREF(exec_ctx, chand->user_agent); GRPC_MDELEM_UNREF(chand->user_agent);
} }
const grpc_channel_filter grpc_http_client_filter = { const grpc_channel_filter grpc_http_client_filter = {

@ -40,8 +40,7 @@ static bool is_building_http_like_transport(
return t != nullptr && strstr(t->vtable->name, "http"); return t != nullptr && strstr(t->vtable->name, "http");
} }
static bool maybe_add_optional_filter(grpc_exec_ctx* exec_ctx, static bool maybe_add_optional_filter(grpc_channel_stack_builder* builder,
grpc_channel_stack_builder* builder,
void* arg) { void* arg) {
if (!is_building_http_like_transport(builder)) return true; if (!is_building_http_like_transport(builder)) return true;
optional_filter* filtarg = (optional_filter*)arg; optional_filter* filtarg = (optional_filter*)arg;
@ -55,8 +54,7 @@ static bool maybe_add_optional_filter(grpc_exec_ctx* exec_ctx,
: true; : true;
} }
static bool maybe_add_required_filter(grpc_exec_ctx* exec_ctx, static bool maybe_add_required_filter(grpc_channel_stack_builder* builder,
grpc_channel_stack_builder* builder,
void* arg) { void* arg) {
return is_building_http_like_transport(builder) return is_building_http_like_transport(builder)
? grpc_channel_stack_builder_prepend_filter( ? grpc_channel_stack_builder_prepend_filter(

@ -100,12 +100,11 @@ static bool skip_compression(grpc_call_element* elem, uint32_t flags,
/** Filter initial metadata */ /** Filter initial metadata */
static grpc_error* process_send_initial_metadata( static grpc_error* process_send_initial_metadata(
grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_element* elem, grpc_metadata_batch* initial_metadata,
grpc_metadata_batch* initial_metadata,
bool* has_compression_algorithm) GRPC_MUST_USE_RESULT; bool* has_compression_algorithm) GRPC_MUST_USE_RESULT;
static grpc_error* process_send_initial_metadata( static grpc_error* process_send_initial_metadata(
grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_element* elem, grpc_metadata_batch* initial_metadata,
grpc_metadata_batch* initial_metadata, bool* has_compression_algorithm) { bool* has_compression_algorithm) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
channel_data* channeld = (channel_data*)elem->channel_data; channel_data* channeld = (channel_data*)elem->channel_data;
*has_compression_algorithm = false; *has_compression_algorithm = false;
@ -137,13 +136,13 @@ static grpc_error* process_send_initial_metadata(
} }
*has_compression_algorithm = true; *has_compression_algorithm = true;
grpc_metadata_batch_remove( grpc_metadata_batch_remove(
exec_ctx, initial_metadata, initial_metadata,
initial_metadata->idx.named.grpc_internal_stream_encoding_request); initial_metadata->idx.named.grpc_internal_stream_encoding_request);
/* Disable message-wise compression */ /* Disable message-wise compression */
calld->compression_algorithm = GRPC_COMPRESS_NONE; calld->compression_algorithm = GRPC_COMPRESS_NONE;
if (initial_metadata->idx.named.grpc_internal_encoding_request != nullptr) { if (initial_metadata->idx.named.grpc_internal_encoding_request != nullptr) {
grpc_metadata_batch_remove( grpc_metadata_batch_remove(
exec_ctx, initial_metadata, initial_metadata,
initial_metadata->idx.named.grpc_internal_encoding_request); initial_metadata->idx.named.grpc_internal_encoding_request);
} }
} else if (initial_metadata->idx.named.grpc_internal_encoding_request != } else if (initial_metadata->idx.named.grpc_internal_encoding_request !=
@ -160,7 +159,7 @@ static grpc_error* process_send_initial_metadata(
} }
*has_compression_algorithm = true; *has_compression_algorithm = true;
grpc_metadata_batch_remove( grpc_metadata_batch_remove(
exec_ctx, initial_metadata, initial_metadata,
initial_metadata->idx.named.grpc_internal_encoding_request); initial_metadata->idx.named.grpc_internal_encoding_request);
} else { } else {
/* If no algorithm was found in the metadata and we aren't /* If no algorithm was found in the metadata and we aren't
@ -181,12 +180,11 @@ static grpc_error* process_send_initial_metadata(
/* hint compression algorithm */ /* hint compression algorithm */
if (stream_compression_algorithm != GRPC_STREAM_COMPRESS_NONE) { if (stream_compression_algorithm != GRPC_STREAM_COMPRESS_NONE) {
error = grpc_metadata_batch_add_tail( error = grpc_metadata_batch_add_tail(
exec_ctx, initial_metadata, initial_metadata, &calld->stream_compression_algorithm_storage,
&calld->stream_compression_algorithm_storage,
grpc_stream_compression_encoding_mdelem(stream_compression_algorithm)); grpc_stream_compression_encoding_mdelem(stream_compression_algorithm));
} else if (calld->compression_algorithm != GRPC_COMPRESS_NONE) { } else if (calld->compression_algorithm != GRPC_COMPRESS_NONE) {
error = grpc_metadata_batch_add_tail( error = grpc_metadata_batch_add_tail(
exec_ctx, initial_metadata, &calld->compression_algorithm_storage, initial_metadata, &calld->compression_algorithm_storage,
grpc_compression_encoding_mdelem(calld->compression_algorithm)); grpc_compression_encoding_mdelem(calld->compression_algorithm));
} }
@ -194,7 +192,7 @@ static grpc_error* process_send_initial_metadata(
/* convey supported compression algorithms */ /* convey supported compression algorithms */
error = grpc_metadata_batch_add_tail( error = grpc_metadata_batch_add_tail(
exec_ctx, initial_metadata, &calld->accept_encoding_storage, initial_metadata, &calld->accept_encoding_storage,
GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS( GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(
channeld->supported_compression_algorithms)); channeld->supported_compression_algorithms));
@ -203,7 +201,7 @@ static grpc_error* process_send_initial_metadata(
/* Do not overwrite accept-encoding header if it already presents. */ /* Do not overwrite accept-encoding header if it already presents. */
if (!initial_metadata->idx.named.accept_encoding) { if (!initial_metadata->idx.named.accept_encoding) {
error = grpc_metadata_batch_add_tail( error = grpc_metadata_batch_add_tail(
exec_ctx, initial_metadata, &calld->accept_stream_encoding_storage, initial_metadata, &calld->accept_stream_encoding_storage,
GRPC_MDELEM_ACCEPT_STREAM_ENCODING_FOR_ALGORITHMS( GRPC_MDELEM_ACCEPT_STREAM_ENCODING_FOR_ALGORITHMS(
channeld->supported_stream_compression_algorithms)); channeld->supported_stream_compression_algorithms));
} }
@ -211,17 +209,15 @@ static grpc_error* process_send_initial_metadata(
return error; return error;
} }
static void send_message_on_complete(grpc_exec_ctx* exec_ctx, void* arg, static void send_message_on_complete(void* arg, grpc_error* error) {
grpc_error* error) {
grpc_call_element* elem = (grpc_call_element*)arg; grpc_call_element* elem = (grpc_call_element*)arg;
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &calld->slices); grpc_slice_buffer_reset_and_unref_internal(&calld->slices);
GRPC_CLOSURE_RUN(exec_ctx, calld->original_send_message_on_complete, GRPC_CLOSURE_RUN(calld->original_send_message_on_complete,
GRPC_ERROR_REF(error)); GRPC_ERROR_REF(error));
} }
static void send_message_batch_continue(grpc_exec_ctx* exec_ctx, static void send_message_batch_continue(grpc_call_element* elem) {
grpc_call_element* elem) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
// Note: The call to grpc_call_next_op() results in yielding the // Note: The call to grpc_call_next_op() results in yielding the
// call combiner, so we need to clear calld->send_message_batch // call combiner, so we need to clear calld->send_message_batch
@ -229,19 +225,18 @@ static void send_message_batch_continue(grpc_exec_ctx* exec_ctx,
grpc_transport_stream_op_batch* send_message_batch = grpc_transport_stream_op_batch* send_message_batch =
calld->send_message_batch; calld->send_message_batch;
calld->send_message_batch = nullptr; calld->send_message_batch = nullptr;
grpc_call_next_op(exec_ctx, elem, send_message_batch); grpc_call_next_op(elem, send_message_batch);
} }
static void finish_send_message(grpc_exec_ctx* exec_ctx, static void finish_send_message(grpc_call_element* elem) {
grpc_call_element* elem) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
// Compress the data if appropriate. // Compress the data if appropriate.
grpc_slice_buffer tmp; grpc_slice_buffer tmp;
grpc_slice_buffer_init(&tmp); grpc_slice_buffer_init(&tmp);
uint32_t send_flags = uint32_t send_flags =
calld->send_message_batch->payload->send_message.send_message->flags; calld->send_message_batch->payload->send_message.send_message->flags;
bool did_compress = grpc_msg_compress(exec_ctx, calld->compression_algorithm, bool did_compress =
&calld->slices, &tmp); grpc_msg_compress(calld->compression_algorithm, &calld->slices, &tmp);
if (did_compress) { if (did_compress) {
if (grpc_compression_trace.enabled()) { if (grpc_compression_trace.enabled()) {
const char* algo_name; const char* algo_name;
@ -268,11 +263,11 @@ static void finish_send_message(grpc_exec_ctx* exec_ctx,
algo_name, calld->slices.length); algo_name, calld->slices.length);
} }
} }
grpc_slice_buffer_destroy_internal(exec_ctx, &tmp); grpc_slice_buffer_destroy_internal(&tmp);
// Swap out the original byte stream with our new one and send the // Swap out the original byte stream with our new one and send the
// batch down. // batch down.
grpc_byte_stream_destroy( grpc_byte_stream_destroy(
exec_ctx, calld->send_message_batch->payload->send_message.send_message); calld->send_message_batch->payload->send_message.send_message);
grpc_slice_buffer_stream_init(&calld->replacement_stream, &calld->slices, grpc_slice_buffer_stream_init(&calld->replacement_stream, &calld->slices,
send_flags); send_flags);
calld->send_message_batch->payload->send_message.send_message = calld->send_message_batch->payload->send_message.send_message =
@ -280,27 +275,24 @@ static void finish_send_message(grpc_exec_ctx* exec_ctx,
calld->original_send_message_on_complete = calld->original_send_message_on_complete =
calld->send_message_batch->on_complete; calld->send_message_batch->on_complete;
calld->send_message_batch->on_complete = &calld->send_message_on_complete; calld->send_message_batch->on_complete = &calld->send_message_on_complete;
send_message_batch_continue(exec_ctx, elem); send_message_batch_continue(elem);
} }
static void fail_send_message_batch_in_call_combiner(grpc_exec_ctx* exec_ctx, static void fail_send_message_batch_in_call_combiner(void* arg,
void* arg,
grpc_error* error) { grpc_error* error) {
call_data* calld = (call_data*)arg; call_data* calld = (call_data*)arg;
if (calld->send_message_batch != nullptr) { if (calld->send_message_batch != nullptr) {
grpc_transport_stream_op_batch_finish_with_failure( grpc_transport_stream_op_batch_finish_with_failure(
exec_ctx, calld->send_message_batch, GRPC_ERROR_REF(error), calld->send_message_batch, GRPC_ERROR_REF(error), calld->call_combiner);
calld->call_combiner);
calld->send_message_batch = nullptr; calld->send_message_batch = nullptr;
} }
} }
// Pulls a slice from the send_message byte stream and adds it to calld->slices. // Pulls a slice from the send_message byte stream and adds it to calld->slices.
static grpc_error* pull_slice_from_send_message(grpc_exec_ctx* exec_ctx, static grpc_error* pull_slice_from_send_message(call_data* calld) {
call_data* calld) {
grpc_slice incoming_slice; grpc_slice incoming_slice;
grpc_error* error = grpc_byte_stream_pull( grpc_error* error = grpc_byte_stream_pull(
exec_ctx, calld->send_message_batch->payload->send_message.send_message, calld->send_message_batch->payload->send_message.send_message,
&incoming_slice); &incoming_slice);
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
grpc_slice_buffer_add(&calld->slices, incoming_slice); grpc_slice_buffer_add(&calld->slices, incoming_slice);
@ -312,69 +304,65 @@ static grpc_error* pull_slice_from_send_message(grpc_exec_ctx* exec_ctx,
// If all data has been read, invokes finish_send_message(). Otherwise, // If all data has been read, invokes finish_send_message(). Otherwise,
// an async call to grpc_byte_stream_next() has been started, which will // an async call to grpc_byte_stream_next() has been started, which will
// eventually result in calling on_send_message_next_done(). // eventually result in calling on_send_message_next_done().
static void continue_reading_send_message(grpc_exec_ctx* exec_ctx, static void continue_reading_send_message(grpc_call_element* elem) {
grpc_call_element* elem) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
while (grpc_byte_stream_next( while (grpc_byte_stream_next(
exec_ctx, calld->send_message_batch->payload->send_message.send_message, calld->send_message_batch->payload->send_message.send_message, ~(size_t)0,
~(size_t)0, &calld->on_send_message_next_done)) { &calld->on_send_message_next_done)) {
grpc_error* error = pull_slice_from_send_message(exec_ctx, calld); grpc_error* error = pull_slice_from_send_message(calld);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
// Closure callback; does not take ownership of error. // Closure callback; does not take ownership of error.
fail_send_message_batch_in_call_combiner(exec_ctx, calld, error); fail_send_message_batch_in_call_combiner(calld, error);
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
return; return;
} }
if (calld->slices.length == if (calld->slices.length ==
calld->send_message_batch->payload->send_message.send_message->length) { calld->send_message_batch->payload->send_message.send_message->length) {
finish_send_message(exec_ctx, elem); finish_send_message(elem);
break; break;
} }
} }
} }
// Async callback for grpc_byte_stream_next(). // Async callback for grpc_byte_stream_next().
static void on_send_message_next_done(grpc_exec_ctx* exec_ctx, void* arg, static void on_send_message_next_done(void* arg, grpc_error* error) {
grpc_error* error) {
grpc_call_element* elem = (grpc_call_element*)arg; grpc_call_element* elem = (grpc_call_element*)arg;
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
// Closure callback; does not take ownership of error. // Closure callback; does not take ownership of error.
fail_send_message_batch_in_call_combiner(exec_ctx, calld, error); fail_send_message_batch_in_call_combiner(calld, error);
return; return;
} }
error = pull_slice_from_send_message(exec_ctx, calld); error = pull_slice_from_send_message(calld);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
// Closure callback; does not take ownership of error. // Closure callback; does not take ownership of error.
fail_send_message_batch_in_call_combiner(exec_ctx, calld, error); fail_send_message_batch_in_call_combiner(calld, error);
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
return; return;
} }
if (calld->slices.length == if (calld->slices.length ==
calld->send_message_batch->payload->send_message.send_message->length) { calld->send_message_batch->payload->send_message.send_message->length) {
finish_send_message(exec_ctx, elem); finish_send_message(elem);
} else { } else {
continue_reading_send_message(exec_ctx, elem); continue_reading_send_message(elem);
} }
} }
static void start_send_message_batch(grpc_exec_ctx* exec_ctx, void* arg, static void start_send_message_batch(void* arg, grpc_error* unused) {
grpc_error* unused) {
grpc_call_element* elem = (grpc_call_element*)arg; grpc_call_element* elem = (grpc_call_element*)arg;
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
if (skip_compression( if (skip_compression(
elem, elem,
calld->send_message_batch->payload->send_message.send_message->flags, calld->send_message_batch->payload->send_message.send_message->flags,
calld->send_initial_metadata_state == HAS_COMPRESSION_ALGORITHM)) { calld->send_initial_metadata_state == HAS_COMPRESSION_ALGORITHM)) {
send_message_batch_continue(exec_ctx, elem); send_message_batch_continue(elem);
} else { } else {
continue_reading_send_message(exec_ctx, elem); continue_reading_send_message(elem);
} }
} }
static void compress_start_transport_stream_op_batch( static void compress_start_transport_stream_op_batch(
grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_element* elem, grpc_transport_stream_op_batch* batch) {
grpc_transport_stream_op_batch* batch) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
GPR_TIMER_BEGIN("compress_start_transport_stream_op_batch", 0); GPR_TIMER_BEGIN("compress_start_transport_stream_op_batch", 0);
// Handle cancel_stream. // Handle cancel_stream.
@ -385,21 +373,19 @@ static void compress_start_transport_stream_op_batch(
if (calld->send_message_batch != nullptr) { if (calld->send_message_batch != nullptr) {
if (calld->send_initial_metadata_state == INITIAL_METADATA_UNSEEN) { if (calld->send_initial_metadata_state == INITIAL_METADATA_UNSEEN) {
GRPC_CALL_COMBINER_START( GRPC_CALL_COMBINER_START(
exec_ctx, calld->call_combiner, calld->call_combiner,
GRPC_CLOSURE_CREATE(fail_send_message_batch_in_call_combiner, calld, GRPC_CLOSURE_CREATE(fail_send_message_batch_in_call_combiner, calld,
grpc_schedule_on_exec_ctx), grpc_schedule_on_exec_ctx),
GRPC_ERROR_REF(calld->cancel_error), "failing send_message op"); GRPC_ERROR_REF(calld->cancel_error), "failing send_message op");
} else { } else {
grpc_byte_stream_shutdown( grpc_byte_stream_shutdown(
exec_ctx,
calld->send_message_batch->payload->send_message.send_message, calld->send_message_batch->payload->send_message.send_message,
GRPC_ERROR_REF(calld->cancel_error)); GRPC_ERROR_REF(calld->cancel_error));
} }
} }
} else if (calld->cancel_error != GRPC_ERROR_NONE) { } else if (calld->cancel_error != GRPC_ERROR_NONE) {
grpc_transport_stream_op_batch_finish_with_failure( grpc_transport_stream_op_batch_finish_with_failure(
exec_ctx, batch, GRPC_ERROR_REF(calld->cancel_error), batch, GRPC_ERROR_REF(calld->cancel_error), calld->call_combiner);
calld->call_combiner);
goto done; goto done;
} }
// Handle send_initial_metadata. // Handle send_initial_metadata.
@ -407,11 +393,10 @@ static void compress_start_transport_stream_op_batch(
GPR_ASSERT(calld->send_initial_metadata_state == INITIAL_METADATA_UNSEEN); GPR_ASSERT(calld->send_initial_metadata_state == INITIAL_METADATA_UNSEEN);
bool has_compression_algorithm; bool has_compression_algorithm;
grpc_error* error = process_send_initial_metadata( grpc_error* error = process_send_initial_metadata(
exec_ctx, elem, elem, batch->payload->send_initial_metadata.send_initial_metadata,
batch->payload->send_initial_metadata.send_initial_metadata,
&has_compression_algorithm); &has_compression_algorithm);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, batch, error, grpc_transport_stream_op_batch_finish_with_failure(batch, error,
calld->call_combiner); calld->call_combiner);
goto done; goto done;
} }
@ -425,7 +410,7 @@ static void compress_start_transport_stream_op_batch(
// the call stack) will release the call combiner for each batch it sees. // the call stack) will release the call combiner for each batch it sees.
if (calld->send_message_batch != nullptr) { if (calld->send_message_batch != nullptr) {
GRPC_CALL_COMBINER_START( GRPC_CALL_COMBINER_START(
exec_ctx, calld->call_combiner, calld->call_combiner,
&calld->start_send_message_batch_in_call_combiner, GRPC_ERROR_NONE, &calld->start_send_message_batch_in_call_combiner, GRPC_ERROR_NONE,
"starting send_message after send_initial_metadata"); "starting send_message after send_initial_metadata");
} }
@ -440,22 +425,21 @@ static void compress_start_transport_stream_op_batch(
// send_initial_metadata. // send_initial_metadata.
if (calld->send_initial_metadata_state == INITIAL_METADATA_UNSEEN) { if (calld->send_initial_metadata_state == INITIAL_METADATA_UNSEEN) {
GRPC_CALL_COMBINER_STOP( GRPC_CALL_COMBINER_STOP(
exec_ctx, calld->call_combiner, calld->call_combiner,
"send_message batch pending send_initial_metadata"); "send_message batch pending send_initial_metadata");
goto done; goto done;
} }
start_send_message_batch(exec_ctx, elem, GRPC_ERROR_NONE); start_send_message_batch(elem, GRPC_ERROR_NONE);
} else { } else {
// Pass control down the stack. // Pass control down the stack.
grpc_call_next_op(exec_ctx, elem, batch); grpc_call_next_op(elem, batch);
} }
done: done:
GPR_TIMER_END("compress_start_transport_stream_op_batch", 0); GPR_TIMER_END("compress_start_transport_stream_op_batch", 0);
} }
/* Constructor for call_data */ /* Constructor for call_data */
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_call_elem(grpc_call_element* elem,
grpc_call_element* elem,
const grpc_call_element_args* args) { const grpc_call_element_args* args) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
calld->call_combiner = args->call_combiner; calld->call_combiner = args->call_combiner;
@ -471,17 +455,16 @@ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
} }
/* Destructor for call_data */ /* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, static void destroy_call_elem(grpc_call_element* elem,
const grpc_call_final_info* final_info, const grpc_call_final_info* final_info,
grpc_closure* ignored) { grpc_closure* ignored) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
grpc_slice_buffer_destroy_internal(exec_ctx, &calld->slices); grpc_slice_buffer_destroy_internal(&calld->slices);
GRPC_ERROR_UNREF(calld->cancel_error); GRPC_ERROR_UNREF(calld->cancel_error);
} }
/* Constructor for channel_data */ /* Constructor for channel_data */
static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_channel_elem(grpc_channel_element* elem,
grpc_channel_element* elem,
grpc_channel_element_args* args) { grpc_channel_element_args* args) {
channel_data* channeld = (channel_data*)elem->channel_data; channel_data* channeld = (channel_data*)elem->channel_data;
@ -531,8 +514,7 @@ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
} }
/* Destructor for channel data */ /* Destructor for channel data */
static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, static void destroy_channel_elem(grpc_channel_element* elem) {}
grpc_channel_element* elem) {}
const grpc_channel_filter grpc_message_compress_filter = { const grpc_channel_filter grpc_message_compress_filter = {
compress_start_transport_stream_op_batch, compress_start_transport_stream_op_batch,

@ -66,8 +66,7 @@ typedef struct channel_data {
uint8_t unused; uint8_t unused;
} channel_data; } channel_data;
static grpc_error* server_filter_outgoing_metadata(grpc_exec_ctx* exec_ctx, static grpc_error* server_filter_outgoing_metadata(grpc_call_element* elem,
grpc_call_element* elem,
grpc_metadata_batch* b) { grpc_metadata_batch* b) {
if (b->idx.named.grpc_message != nullptr) { if (b->idx.named.grpc_message != nullptr) {
grpc_slice pct_encoded_msg = grpc_percent_encode_slice( grpc_slice pct_encoded_msg = grpc_percent_encode_slice(
@ -75,10 +74,9 @@ static grpc_error* server_filter_outgoing_metadata(grpc_exec_ctx* exec_ctx,
grpc_compatible_percent_encoding_unreserved_bytes); grpc_compatible_percent_encoding_unreserved_bytes);
if (grpc_slice_is_equivalent(pct_encoded_msg, if (grpc_slice_is_equivalent(pct_encoded_msg,
GRPC_MDVALUE(b->idx.named.grpc_message->md))) { GRPC_MDVALUE(b->idx.named.grpc_message->md))) {
grpc_slice_unref_internal(exec_ctx, pct_encoded_msg); grpc_slice_unref_internal(pct_encoded_msg);
} else { } else {
grpc_metadata_batch_set_value(exec_ctx, b->idx.named.grpc_message, grpc_metadata_batch_set_value(b->idx.named.grpc_message, pct_encoded_msg);
pct_encoded_msg);
} }
} }
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
@ -93,8 +91,7 @@ static void add_error(const char* error_name, grpc_error** cumulative,
*cumulative = grpc_error_add_child(*cumulative, new_err); *cumulative = grpc_error_add_child(*cumulative, new_err);
} }
static grpc_error* server_filter_incoming_metadata(grpc_exec_ctx* exec_ctx, static grpc_error* server_filter_incoming_metadata(grpc_call_element* elem,
grpc_call_element* elem,
grpc_metadata_batch* b) { grpc_metadata_batch* b) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
grpc_error* error = GRPC_ERROR_NONE; grpc_error* error = GRPC_ERROR_NONE;
@ -123,7 +120,7 @@ static grpc_error* server_filter_incoming_metadata(grpc_exec_ctx* exec_ctx,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"),
b->idx.named.method->md)); b->idx.named.method->md));
} }
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.method); grpc_metadata_batch_remove(b, b->idx.named.method);
} else { } else {
add_error( add_error(
error_name, &error, error_name, &error,
@ -139,7 +136,7 @@ static grpc_error* server_filter_incoming_metadata(grpc_exec_ctx* exec_ctx,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"),
b->idx.named.te->md)); b->idx.named.te->md));
} }
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.te); grpc_metadata_batch_remove(b, b->idx.named.te);
} else { } else {
add_error(error_name, &error, add_error(error_name, &error,
grpc_error_set_str( grpc_error_set_str(
@ -156,7 +153,7 @@ static grpc_error* server_filter_incoming_metadata(grpc_exec_ctx* exec_ctx,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"),
b->idx.named.scheme->md)); b->idx.named.scheme->md));
} }
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.scheme); grpc_metadata_batch_remove(b, b->idx.named.scheme);
} else { } else {
add_error( add_error(
error_name, &error, error_name, &error,
@ -191,7 +188,7 @@ static grpc_error* server_filter_incoming_metadata(grpc_exec_ctx* exec_ctx,
gpr_free(val); gpr_free(val);
} }
} }
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.content_type); grpc_metadata_batch_remove(b, b->idx.named.content_type);
} }
if (b->idx.named.path == nullptr) { if (b->idx.named.path == nullptr) {
@ -218,22 +215,21 @@ static grpc_error* server_filter_incoming_metadata(grpc_exec_ctx* exec_ctx,
/* substitute path metadata with just the path (not query) */ /* substitute path metadata with just the path (not query) */
grpc_mdelem mdelem_path_without_query = grpc_mdelem_from_slices( grpc_mdelem mdelem_path_without_query = grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_PATH, grpc_slice_sub(path_slice, 0, offset)); GRPC_MDSTR_PATH, grpc_slice_sub(path_slice, 0, offset));
grpc_metadata_batch_substitute(exec_ctx, b, b->idx.named.path, grpc_metadata_batch_substitute(b, b->idx.named.path,
mdelem_path_without_query); mdelem_path_without_query);
/* decode payload from query and add to the slice buffer to be returned */ /* decode payload from query and add to the slice buffer to be returned */
const int k_url_safe = 1; const int k_url_safe = 1;
grpc_slice_buffer_add( grpc_slice_buffer_add(&calld->read_slice_buffer,
&calld->read_slice_buffer,
grpc_base64_decode_with_len( grpc_base64_decode_with_len(
exec_ctx, (const char*)GRPC_SLICE_START_PTR(query_slice), (const char*)GRPC_SLICE_START_PTR(query_slice),
GRPC_SLICE_LENGTH(query_slice), k_url_safe)); GRPC_SLICE_LENGTH(query_slice), k_url_safe));
grpc_slice_buffer_stream_init(&calld->read_stream, grpc_slice_buffer_stream_init(&calld->read_stream,
&calld->read_slice_buffer, 0); &calld->read_slice_buffer, 0);
calld->seen_path_with_query = true; calld->seen_path_with_query = true;
grpc_slice_unref_internal(exec_ctx, query_slice); grpc_slice_unref_internal(query_slice);
} else { } else {
gpr_log(GPR_ERROR, "GET request without QUERY"); gpr_log(GPR_ERROR, "GET request without QUERY");
} }
@ -242,14 +238,14 @@ static grpc_error* server_filter_incoming_metadata(grpc_exec_ctx* exec_ctx,
if (b->idx.named.host != nullptr && b->idx.named.authority == nullptr) { if (b->idx.named.host != nullptr && b->idx.named.authority == nullptr) {
grpc_linked_mdelem* el = b->idx.named.host; grpc_linked_mdelem* el = b->idx.named.host;
grpc_mdelem md = GRPC_MDELEM_REF(el->md); grpc_mdelem md = GRPC_MDELEM_REF(el->md);
grpc_metadata_batch_remove(exec_ctx, b, el); grpc_metadata_batch_remove(b, el);
add_error(error_name, &error, add_error(error_name, &error,
grpc_metadata_batch_add_head( grpc_metadata_batch_add_head(
exec_ctx, b, el, b, el,
grpc_mdelem_from_slices( grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_AUTHORITY, GRPC_MDSTR_AUTHORITY,
grpc_slice_ref_internal(GRPC_MDVALUE(md))))); grpc_slice_ref_internal(GRPC_MDVALUE(md)))));
GRPC_MDELEM_UNREF(exec_ctx, md); GRPC_MDELEM_UNREF(md);
} }
if (b->idx.named.authority == nullptr) { if (b->idx.named.authority == nullptr) {
@ -263,21 +259,18 @@ static grpc_error* server_filter_incoming_metadata(grpc_exec_ctx* exec_ctx,
return error; return error;
} }
static void hs_on_recv(grpc_exec_ctx* exec_ctx, void* user_data, static void hs_on_recv(void* user_data, grpc_error* err) {
grpc_error* err) {
grpc_call_element* elem = (grpc_call_element*)user_data; grpc_call_element* elem = (grpc_call_element*)user_data;
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
if (err == GRPC_ERROR_NONE) { if (err == GRPC_ERROR_NONE) {
err = server_filter_incoming_metadata(exec_ctx, elem, err = server_filter_incoming_metadata(elem, calld->recv_initial_metadata);
calld->recv_initial_metadata);
} else { } else {
GRPC_ERROR_REF(err); GRPC_ERROR_REF(err);
} }
GRPC_CLOSURE_RUN(exec_ctx, calld->on_done_recv, err); GRPC_CLOSURE_RUN(calld->on_done_recv, err);
} }
static void hs_on_complete(grpc_exec_ctx* exec_ctx, void* user_data, static void hs_on_complete(void* user_data, grpc_error* err) {
grpc_error* err) {
grpc_call_element* elem = (grpc_call_element*)user_data; grpc_call_element* elem = (grpc_call_element*)user_data;
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
/* Call recv_message_ready if we got the payload via the path field */ /* Call recv_message_ready if we got the payload via the path field */
@ -287,17 +280,16 @@ static void hs_on_complete(grpc_exec_ctx* exec_ctx, void* user_data,
: (grpc_byte_stream*)&calld->read_stream; : (grpc_byte_stream*)&calld->read_stream;
// Re-enter call combiner for recv_message_ready, since the surface // Re-enter call combiner for recv_message_ready, since the surface
// code will release the call combiner for each callback it receives. // code will release the call combiner for each callback it receives.
GRPC_CALL_COMBINER_START(exec_ctx, calld->call_combiner, GRPC_CALL_COMBINER_START(calld->call_combiner, calld->recv_message_ready,
calld->recv_message_ready, GRPC_ERROR_REF(err), GRPC_ERROR_REF(err),
"resuming recv_message_ready from on_complete"); "resuming recv_message_ready from on_complete");
calld->recv_message_ready = nullptr; calld->recv_message_ready = nullptr;
calld->payload_bin_delivered = true; calld->payload_bin_delivered = true;
} }
GRPC_CLOSURE_RUN(exec_ctx, calld->on_complete, GRPC_ERROR_REF(err)); GRPC_CLOSURE_RUN(calld->on_complete, GRPC_ERROR_REF(err));
} }
static void hs_recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data, static void hs_recv_message_ready(void* user_data, grpc_error* err) {
grpc_error* err) {
grpc_call_element* elem = (grpc_call_element*)user_data; grpc_call_element* elem = (grpc_call_element*)user_data;
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
if (calld->seen_path_with_query) { if (calld->seen_path_with_query) {
@ -305,15 +297,14 @@ static void hs_recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data,
// returned in hs_on_complete callback. // returned in hs_on_complete callback.
// Note that we release the call combiner here, so that other // Note that we release the call combiner here, so that other
// callbacks can run. // callbacks can run.
GRPC_CALL_COMBINER_STOP(exec_ctx, calld->call_combiner, GRPC_CALL_COMBINER_STOP(calld->call_combiner,
"pausing recv_message_ready until on_complete"); "pausing recv_message_ready until on_complete");
} else { } else {
GRPC_CLOSURE_RUN(exec_ctx, calld->recv_message_ready, GRPC_ERROR_REF(err)); GRPC_CLOSURE_RUN(calld->recv_message_ready, GRPC_ERROR_REF(err));
} }
} }
static grpc_error* hs_mutate_op(grpc_exec_ctx* exec_ctx, static grpc_error* hs_mutate_op(grpc_call_element* elem,
grpc_call_element* elem,
grpc_transport_stream_op_batch* op) { grpc_transport_stream_op_batch* op) {
/* grab pointers to our data from the call element */ /* grab pointers to our data from the call element */
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
@ -321,21 +312,19 @@ static grpc_error* hs_mutate_op(grpc_exec_ctx* exec_ctx,
if (op->send_initial_metadata) { if (op->send_initial_metadata) {
grpc_error* error = GRPC_ERROR_NONE; grpc_error* error = GRPC_ERROR_NONE;
static const char* error_name = "Failed sending initial metadata"; static const char* error_name = "Failed sending initial metadata";
add_error( add_error(error_name, &error,
error_name, &error,
grpc_metadata_batch_add_head( grpc_metadata_batch_add_head(
exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, op->payload->send_initial_metadata.send_initial_metadata,
&calld->status, GRPC_MDELEM_STATUS_200)); &calld->status, GRPC_MDELEM_STATUS_200));
add_error( add_error(error_name, &error,
error_name, &error,
grpc_metadata_batch_add_tail( grpc_metadata_batch_add_tail(
exec_ctx, op->payload->send_initial_metadata.send_initial_metadata, op->payload->send_initial_metadata.send_initial_metadata,
&calld->content_type, &calld->content_type,
GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)); GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC));
add_error(error_name, &error, add_error(
error_name, &error,
server_filter_outgoing_metadata( server_filter_outgoing_metadata(
exec_ctx, elem, elem, op->payload->send_initial_metadata.send_initial_metadata));
op->payload->send_initial_metadata.send_initial_metadata));
if (error != GRPC_ERROR_NONE) return error; if (error != GRPC_ERROR_NONE) return error;
} }
@ -367,8 +356,7 @@ static grpc_error* hs_mutate_op(grpc_exec_ctx* exec_ctx,
if (op->send_trailing_metadata) { if (op->send_trailing_metadata) {
grpc_error* error = server_filter_outgoing_metadata( grpc_error* error = server_filter_outgoing_metadata(
exec_ctx, elem, elem, op->payload->send_trailing_metadata.send_trailing_metadata);
op->payload->send_trailing_metadata.send_trailing_metadata);
if (error != GRPC_ERROR_NONE) return error; if (error != GRPC_ERROR_NONE) return error;
} }
@ -376,23 +364,21 @@ static grpc_error* hs_mutate_op(grpc_exec_ctx* exec_ctx,
} }
static void hs_start_transport_stream_op_batch( static void hs_start_transport_stream_op_batch(
grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_element* elem, grpc_transport_stream_op_batch* op) {
grpc_transport_stream_op_batch* op) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
GPR_TIMER_BEGIN("hs_start_transport_stream_op_batch", 0); GPR_TIMER_BEGIN("hs_start_transport_stream_op_batch", 0);
grpc_error* error = hs_mutate_op(exec_ctx, elem, op); grpc_error* error = hs_mutate_op(elem, op);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, error, grpc_transport_stream_op_batch_finish_with_failure(op, error,
calld->call_combiner); calld->call_combiner);
} else { } else {
grpc_call_next_op(exec_ctx, elem, op); grpc_call_next_op(elem, op);
} }
GPR_TIMER_END("hs_start_transport_stream_op_batch", 0); GPR_TIMER_END("hs_start_transport_stream_op_batch", 0);
} }
/* Constructor for call_data */ /* Constructor for call_data */
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_call_elem(grpc_call_element* elem,
grpc_call_element* elem,
const grpc_call_element_args* args) { const grpc_call_element_args* args) {
/* grab pointers to our data from the call element */ /* grab pointers to our data from the call element */
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
@ -409,24 +395,22 @@ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
} }
/* Destructor for call_data */ /* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, static void destroy_call_elem(grpc_call_element* elem,
const grpc_call_final_info* final_info, const grpc_call_final_info* final_info,
grpc_closure* ignored) { grpc_closure* ignored) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
grpc_slice_buffer_destroy_internal(exec_ctx, &calld->read_slice_buffer); grpc_slice_buffer_destroy_internal(&calld->read_slice_buffer);
} }
/* Constructor for channel_data */ /* Constructor for channel_data */
static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_channel_elem(grpc_channel_element* elem,
grpc_channel_element* elem,
grpc_channel_element_args* args) { grpc_channel_element_args* args) {
GPR_ASSERT(!args->is_last); GPR_ASSERT(!args->is_last);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
/* Destructor for channel data */ /* Destructor for channel data */
static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, static void destroy_channel_elem(grpc_channel_element* elem) {}
grpc_channel_element* elem) {}
const grpc_channel_filter grpc_http_server_filter = { const grpc_channel_filter grpc_http_server_filter = {
hs_start_transport_stream_op_batch, hs_start_transport_stream_op_batch,

@ -54,8 +54,7 @@ typedef struct channel_data {
intptr_t id; /**< an id unique to the channel */ intptr_t id; /**< an id unique to the channel */
} channel_data; } channel_data;
static void on_initial_md_ready(grpc_exec_ctx* exec_ctx, void* user_data, static void on_initial_md_ready(void* user_data, grpc_error* err) {
grpc_error* err) {
grpc_call_element* elem = (grpc_call_element*)user_data; grpc_call_element* elem = (grpc_call_element*)user_data;
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
@ -73,20 +72,19 @@ static void on_initial_md_ready(grpc_exec_ctx* exec_ctx, void* user_data,
GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.lb_token->md)); GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.lb_token->md));
calld->have_initial_md_string = true; calld->have_initial_md_string = true;
grpc_metadata_batch_remove( grpc_metadata_batch_remove(
exec_ctx, calld->recv_initial_metadata, calld->recv_initial_metadata,
calld->recv_initial_metadata->idx.named.lb_token); calld->recv_initial_metadata->idx.named.lb_token);
} }
} else { } else {
GRPC_ERROR_REF(err); GRPC_ERROR_REF(err);
} }
calld->ops_recv_initial_metadata_ready->cb( calld->ops_recv_initial_metadata_ready->cb(
exec_ctx, calld->ops_recv_initial_metadata_ready->cb_arg, err); calld->ops_recv_initial_metadata_ready->cb_arg, err);
GRPC_ERROR_UNREF(err); GRPC_ERROR_UNREF(err);
} }
/* Constructor for call_data */ /* Constructor for call_data */
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_call_elem(grpc_call_element* elem,
grpc_call_element* elem,
const grpc_call_element_args* args) { const grpc_call_element_args* args) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
calld->id = (intptr_t)args->call_stack; calld->id = (intptr_t)args->call_stack;
@ -108,7 +106,7 @@ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
} }
/* Destructor for call_data */ /* Destructor for call_data */
static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, static void destroy_call_elem(grpc_call_element* elem,
const grpc_call_final_info* final_info, const grpc_call_final_info* final_info,
grpc_closure* ignored) { grpc_closure* ignored) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
@ -125,19 +123,18 @@ static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
*/ */
if (calld->have_initial_md_string) { if (calld->have_initial_md_string) {
grpc_slice_unref_internal(exec_ctx, calld->initial_md_string); grpc_slice_unref_internal(calld->initial_md_string);
} }
if (calld->have_trailing_md_string) { if (calld->have_trailing_md_string) {
grpc_slice_unref_internal(exec_ctx, calld->trailing_md_string); grpc_slice_unref_internal(calld->trailing_md_string);
} }
if (calld->have_service_method) { if (calld->have_service_method) {
grpc_slice_unref_internal(exec_ctx, calld->service_method); grpc_slice_unref_internal(calld->service_method);
} }
} }
/* Constructor for channel_data */ /* Constructor for channel_data */
static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_channel_elem(grpc_channel_element* elem,
grpc_channel_element* elem,
grpc_channel_element_args* args) { grpc_channel_element_args* args) {
GPR_ASSERT(!args->is_last); GPR_ASSERT(!args->is_last);
@ -158,8 +155,7 @@ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
} }
/* Destructor for channel data */ /* Destructor for channel data */
static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, static void destroy_channel_elem(grpc_channel_element* elem) {
grpc_channel_element* elem) {
/* TODO(dgq): do something with the data /* TODO(dgq): do something with the data
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
grpc_load_reporting_call_data lr_call_data = { grpc_load_reporting_call_data lr_call_data = {
@ -173,8 +169,7 @@ static void destroy_channel_elem(grpc_exec_ctx* exec_ctx,
*/ */
} }
static grpc_filtered_mdelem lr_trailing_md_filter(grpc_exec_ctx* exec_ctx, static grpc_filtered_mdelem lr_trailing_md_filter(void* user_data,
void* user_data,
grpc_mdelem md) { grpc_mdelem md) {
grpc_call_element* elem = (grpc_call_element*)user_data; grpc_call_element* elem = (grpc_call_element*)user_data;
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
@ -186,8 +181,7 @@ static grpc_filtered_mdelem lr_trailing_md_filter(grpc_exec_ctx* exec_ctx,
} }
static void lr_start_transport_stream_op_batch( static void lr_start_transport_stream_op_batch(
grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_element* elem, grpc_transport_stream_op_batch* op) {
grpc_transport_stream_op_batch* op) {
GPR_TIMER_BEGIN("lr_start_transport_stream_op_batch", 0); GPR_TIMER_BEGIN("lr_start_transport_stream_op_batch", 0);
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
@ -203,12 +197,11 @@ static void lr_start_transport_stream_op_batch(
GRPC_LOG_IF_ERROR( GRPC_LOG_IF_ERROR(
"grpc_metadata_batch_filter", "grpc_metadata_batch_filter",
grpc_metadata_batch_filter( grpc_metadata_batch_filter(
exec_ctx,
op->payload->send_trailing_metadata.send_trailing_metadata, op->payload->send_trailing_metadata.send_trailing_metadata,
lr_trailing_md_filter, elem, lr_trailing_md_filter, elem,
"LR trailing metadata filtering error")); "LR trailing metadata filtering error"));
} }
grpc_call_next_op(exec_ctx, elem, op); grpc_call_next_op(elem, op);
GPR_TIMER_END("lr_start_transport_stream_op_batch", 0); GPR_TIMER_END("lr_start_transport_stream_op_batch", 0);
} }

@ -38,7 +38,7 @@ static bool is_load_reporting_enabled(const grpc_channel_args* a) {
} }
static bool maybe_add_server_load_reporting_filter( static bool maybe_add_server_load_reporting_filter(
grpc_exec_ctx* exec_ctx, grpc_channel_stack_builder* builder, void* arg) { grpc_channel_stack_builder* builder, void* arg) {
const grpc_channel_args* args = const grpc_channel_args* args =
grpc_channel_stack_builder_get_channel_arguments(builder); grpc_channel_stack_builder_get_channel_arguments(builder);
const grpc_channel_filter* filter = (const grpc_channel_filter*)arg; const grpc_channel_filter* filter = (const grpc_channel_filter*)arg;

@ -88,73 +88,69 @@ typedef struct channel_data {
/* Increase the nubmer of active calls. Before the increasement, if there are no /* Increase the nubmer of active calls. Before the increasement, if there are no
calls, the max_idle_timer should be cancelled. */ calls, the max_idle_timer should be cancelled. */
static void increase_call_count(grpc_exec_ctx* exec_ctx, channel_data* chand) { static void increase_call_count(channel_data* chand) {
if (gpr_atm_full_fetch_add(&chand->call_count, 1) == 0) { if (gpr_atm_full_fetch_add(&chand->call_count, 1) == 0) {
grpc_timer_cancel(exec_ctx, &chand->max_idle_timer); grpc_timer_cancel(&chand->max_idle_timer);
} }
} }
/* Decrease the nubmer of active calls. After the decrement, if there are no /* Decrease the nubmer of active calls. After the decrement, if there are no
calls, the max_idle_timer should be started. */ calls, the max_idle_timer should be started. */
static void decrease_call_count(grpc_exec_ctx* exec_ctx, channel_data* chand) { static void decrease_call_count(channel_data* chand) {
if (gpr_atm_full_fetch_add(&chand->call_count, -1) == 1) { if (gpr_atm_full_fetch_add(&chand->call_count, -1) == 1) {
GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age max_idle_timer"); GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age max_idle_timer");
grpc_timer_init(exec_ctx, &chand->max_idle_timer, grpc_timer_init(
grpc_exec_ctx_now(exec_ctx) + chand->max_connection_idle, &chand->max_idle_timer,
grpc_core::ExecCtx::Get()->Now() + chand->max_connection_idle,
&chand->close_max_idle_channel); &chand->close_max_idle_channel);
} }
} }
static void start_max_idle_timer_after_init(grpc_exec_ctx* exec_ctx, void* arg, static void start_max_idle_timer_after_init(void* arg, grpc_error* error) {
grpc_error* error) {
channel_data* chand = (channel_data*)arg; channel_data* chand = (channel_data*)arg;
/* Decrease call_count. If there are no active calls at this time, /* Decrease call_count. If there are no active calls at this time,
max_idle_timer will start here. If the number of active calls is not 0, max_idle_timer will start here. If the number of active calls is not 0,
max_idle_timer will start after all the active calls end. */ max_idle_timer will start after all the active calls end. */
decrease_call_count(exec_ctx, chand); decrease_call_count(chand);
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack, GRPC_CHANNEL_STACK_UNREF(chand->channel_stack,
"max_age start_max_idle_timer_after_init"); "max_age start_max_idle_timer_after_init");
} }
static void start_max_age_timer_after_init(grpc_exec_ctx* exec_ctx, void* arg, static void start_max_age_timer_after_init(void* arg, grpc_error* error) {
grpc_error* error) {
channel_data* chand = (channel_data*)arg; channel_data* chand = (channel_data*)arg;
gpr_mu_lock(&chand->max_age_timer_mu); gpr_mu_lock(&chand->max_age_timer_mu);
chand->max_age_timer_pending = true; chand->max_age_timer_pending = true;
GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age max_age_timer"); GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age max_age_timer");
grpc_timer_init(exec_ctx, &chand->max_age_timer, grpc_timer_init(&chand->max_age_timer,
grpc_exec_ctx_now(exec_ctx) + chand->max_connection_age, grpc_core::ExecCtx::Get()->Now() + chand->max_connection_age,
&chand->close_max_age_channel); &chand->close_max_age_channel);
gpr_mu_unlock(&chand->max_age_timer_mu); gpr_mu_unlock(&chand->max_age_timer_mu);
grpc_transport_op* op = grpc_make_transport_op(nullptr); grpc_transport_op* op = grpc_make_transport_op(nullptr);
op->on_connectivity_state_change = &chand->channel_connectivity_changed; op->on_connectivity_state_change = &chand->channel_connectivity_changed;
op->connectivity_state = &chand->connectivity_state; op->connectivity_state = &chand->connectivity_state;
grpc_channel_next_op(exec_ctx, grpc_channel_next_op(grpc_channel_stack_element(chand->channel_stack, 0), op);
grpc_channel_stack_element(chand->channel_stack, 0), op); GRPC_CHANNEL_STACK_UNREF(chand->channel_stack,
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack,
"max_age start_max_age_timer_after_init"); "max_age start_max_age_timer_after_init");
} }
static void start_max_age_grace_timer_after_goaway_op(grpc_exec_ctx* exec_ctx, static void start_max_age_grace_timer_after_goaway_op(void* arg,
void* arg,
grpc_error* error) { grpc_error* error) {
channel_data* chand = (channel_data*)arg; channel_data* chand = (channel_data*)arg;
gpr_mu_lock(&chand->max_age_timer_mu); gpr_mu_lock(&chand->max_age_timer_mu);
chand->max_age_grace_timer_pending = true; chand->max_age_grace_timer_pending = true;
GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age max_age_grace_timer"); GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age max_age_grace_timer");
grpc_timer_init( grpc_timer_init(
exec_ctx, &chand->max_age_grace_timer, &chand->max_age_grace_timer,
chand->max_connection_age_grace == GRPC_MILLIS_INF_FUTURE chand->max_connection_age_grace == GRPC_MILLIS_INF_FUTURE
? GRPC_MILLIS_INF_FUTURE ? GRPC_MILLIS_INF_FUTURE
: grpc_exec_ctx_now(exec_ctx) + chand->max_connection_age_grace, : grpc_core::ExecCtx::Get()->Now() + chand->max_connection_age_grace,
&chand->force_close_max_age_channel); &chand->force_close_max_age_channel);
gpr_mu_unlock(&chand->max_age_timer_mu); gpr_mu_unlock(&chand->max_age_timer_mu);
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack, GRPC_CHANNEL_STACK_UNREF(chand->channel_stack,
"max_age start_max_age_grace_timer_after_goaway_op"); "max_age start_max_age_grace_timer_after_goaway_op");
} }
static void close_max_idle_channel(grpc_exec_ctx* exec_ctx, void* arg, static void close_max_idle_channel(void* arg, grpc_error* error) {
grpc_error* error) {
channel_data* chand = (channel_data*)arg; channel_data* chand = (channel_data*)arg;
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
/* Prevent the max idle timer from being set again */ /* Prevent the max idle timer from being set again */
@ -165,16 +161,14 @@ static void close_max_idle_channel(grpc_exec_ctx* exec_ctx, void* arg,
GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_NO_ERROR); GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_NO_ERROR);
grpc_channel_element* elem = grpc_channel_element* elem =
grpc_channel_stack_element(chand->channel_stack, 0); grpc_channel_stack_element(chand->channel_stack, 0);
elem->filter->start_transport_op(exec_ctx, elem, op); elem->filter->start_transport_op(elem, op);
} else if (error != GRPC_ERROR_CANCELLED) { } else if (error != GRPC_ERROR_CANCELLED) {
GRPC_LOG_IF_ERROR("close_max_idle_channel", error); GRPC_LOG_IF_ERROR("close_max_idle_channel", error);
} }
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack, GRPC_CHANNEL_STACK_UNREF(chand->channel_stack, "max_age max_idle_timer");
"max_age max_idle_timer");
} }
static void close_max_age_channel(grpc_exec_ctx* exec_ctx, void* arg, static void close_max_age_channel(void* arg, grpc_error* error) {
grpc_error* error) {
channel_data* chand = (channel_data*)arg; channel_data* chand = (channel_data*)arg;
gpr_mu_lock(&chand->max_age_timer_mu); gpr_mu_lock(&chand->max_age_timer_mu);
chand->max_age_timer_pending = false; chand->max_age_timer_pending = false;
@ -189,16 +183,14 @@ static void close_max_age_channel(grpc_exec_ctx* exec_ctx, void* arg,
GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_NO_ERROR); GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_NO_ERROR);
grpc_channel_element* elem = grpc_channel_element* elem =
grpc_channel_stack_element(chand->channel_stack, 0); grpc_channel_stack_element(chand->channel_stack, 0);
elem->filter->start_transport_op(exec_ctx, elem, op); elem->filter->start_transport_op(elem, op);
} else if (error != GRPC_ERROR_CANCELLED) { } else if (error != GRPC_ERROR_CANCELLED) {
GRPC_LOG_IF_ERROR("close_max_age_channel", error); GRPC_LOG_IF_ERROR("close_max_age_channel", error);
} }
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack, GRPC_CHANNEL_STACK_UNREF(chand->channel_stack, "max_age max_age_timer");
"max_age max_age_timer");
} }
static void force_close_max_age_channel(grpc_exec_ctx* exec_ctx, void* arg, static void force_close_max_age_channel(void* arg, grpc_error* error) {
grpc_error* error) {
channel_data* chand = (channel_data*)arg; channel_data* chand = (channel_data*)arg;
gpr_mu_lock(&chand->max_age_timer_mu); gpr_mu_lock(&chand->max_age_timer_mu);
chand->max_age_grace_timer_pending = false; chand->max_age_grace_timer_pending = false;
@ -209,38 +201,36 @@ static void force_close_max_age_channel(grpc_exec_ctx* exec_ctx, void* arg,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel reaches max age"); GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel reaches max age");
grpc_channel_element* elem = grpc_channel_element* elem =
grpc_channel_stack_element(chand->channel_stack, 0); grpc_channel_stack_element(chand->channel_stack, 0);
elem->filter->start_transport_op(exec_ctx, elem, op); elem->filter->start_transport_op(elem, op);
} else if (error != GRPC_ERROR_CANCELLED) { } else if (error != GRPC_ERROR_CANCELLED) {
GRPC_LOG_IF_ERROR("force_close_max_age_channel", error); GRPC_LOG_IF_ERROR("force_close_max_age_channel", error);
} }
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack, GRPC_CHANNEL_STACK_UNREF(chand->channel_stack, "max_age max_age_grace_timer");
"max_age max_age_grace_timer");
} }
static void channel_connectivity_changed(grpc_exec_ctx* exec_ctx, void* arg, static void channel_connectivity_changed(void* arg, grpc_error* error) {
grpc_error* error) {
channel_data* chand = (channel_data*)arg; channel_data* chand = (channel_data*)arg;
if (chand->connectivity_state != GRPC_CHANNEL_SHUTDOWN) { if (chand->connectivity_state != GRPC_CHANNEL_SHUTDOWN) {
grpc_transport_op* op = grpc_make_transport_op(nullptr); grpc_transport_op* op = grpc_make_transport_op(nullptr);
op->on_connectivity_state_change = &chand->channel_connectivity_changed; op->on_connectivity_state_change = &chand->channel_connectivity_changed;
op->connectivity_state = &chand->connectivity_state; op->connectivity_state = &chand->connectivity_state;
grpc_channel_next_op( grpc_channel_next_op(grpc_channel_stack_element(chand->channel_stack, 0),
exec_ctx, grpc_channel_stack_element(chand->channel_stack, 0), op); op);
} else { } else {
gpr_mu_lock(&chand->max_age_timer_mu); gpr_mu_lock(&chand->max_age_timer_mu);
if (chand->max_age_timer_pending) { if (chand->max_age_timer_pending) {
grpc_timer_cancel(exec_ctx, &chand->max_age_timer); grpc_timer_cancel(&chand->max_age_timer);
chand->max_age_timer_pending = false; chand->max_age_timer_pending = false;
} }
if (chand->max_age_grace_timer_pending) { if (chand->max_age_grace_timer_pending) {
grpc_timer_cancel(exec_ctx, &chand->max_age_grace_timer); grpc_timer_cancel(&chand->max_age_grace_timer);
chand->max_age_grace_timer_pending = false; chand->max_age_grace_timer_pending = false;
} }
gpr_mu_unlock(&chand->max_age_timer_mu); gpr_mu_unlock(&chand->max_age_timer_mu);
/* If there are no active calls, this increasement will cancel /* If there are no active calls, this increasement will cancel
max_idle_timer, and prevent max_idle_timer from being started in the max_idle_timer, and prevent max_idle_timer from being started in the
future. */ future. */
increase_call_count(exec_ctx, chand); increase_call_count(chand);
} }
} }
@ -263,25 +253,23 @@ add_random_max_connection_age_jitter_and_convert_to_grpc_millis(int value) {
} }
/* Constructor for call_data. */ /* Constructor for call_data. */
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_call_elem(grpc_call_element* elem,
grpc_call_element* elem,
const grpc_call_element_args* args) { const grpc_call_element_args* args) {
channel_data* chand = (channel_data*)elem->channel_data; channel_data* chand = (channel_data*)elem->channel_data;
increase_call_count(exec_ctx, chand); increase_call_count(chand);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
/* Destructor for call_data. */ /* Destructor for call_data. */
static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, static void destroy_call_elem(grpc_call_element* elem,
const grpc_call_final_info* final_info, const grpc_call_final_info* final_info,
grpc_closure* ignored) { grpc_closure* ignored) {
channel_data* chand = (channel_data*)elem->channel_data; channel_data* chand = (channel_data*)elem->channel_data;
decrease_call_count(exec_ctx, chand); decrease_call_count(chand);
} }
/* Constructor for channel_data. */ /* Constructor for channel_data. */
static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_channel_elem(grpc_channel_element* elem,
grpc_channel_element* elem,
grpc_channel_element_args* args) { grpc_channel_element_args* args) {
channel_data* chand = (channel_data*)elem->channel_data; channel_data* chand = (channel_data*)elem->channel_data;
gpr_mu_init(&chand->max_age_timer_mu); gpr_mu_init(&chand->max_age_timer_mu);
@ -351,8 +339,7 @@ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
initialization is done. */ initialization is done. */
GRPC_CHANNEL_STACK_REF(chand->channel_stack, GRPC_CHANNEL_STACK_REF(chand->channel_stack,
"max_age start_max_age_timer_after_init"); "max_age start_max_age_timer_after_init");
GRPC_CLOSURE_SCHED(exec_ctx, &chand->start_max_age_timer_after_init, GRPC_CLOSURE_SCHED(&chand->start_max_age_timer_after_init, GRPC_ERROR_NONE);
GRPC_ERROR_NONE);
} }
/* Initialize the number of calls as 1, so that the max_idle_timer will not /* Initialize the number of calls as 1, so that the max_idle_timer will not
@ -361,15 +348,14 @@ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
if (chand->max_connection_idle != GRPC_MILLIS_INF_FUTURE) { if (chand->max_connection_idle != GRPC_MILLIS_INF_FUTURE) {
GRPC_CHANNEL_STACK_REF(chand->channel_stack, GRPC_CHANNEL_STACK_REF(chand->channel_stack,
"max_age start_max_idle_timer_after_init"); "max_age start_max_idle_timer_after_init");
GRPC_CLOSURE_SCHED(exec_ctx, &chand->start_max_idle_timer_after_init, GRPC_CLOSURE_SCHED(&chand->start_max_idle_timer_after_init,
GRPC_ERROR_NONE); GRPC_ERROR_NONE);
} }
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
/* Destructor for channel_data. */ /* Destructor for channel_data. */
static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, static void destroy_channel_elem(grpc_channel_element* elem) {}
grpc_channel_element* elem) {}
const grpc_channel_filter grpc_max_age_filter = { const grpc_channel_filter grpc_max_age_filter = {
grpc_call_next_op, grpc_call_next_op,
@ -384,8 +370,7 @@ const grpc_channel_filter grpc_max_age_filter = {
grpc_channel_next_get_info, grpc_channel_next_get_info,
"max_age"}; "max_age"};
static bool maybe_add_max_age_filter(grpc_exec_ctx* exec_ctx, static bool maybe_add_max_age_filter(grpc_channel_stack_builder* builder,
grpc_channel_stack_builder* builder,
void* arg) { void* arg) {
const grpc_channel_args* channel_args = const grpc_channel_args* channel_args =
grpc_channel_stack_builder_get_channel_arguments(builder); grpc_channel_stack_builder_get_channel_arguments(builder);

@ -47,8 +47,7 @@ static void* refcounted_message_size_limits_ref(void* value) {
return value; return value;
} }
static void refcounted_message_size_limits_unref(grpc_exec_ctx* exec_ctx, static void refcounted_message_size_limits_unref(void* value) {
void* value) {
refcounted_message_size_limits* limits = refcounted_message_size_limits* limits =
(refcounted_message_size_limits*)value; (refcounted_message_size_limits*)value;
if (gpr_unref(&limits->refs)) { if (gpr_unref(&limits->refs)) {
@ -108,8 +107,7 @@ typedef struct channel_data {
// Callback invoked when we receive a message. Here we check the max // Callback invoked when we receive a message. Here we check the max
// receive message size. // receive message size.
static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data, static void recv_message_ready(void* user_data, grpc_error* error) {
grpc_error* error) {
grpc_call_element* elem = (grpc_call_element*)user_data; grpc_call_element* elem = (grpc_call_element*)user_data;
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
if (*calld->recv_message != nullptr && calld->limits.max_recv_size >= 0 && if (*calld->recv_message != nullptr && calld->limits.max_recv_size >= 0 &&
@ -132,13 +130,12 @@ static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data,
GRPC_ERROR_REF(error); GRPC_ERROR_REF(error);
} }
// Invoke the next callback. // Invoke the next callback.
GRPC_CLOSURE_RUN(exec_ctx, calld->next_recv_message_ready, error); GRPC_CLOSURE_RUN(calld->next_recv_message_ready, error);
} }
// Start transport stream op. // Start transport stream op.
static void start_transport_stream_op_batch( static void start_transport_stream_op_batch(
grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_element* elem, grpc_transport_stream_op_batch* op) {
grpc_transport_stream_op_batch* op) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
// Check max send message size. // Check max send message size.
if (op->send_message && calld->limits.max_send_size >= 0 && if (op->send_message && calld->limits.max_send_size >= 0 &&
@ -149,7 +146,7 @@ static void start_transport_stream_op_batch(
op->payload->send_message.send_message->length, op->payload->send_message.send_message->length,
calld->limits.max_send_size); calld->limits.max_send_size);
grpc_transport_stream_op_batch_finish_with_failure( grpc_transport_stream_op_batch_finish_with_failure(
exec_ctx, op, op,
grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(message_string), grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(message_string),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_ERROR_INT_GRPC_STATUS,
GRPC_STATUS_RESOURCE_EXHAUSTED), GRPC_STATUS_RESOURCE_EXHAUSTED),
@ -165,12 +162,11 @@ static void start_transport_stream_op_batch(
op->payload->recv_message.recv_message_ready = &calld->recv_message_ready; op->payload->recv_message.recv_message_ready = &calld->recv_message_ready;
} }
// Chain to the next filter. // Chain to the next filter.
grpc_call_next_op(exec_ctx, elem, op); grpc_call_next_op(elem, op);
} }
// Constructor for call_data. // Constructor for call_data.
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_call_elem(grpc_call_element* elem,
grpc_call_element* elem,
const grpc_call_element_args* args) { const grpc_call_element_args* args) {
channel_data* chand = (channel_data*)elem->channel_data; channel_data* chand = (channel_data*)elem->channel_data;
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
@ -186,7 +182,7 @@ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
if (chand->method_limit_table != nullptr) { if (chand->method_limit_table != nullptr) {
refcounted_message_size_limits* limits = refcounted_message_size_limits* limits =
(refcounted_message_size_limits*)grpc_method_config_table_get( (refcounted_message_size_limits*)grpc_method_config_table_get(
exec_ctx, chand->method_limit_table, args->path); chand->method_limit_table, args->path);
if (limits != nullptr) { if (limits != nullptr) {
if (limits->limits.max_send_size >= 0 && if (limits->limits.max_send_size >= 0 &&
(limits->limits.max_send_size < calld->limits.max_send_size || (limits->limits.max_send_size < calld->limits.max_send_size ||
@ -204,7 +200,7 @@ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
} }
// Destructor for call_data. // Destructor for call_data.
static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, static void destroy_call_elem(grpc_call_element* elem,
const grpc_call_final_info* final_info, const grpc_call_final_info* final_info,
grpc_closure* ignored) {} grpc_closure* ignored) {}
@ -241,8 +237,7 @@ message_size_limits get_message_size_limits(
} }
// Constructor for channel_data. // Constructor for channel_data.
static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_channel_elem(grpc_channel_element* elem,
grpc_channel_element* elem,
grpc_channel_element_args* args) { grpc_channel_element_args* args) {
GPR_ASSERT(!args->is_last); GPR_ASSERT(!args->is_last);
channel_data* chand = (channel_data*)elem->channel_data; channel_data* chand = (channel_data*)elem->channel_data;
@ -257,8 +252,7 @@ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
if (service_config != nullptr) { if (service_config != nullptr) {
chand->method_limit_table = chand->method_limit_table =
grpc_service_config_create_method_config_table( grpc_service_config_create_method_config_table(
exec_ctx, service_config, service_config, refcounted_message_size_limits_create_from_json,
refcounted_message_size_limits_create_from_json,
refcounted_message_size_limits_ref, refcounted_message_size_limits_ref,
refcounted_message_size_limits_unref); refcounted_message_size_limits_unref);
grpc_service_config_destroy(service_config); grpc_service_config_destroy(service_config);
@ -268,10 +262,9 @@ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
} }
// Destructor for channel_data. // Destructor for channel_data.
static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, static void destroy_channel_elem(grpc_channel_element* elem) {
grpc_channel_element* elem) {
channel_data* chand = (channel_data*)elem->channel_data; channel_data* chand = (channel_data*)elem->channel_data;
grpc_slice_hash_table_unref(exec_ctx, chand->method_limit_table); grpc_slice_hash_table_unref(chand->method_limit_table);
} }
const grpc_channel_filter grpc_message_size_filter = { const grpc_channel_filter grpc_message_size_filter = {
@ -287,8 +280,7 @@ const grpc_channel_filter grpc_message_size_filter = {
grpc_channel_next_get_info, grpc_channel_next_get_info,
"message_size"}; "message_size"};
static bool maybe_add_message_size_filter(grpc_exec_ctx* exec_ctx, static bool maybe_add_message_size_filter(grpc_channel_stack_builder* builder,
grpc_channel_stack_builder* builder,
void* arg) { void* arg) {
const grpc_channel_args* channel_args = const grpc_channel_args* channel_args =
grpc_channel_stack_builder_get_channel_arguments(builder); grpc_channel_stack_builder_get_channel_arguments(builder);

@ -50,8 +50,7 @@ static bool get_user_agent_mdelem(const grpc_metadata_batch* batch,
} }
// Callback invoked when we receive an initial metadata. // Callback invoked when we receive an initial metadata.
static void recv_initial_metadata_ready(grpc_exec_ctx* exec_ctx, static void recv_initial_metadata_ready(void* user_data, grpc_error* error) {
void* user_data, grpc_error* error) {
grpc_call_element* elem = (grpc_call_element*)user_data; grpc_call_element* elem = (grpc_call_element*)user_data;
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
@ -67,14 +66,13 @@ static void recv_initial_metadata_ready(grpc_exec_ctx* exec_ctx,
} }
// Invoke the next callback. // Invoke the next callback.
GRPC_CLOSURE_RUN(exec_ctx, calld->next_recv_initial_metadata_ready, GRPC_CLOSURE_RUN(calld->next_recv_initial_metadata_ready,
GRPC_ERROR_REF(error)); GRPC_ERROR_REF(error));
} }
// Start transport stream op. // Start transport stream op.
static void start_transport_stream_op_batch( static void start_transport_stream_op_batch(
grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_element* elem, grpc_transport_stream_op_batch* op) {
grpc_transport_stream_op_batch* op) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
// Inject callback for receiving initial metadata // Inject callback for receiving initial metadata
@ -96,12 +94,11 @@ static void start_transport_stream_op_batch(
} }
// Chain to the next filter. // Chain to the next filter.
grpc_call_next_op(exec_ctx, elem, op); grpc_call_next_op(elem, op);
} }
// Constructor for call_data. // Constructor for call_data.
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_call_elem(grpc_call_element* elem,
grpc_call_element* elem,
const grpc_call_element_args* args) { const grpc_call_element_args* args) {
call_data* calld = (call_data*)elem->call_data; call_data* calld = (call_data*)elem->call_data;
calld->next_recv_initial_metadata_ready = nullptr; calld->next_recv_initial_metadata_ready = nullptr;
@ -113,20 +110,18 @@ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
} }
// Destructor for call_data. // Destructor for call_data.
static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, static void destroy_call_elem(grpc_call_element* elem,
const grpc_call_final_info* final_info, const grpc_call_final_info* final_info,
grpc_closure* ignored) {} grpc_closure* ignored) {}
// Constructor for channel_data. // Constructor for channel_data.
static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_channel_elem(grpc_channel_element* elem,
grpc_channel_element* elem,
grpc_channel_element_args* args) { grpc_channel_element_args* args) {
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
// Destructor for channel_data. // Destructor for channel_data.
static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, static void destroy_channel_elem(grpc_channel_element* elem) {}
grpc_channel_element* elem) {}
// Parse the user agent // Parse the user agent
static bool parse_user_agent(grpc_mdelem md) { static bool parse_user_agent(grpc_mdelem md) {
@ -181,7 +176,7 @@ const grpc_channel_filter grpc_workaround_cronet_compression_filter = {
"workaround_cronet_compression"}; "workaround_cronet_compression"};
static bool register_workaround_cronet_compression( static bool register_workaround_cronet_compression(
grpc_exec_ctx* exec_ctx, grpc_channel_stack_builder* builder, void* arg) { grpc_channel_stack_builder* builder, void* arg) {
const grpc_channel_args* channel_args = const grpc_channel_args* channel_args =
grpc_channel_stack_builder_get_channel_arguments(builder); grpc_channel_stack_builder_get_channel_arguments(builder);
const grpc_arg* a = grpc_channel_args_find( const grpc_arg* a = grpc_channel_args_find(

@ -61,38 +61,34 @@ static void chttp2_connector_ref(grpc_connector* con) {
gpr_ref(&c->refs); gpr_ref(&c->refs);
} }
static void chttp2_connector_unref(grpc_exec_ctx* exec_ctx, static void chttp2_connector_unref(grpc_connector* con) {
grpc_connector* con) {
chttp2_connector* c = (chttp2_connector*)con; chttp2_connector* c = (chttp2_connector*)con;
if (gpr_unref(&c->refs)) { if (gpr_unref(&c->refs)) {
gpr_mu_destroy(&c->mu); gpr_mu_destroy(&c->mu);
// If handshaking is not yet in progress, destroy the endpoint. // If handshaking is not yet in progress, destroy the endpoint.
// Otherwise, the handshaker will do this for us. // Otherwise, the handshaker will do this for us.
if (c->endpoint != nullptr) grpc_endpoint_destroy(exec_ctx, c->endpoint); if (c->endpoint != nullptr) grpc_endpoint_destroy(c->endpoint);
gpr_free(c); gpr_free(c);
} }
} }
static void chttp2_connector_shutdown(grpc_exec_ctx* exec_ctx, static void chttp2_connector_shutdown(grpc_connector* con, grpc_error* why) {
grpc_connector* con, grpc_error* why) {
chttp2_connector* c = (chttp2_connector*)con; chttp2_connector* c = (chttp2_connector*)con;
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
c->shutdown = true; c->shutdown = true;
if (c->handshake_mgr != nullptr) { if (c->handshake_mgr != nullptr) {
grpc_handshake_manager_shutdown(exec_ctx, c->handshake_mgr, grpc_handshake_manager_shutdown(c->handshake_mgr, GRPC_ERROR_REF(why));
GRPC_ERROR_REF(why));
} }
// If handshaking is not yet in progress, shutdown the endpoint. // If handshaking is not yet in progress, shutdown the endpoint.
// Otherwise, the handshaker will do this for us. // Otherwise, the handshaker will do this for us.
if (!c->connecting && c->endpoint != nullptr) { if (!c->connecting && c->endpoint != nullptr) {
grpc_endpoint_shutdown(exec_ctx, c->endpoint, GRPC_ERROR_REF(why)); grpc_endpoint_shutdown(c->endpoint, GRPC_ERROR_REF(why));
} }
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
GRPC_ERROR_UNREF(why); GRPC_ERROR_UNREF(why);
} }
static void on_handshake_done(grpc_exec_ctx* exec_ctx, void* arg, static void on_handshake_done(void* arg, grpc_error* error) {
grpc_error* error) {
grpc_handshaker_args* args = (grpc_handshaker_args*)arg; grpc_handshaker_args* args = (grpc_handshaker_args*)arg;
chttp2_connector* c = (chttp2_connector*)args->user_data; chttp2_connector* c = (chttp2_connector*)args->user_data;
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
@ -105,20 +101,20 @@ static void on_handshake_done(grpc_exec_ctx* exec_ctx, void* arg,
// before destroying them, even if we know that there are no // before destroying them, even if we know that there are no
// pending read/write callbacks. This should be fixed, at which // pending read/write callbacks. This should be fixed, at which
// point this can be removed. // point this can be removed.
grpc_endpoint_shutdown(exec_ctx, args->endpoint, GRPC_ERROR_REF(error)); grpc_endpoint_shutdown(args->endpoint, GRPC_ERROR_REF(error));
grpc_endpoint_destroy(exec_ctx, args->endpoint); grpc_endpoint_destroy(args->endpoint);
grpc_channel_args_destroy(exec_ctx, args->args); grpc_channel_args_destroy(args->args);
grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer); grpc_slice_buffer_destroy_internal(args->read_buffer);
gpr_free(args->read_buffer); gpr_free(args->read_buffer);
} else { } else {
error = GRPC_ERROR_REF(error); error = GRPC_ERROR_REF(error);
} }
memset(c->result, 0, sizeof(*c->result)); memset(c->result, 0, sizeof(*c->result));
} else { } else {
grpc_endpoint_delete_from_pollset_set(exec_ctx, args->endpoint, grpc_endpoint_delete_from_pollset_set(args->endpoint,
c->args.interested_parties); c->args.interested_parties);
c->result->transport = grpc_create_chttp2_transport(exec_ctx, args->args, c->result->transport =
args->endpoint, true); grpc_create_chttp2_transport(args->args, args->endpoint, true);
GPR_ASSERT(c->result->transport); GPR_ASSERT(c->result->transport);
// TODO(roth): We ideally want to wait until we receive HTTP/2 // TODO(roth): We ideally want to wait until we receive HTTP/2
// settings from the server before we consider the connection // settings from the server before we consider the connection
@ -144,34 +140,32 @@ static void on_handshake_done(grpc_exec_ctx* exec_ctx, void* arg,
// so until after transparent retries is implemented. Otherwise, any // so until after transparent retries is implemented. Otherwise, any
// RPC that we attempt to send on the connection before the timeout // RPC that we attempt to send on the connection before the timeout
// would fail instead of being retried on a subsequent attempt. // would fail instead of being retried on a subsequent attempt.
grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, grpc_chttp2_transport_start_reading(c->result->transport, args->read_buffer,
args->read_buffer, nullptr); nullptr);
c->result->channel_args = args->args; c->result->channel_args = args->args;
} }
grpc_closure* notify = c->notify; grpc_closure* notify = c->notify;
c->notify = nullptr; c->notify = nullptr;
GRPC_CLOSURE_SCHED(exec_ctx, notify, error); GRPC_CLOSURE_SCHED(notify, error);
grpc_handshake_manager_destroy(exec_ctx, c->handshake_mgr); grpc_handshake_manager_destroy(c->handshake_mgr);
c->handshake_mgr = nullptr; c->handshake_mgr = nullptr;
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
chttp2_connector_unref(exec_ctx, (grpc_connector*)c); chttp2_connector_unref((grpc_connector*)c);
} }
static void start_handshake_locked(grpc_exec_ctx* exec_ctx, static void start_handshake_locked(chttp2_connector* c) {
chttp2_connector* c) {
c->handshake_mgr = grpc_handshake_manager_create(); c->handshake_mgr = grpc_handshake_manager_create();
grpc_handshakers_add(exec_ctx, HANDSHAKER_CLIENT, c->args.channel_args, grpc_handshakers_add(HANDSHAKER_CLIENT, c->args.channel_args,
c->handshake_mgr); c->handshake_mgr);
grpc_endpoint_add_to_pollset_set(exec_ctx, c->endpoint, grpc_endpoint_add_to_pollset_set(c->endpoint, c->args.interested_parties);
c->args.interested_parties);
grpc_handshake_manager_do_handshake( grpc_handshake_manager_do_handshake(
exec_ctx, c->handshake_mgr, c->args.interested_parties, c->endpoint, c->handshake_mgr, c->args.interested_parties, c->endpoint,
c->args.channel_args, c->args.deadline, nullptr /* acceptor */, c->args.channel_args, c->args.deadline, nullptr /* acceptor */,
on_handshake_done, c); on_handshake_done, c);
c->endpoint = nullptr; // Endpoint handed off to handshake manager. c->endpoint = nullptr; // Endpoint handed off to handshake manager.
} }
static void connected(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { static void connected(void* arg, grpc_error* error) {
chttp2_connector* c = (chttp2_connector*)arg; chttp2_connector* c = (chttp2_connector*)arg;
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
GPR_ASSERT(c->connecting); GPR_ASSERT(c->connecting);
@ -185,27 +179,26 @@ static void connected(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) {
memset(c->result, 0, sizeof(*c->result)); memset(c->result, 0, sizeof(*c->result));
grpc_closure* notify = c->notify; grpc_closure* notify = c->notify;
c->notify = nullptr; c->notify = nullptr;
GRPC_CLOSURE_SCHED(exec_ctx, notify, error); GRPC_CLOSURE_SCHED(notify, error);
if (c->endpoint != nullptr) { if (c->endpoint != nullptr) {
grpc_endpoint_shutdown(exec_ctx, c->endpoint, GRPC_ERROR_REF(error)); grpc_endpoint_shutdown(c->endpoint, GRPC_ERROR_REF(error));
} }
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
chttp2_connector_unref(exec_ctx, (grpc_connector*)arg); chttp2_connector_unref((grpc_connector*)arg);
} else { } else {
GPR_ASSERT(c->endpoint != nullptr); GPR_ASSERT(c->endpoint != nullptr);
start_handshake_locked(exec_ctx, c); start_handshake_locked(c);
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
} }
} }
static void chttp2_connector_connect(grpc_exec_ctx* exec_ctx, static void chttp2_connector_connect(grpc_connector* con,
grpc_connector* con,
const grpc_connect_in_args* args, const grpc_connect_in_args* args,
grpc_connect_out_args* result, grpc_connect_out_args* result,
grpc_closure* notify) { grpc_closure* notify) {
chttp2_connector* c = (chttp2_connector*)con; chttp2_connector* c = (chttp2_connector*)con;
grpc_resolved_address addr; grpc_resolved_address addr;
grpc_get_subchannel_address_arg(exec_ctx, args->channel_args, &addr); grpc_get_subchannel_address_arg(args->channel_args, &addr);
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
GPR_ASSERT(c->notify == nullptr); GPR_ASSERT(c->notify == nullptr);
c->notify = notify; c->notify = notify;
@ -216,9 +209,8 @@ static void chttp2_connector_connect(grpc_exec_ctx* exec_ctx,
GRPC_CLOSURE_INIT(&c->connected, connected, c, grpc_schedule_on_exec_ctx); GRPC_CLOSURE_INIT(&c->connected, connected, c, grpc_schedule_on_exec_ctx);
GPR_ASSERT(!c->connecting); GPR_ASSERT(!c->connecting);
c->connecting = true; c->connecting = true;
grpc_tcp_client_connect(exec_ctx, &c->connected, &c->endpoint, grpc_tcp_client_connect(&c->connected, &c->endpoint, args->interested_parties,
args->interested_parties, args->channel_args, &addr, args->channel_args, &addr, args->deadline);
args->deadline);
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
} }

@ -34,21 +34,19 @@ static void client_channel_factory_ref(
grpc_client_channel_factory* cc_factory) {} grpc_client_channel_factory* cc_factory) {}
static void client_channel_factory_unref( static void client_channel_factory_unref(
grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* cc_factory) {} grpc_client_channel_factory* cc_factory) {}
static grpc_subchannel* client_channel_factory_create_subchannel( static grpc_subchannel* client_channel_factory_create_subchannel(
grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* cc_factory, grpc_client_channel_factory* cc_factory, const grpc_subchannel_args* args) {
const grpc_subchannel_args* args) {
grpc_connector* connector = grpc_chttp2_connector_create(); grpc_connector* connector = grpc_chttp2_connector_create();
grpc_subchannel* s = grpc_subchannel_create(exec_ctx, connector, args); grpc_subchannel* s = grpc_subchannel_create(connector, args);
grpc_connector_unref(exec_ctx, connector); grpc_connector_unref(connector);
return s; return s;
} }
static grpc_channel* client_channel_factory_create_channel( static grpc_channel* client_channel_factory_create_channel(
grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* cc_factory, grpc_client_channel_factory* cc_factory, const char* target,
const char* target, grpc_client_channel_type type, grpc_client_channel_type type, const grpc_channel_args* args) {
const grpc_channel_args* args) {
if (target == nullptr) { if (target == nullptr) {
gpr_log(GPR_ERROR, "cannot create channel with NULL target name"); gpr_log(GPR_ERROR, "cannot create channel with NULL target name");
return nullptr; return nullptr;
@ -56,14 +54,14 @@ static grpc_channel* client_channel_factory_create_channel(
// Add channel arg containing the server URI. // Add channel arg containing the server URI.
grpc_arg arg = grpc_channel_arg_string_create( grpc_arg arg = grpc_channel_arg_string_create(
(char*)GRPC_ARG_SERVER_URI, (char*)GRPC_ARG_SERVER_URI,
grpc_resolver_factory_add_default_prefix_if_needed(exec_ctx, target)); grpc_resolver_factory_add_default_prefix_if_needed(target));
const char* to_remove[] = {GRPC_ARG_SERVER_URI}; const char* to_remove[] = {GRPC_ARG_SERVER_URI};
grpc_channel_args* new_args = grpc_channel_args* new_args =
grpc_channel_args_copy_and_add_and_remove(args, to_remove, 1, &arg, 1); grpc_channel_args_copy_and_add_and_remove(args, to_remove, 1, &arg, 1);
gpr_free(arg.value.string); gpr_free(arg.value.string);
grpc_channel* channel = grpc_channel_create(exec_ctx, target, new_args, grpc_channel* channel =
GRPC_CLIENT_CHANNEL, nullptr); grpc_channel_create(target, new_args, GRPC_CLIENT_CHANNEL, nullptr);
grpc_channel_args_destroy(exec_ctx, new_args); grpc_channel_args_destroy(new_args);
return channel; return channel;
} }
@ -82,7 +80,7 @@ static grpc_client_channel_factory client_channel_factory = {
grpc_channel* grpc_insecure_channel_create(const char* target, grpc_channel* grpc_insecure_channel_create(const char* target,
const grpc_channel_args* args, const grpc_channel_args* args,
void* reserved) { void* reserved) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_core::ExecCtx exec_ctx;
GRPC_API_TRACE( GRPC_API_TRACE(
"grpc_insecure_channel_create(target=%s, args=%p, reserved=%p)", 3, "grpc_insecure_channel_create(target=%s, args=%p, reserved=%p)", 3,
(target, args, reserved)); (target, args, reserved));
@ -93,11 +91,11 @@ grpc_channel* grpc_insecure_channel_create(const char* target,
grpc_channel_args* new_args = grpc_channel_args_copy_and_add(args, &arg, 1); grpc_channel_args* new_args = grpc_channel_args_copy_and_add(args, &arg, 1);
// Create channel. // Create channel.
grpc_channel* channel = client_channel_factory_create_channel( grpc_channel* channel = client_channel_factory_create_channel(
&exec_ctx, &client_channel_factory, target, &client_channel_factory, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR,
GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args); new_args);
// Clean up. // Clean up.
grpc_channel_args_destroy(&exec_ctx, new_args); grpc_channel_args_destroy(new_args);
grpc_exec_ctx_finish(&exec_ctx);
return channel != nullptr ? channel return channel != nullptr ? channel
: grpc_lame_client_channel_create( : grpc_lame_client_channel_create(
target, GRPC_STATUS_INTERNAL, target, GRPC_STATUS_INTERNAL,

@ -37,7 +37,7 @@
grpc_channel* grpc_insecure_channel_create_from_fd( grpc_channel* grpc_insecure_channel_create_from_fd(
const char* target, int fd, const grpc_channel_args* args) { const char* target, int fd, const grpc_channel_args* args) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_core::ExecCtx exec_ctx;
GRPC_API_TRACE("grpc_insecure_channel_create(target=%p, fd=%d, args=%p)", 3, GRPC_API_TRACE("grpc_insecure_channel_create(target=%p, fd=%d, args=%p)", 3,
(target, fd, args)); (target, fd, args));
@ -50,17 +50,17 @@ grpc_channel* grpc_insecure_channel_create_from_fd(
GPR_ASSERT(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0); GPR_ASSERT(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0);
grpc_endpoint* client = grpc_tcp_client_create_from_fd( grpc_endpoint* client = grpc_tcp_client_create_from_fd(
&exec_ctx, grpc_fd_create(fd, "client"), args, "fd-client"); grpc_fd_create(fd, "client"), args, "fd-client");
grpc_transport* transport = grpc_transport* transport =
grpc_create_chttp2_transport(&exec_ctx, final_args, client, true); grpc_create_chttp2_transport(final_args, client, true);
GPR_ASSERT(transport); GPR_ASSERT(transport);
grpc_channel* channel = grpc_channel_create( grpc_channel* channel = grpc_channel_create(
&exec_ctx, target, final_args, GRPC_CLIENT_DIRECT_CHANNEL, transport); target, final_args, GRPC_CLIENT_DIRECT_CHANNEL, transport);
grpc_channel_args_destroy(&exec_ctx, final_args); grpc_channel_args_destroy(final_args);
grpc_chttp2_transport_start_reading(&exec_ctx, transport, nullptr, nullptr); grpc_chttp2_transport_start_reading(transport, nullptr, nullptr);
grpc_exec_ctx_finish(&exec_ctx); grpc_core::ExecCtx::Get()->Flush();
return channel != nullptr ? channel return channel != nullptr ? channel
: grpc_lame_client_channel_create( : grpc_lame_client_channel_create(
@ -73,7 +73,7 @@ grpc_channel* grpc_insecure_channel_create_from_fd(
grpc_channel* grpc_insecure_channel_create_from_fd( grpc_channel* grpc_insecure_channel_create_from_fd(
const char* target, int fd, const grpc_channel_args* args) { const char* target, int fd, const grpc_channel_args* args) {
GPR_ASSERT(0); GPR_ASSERT(0);
return NULL; return nullptr;
} }
#endif // GPR_SUPPORT_CHANNELS_FROM_FD #endif // GPR_SUPPORT_CHANNELS_FROM_FD

@ -41,10 +41,10 @@ static void client_channel_factory_ref(
grpc_client_channel_factory* cc_factory) {} grpc_client_channel_factory* cc_factory) {}
static void client_channel_factory_unref( static void client_channel_factory_unref(
grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* cc_factory) {} grpc_client_channel_factory* cc_factory) {}
static grpc_subchannel_args* get_secure_naming_subchannel_args( static grpc_subchannel_args* get_secure_naming_subchannel_args(
grpc_exec_ctx* exec_ctx, const grpc_subchannel_args* args) { const grpc_subchannel_args* args) {
grpc_channel_credentials* channel_credentials = grpc_channel_credentials* channel_credentials =
grpc_channel_credentials_find_in_args(args->args); grpc_channel_credentials_find_in_args(args->args);
if (channel_credentials == nullptr) { if (channel_credentials == nullptr) {
@ -68,7 +68,7 @@ static grpc_subchannel_args* get_secure_naming_subchannel_args(
const char* server_uri_str = server_uri_arg->value.string; const char* server_uri_str = server_uri_arg->value.string;
GPR_ASSERT(server_uri_str != nullptr); GPR_ASSERT(server_uri_str != nullptr);
grpc_uri* server_uri = grpc_uri* server_uri =
grpc_uri_parse(exec_ctx, server_uri_str, true /* supress errors */); grpc_uri_parse(server_uri_str, true /* supress errors */);
GPR_ASSERT(server_uri != nullptr); GPR_ASSERT(server_uri != nullptr);
const char* server_uri_path; const char* server_uri_path;
server_uri_path = server_uri_path =
@ -81,7 +81,7 @@ static grpc_subchannel_args* get_secure_naming_subchannel_args(
const char* target_uri_str = const char* target_uri_str =
grpc_get_subchannel_address_uri_arg(args->args); grpc_get_subchannel_address_uri_arg(args->args);
grpc_uri* target_uri = grpc_uri* target_uri =
grpc_uri_parse(exec_ctx, target_uri_str, false /* suppress errors */); grpc_uri_parse(target_uri_str, false /* suppress errors */);
GPR_ASSERT(target_uri != nullptr); GPR_ASSERT(target_uri != nullptr);
if (target_uri->path[0] != '\0') { // "path" may be empty if (target_uri->path[0] != '\0') { // "path" may be empty
const grpc_slice key = grpc_slice_from_static_string( const grpc_slice key = grpc_slice_from_static_string(
@ -89,7 +89,7 @@ static grpc_subchannel_args* get_secure_naming_subchannel_args(
const char* value = const char* value =
(const char*)grpc_slice_hash_table_get(targets_info, key); (const char*)grpc_slice_hash_table_get(targets_info, key);
if (value != nullptr) target_name_to_check = gpr_strdup(value); if (value != nullptr) target_name_to_check = gpr_strdup(value);
grpc_slice_unref_internal(exec_ctx, key); grpc_slice_unref_internal(key);
} }
if (target_name_to_check == nullptr) { if (target_name_to_check == nullptr) {
// If the target name to check hasn't already been set, fall back to using // If the target name to check hasn't already been set, fall back to using
@ -107,7 +107,7 @@ static grpc_subchannel_args* get_secure_naming_subchannel_args(
grpc_channel_args* new_args_from_connector = nullptr; grpc_channel_args* new_args_from_connector = nullptr;
const grpc_security_status security_status = const grpc_security_status security_status =
grpc_channel_credentials_create_security_connector( grpc_channel_credentials_create_security_connector(
exec_ctx, channel_credentials, target_name_to_check, args->args, channel_credentials, target_name_to_check, args->args,
&subchannel_security_connector, &new_args_from_connector); &subchannel_security_connector, &new_args_from_connector);
if (security_status != GRPC_SECURITY_OK) { if (security_status != GRPC_SECURITY_OK) {
gpr_log(GPR_ERROR, gpr_log(GPR_ERROR,
@ -123,10 +123,10 @@ static grpc_subchannel_args* get_secure_naming_subchannel_args(
grpc_channel_args* new_args = grpc_channel_args_copy_and_add( grpc_channel_args* new_args = grpc_channel_args_copy_and_add(
new_args_from_connector != nullptr ? new_args_from_connector : args->args, new_args_from_connector != nullptr ? new_args_from_connector : args->args,
&new_security_connector_arg, 1); &new_security_connector_arg, 1);
GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, &subchannel_security_connector->base, GRPC_SECURITY_CONNECTOR_UNREF(&subchannel_security_connector->base,
"lb_channel_create"); "lb_channel_create");
if (new_args_from_connector != nullptr) { if (new_args_from_connector != nullptr) {
grpc_channel_args_destroy(exec_ctx, new_args_from_connector); grpc_channel_args_destroy(new_args_from_connector);
} }
grpc_subchannel_args* final_sc_args = grpc_subchannel_args* final_sc_args =
(grpc_subchannel_args*)gpr_malloc(sizeof(*final_sc_args)); (grpc_subchannel_args*)gpr_malloc(sizeof(*final_sc_args));
@ -136,10 +136,9 @@ static grpc_subchannel_args* get_secure_naming_subchannel_args(
} }
static grpc_subchannel* client_channel_factory_create_subchannel( static grpc_subchannel* client_channel_factory_create_subchannel(
grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* cc_factory, grpc_client_channel_factory* cc_factory, const grpc_subchannel_args* args) {
const grpc_subchannel_args* args) {
grpc_subchannel_args* subchannel_args = grpc_subchannel_args* subchannel_args =
get_secure_naming_subchannel_args(exec_ctx, args); get_secure_naming_subchannel_args(args);
if (subchannel_args == nullptr) { if (subchannel_args == nullptr) {
gpr_log( gpr_log(
GPR_ERROR, GPR_ERROR,
@ -147,19 +146,16 @@ static grpc_subchannel* client_channel_factory_create_subchannel(
return nullptr; return nullptr;
} }
grpc_connector* connector = grpc_chttp2_connector_create(); grpc_connector* connector = grpc_chttp2_connector_create();
grpc_subchannel* s = grpc_subchannel* s = grpc_subchannel_create(connector, subchannel_args);
grpc_subchannel_create(exec_ctx, connector, subchannel_args); grpc_connector_unref(connector);
grpc_connector_unref(exec_ctx, connector); grpc_channel_args_destroy((grpc_channel_args*)subchannel_args->args);
grpc_channel_args_destroy(exec_ctx,
(grpc_channel_args*)subchannel_args->args);
gpr_free(subchannel_args); gpr_free(subchannel_args);
return s; return s;
} }
static grpc_channel* client_channel_factory_create_channel( static grpc_channel* client_channel_factory_create_channel(
grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* cc_factory, grpc_client_channel_factory* cc_factory, const char* target,
const char* target, grpc_client_channel_type type, grpc_client_channel_type type, const grpc_channel_args* args) {
const grpc_channel_args* args) {
if (target == nullptr) { if (target == nullptr) {
gpr_log(GPR_ERROR, "cannot create channel with NULL target name"); gpr_log(GPR_ERROR, "cannot create channel with NULL target name");
return nullptr; return nullptr;
@ -167,14 +163,14 @@ static grpc_channel* client_channel_factory_create_channel(
// Add channel arg containing the server URI. // Add channel arg containing the server URI.
grpc_arg arg = grpc_channel_arg_string_create( grpc_arg arg = grpc_channel_arg_string_create(
(char*)GRPC_ARG_SERVER_URI, (char*)GRPC_ARG_SERVER_URI,
grpc_resolver_factory_add_default_prefix_if_needed(exec_ctx, target)); grpc_resolver_factory_add_default_prefix_if_needed(target));
const char* to_remove[] = {GRPC_ARG_SERVER_URI}; const char* to_remove[] = {GRPC_ARG_SERVER_URI};
grpc_channel_args* new_args = grpc_channel_args* new_args =
grpc_channel_args_copy_and_add_and_remove(args, to_remove, 1, &arg, 1); grpc_channel_args_copy_and_add_and_remove(args, to_remove, 1, &arg, 1);
gpr_free(arg.value.string); gpr_free(arg.value.string);
grpc_channel* channel = grpc_channel_create(exec_ctx, target, new_args, grpc_channel* channel =
GRPC_CLIENT_CHANNEL, nullptr); grpc_channel_create(target, new_args, GRPC_CLIENT_CHANNEL, nullptr);
grpc_channel_args_destroy(exec_ctx, new_args); grpc_channel_args_destroy(new_args);
return channel; return channel;
} }
@ -194,7 +190,7 @@ grpc_channel* grpc_secure_channel_create(grpc_channel_credentials* creds,
const char* target, const char* target,
const grpc_channel_args* args, const grpc_channel_args* args,
void* reserved) { void* reserved) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_core::ExecCtx exec_ctx;
GRPC_API_TRACE( GRPC_API_TRACE(
"grpc_secure_channel_create(creds=%p, target=%s, args=%p, " "grpc_secure_channel_create(creds=%p, target=%s, args=%p, "
"reserved=%p)", "reserved=%p)",
@ -211,11 +207,10 @@ grpc_channel* grpc_secure_channel_create(grpc_channel_credentials* creds,
args, args_to_add, GPR_ARRAY_SIZE(args_to_add)); args, args_to_add, GPR_ARRAY_SIZE(args_to_add));
// Create channel. // Create channel.
channel = client_channel_factory_create_channel( channel = client_channel_factory_create_channel(
&exec_ctx, &client_channel_factory, target, &client_channel_factory, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR,
GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args); new_args);
// Clean up. // Clean up.
grpc_channel_args_destroy(&exec_ctx, new_args); grpc_channel_args_destroy(new_args);
grpc_exec_ctx_finish(&exec_ctx);
} }
return channel != nullptr ? channel return channel != nullptr ? channel
: grpc_lame_client_channel_create( : grpc_lame_client_channel_create(

@ -69,17 +69,17 @@ typedef struct {
} server_connection_state; } server_connection_state;
static void server_connection_state_unref( static void server_connection_state_unref(
grpc_exec_ctx* exec_ctx, server_connection_state* connection_state) { server_connection_state* connection_state) {
if (gpr_unref(&connection_state->refs)) { if (gpr_unref(&connection_state->refs)) {
if (connection_state->transport != nullptr) { if (connection_state->transport != nullptr) {
GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, connection_state->transport, GRPC_CHTTP2_UNREF_TRANSPORT(connection_state->transport,
"receive settings timeout"); "receive settings timeout");
} }
gpr_free(connection_state); gpr_free(connection_state);
} }
} }
static void on_timeout(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { static void on_timeout(void* arg, grpc_error* error) {
server_connection_state* connection_state = (server_connection_state*)arg; server_connection_state* connection_state = (server_connection_state*)arg;
// Note that we may be called with GRPC_ERROR_NONE when the timer fires // Note that we may be called with GRPC_ERROR_NONE when the timer fires
// or with an error indicating that the timer system is being shut down. // or with an error indicating that the timer system is being shut down.
@ -87,22 +87,20 @@ static void on_timeout(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) {
grpc_transport_op* op = grpc_make_transport_op(nullptr); grpc_transport_op* op = grpc_make_transport_op(nullptr);
op->disconnect_with_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( op->disconnect_with_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Did not receive HTTP/2 settings before handshake timeout"); "Did not receive HTTP/2 settings before handshake timeout");
grpc_transport_perform_op(exec_ctx, &connection_state->transport->base, op); grpc_transport_perform_op(&connection_state->transport->base, op);
} }
server_connection_state_unref(exec_ctx, connection_state); server_connection_state_unref(connection_state);
} }
static void on_receive_settings(grpc_exec_ctx* exec_ctx, void* arg, static void on_receive_settings(void* arg, grpc_error* error) {
grpc_error* error) {
server_connection_state* connection_state = (server_connection_state*)arg; server_connection_state* connection_state = (server_connection_state*)arg;
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
grpc_timer_cancel(exec_ctx, &connection_state->timer); grpc_timer_cancel(&connection_state->timer);
} }
server_connection_state_unref(exec_ctx, connection_state); server_connection_state_unref(connection_state);
} }
static void on_handshake_done(grpc_exec_ctx* exec_ctx, void* arg, static void on_handshake_done(void* arg, grpc_error* error) {
grpc_error* error) {
grpc_handshaker_args* args = (grpc_handshaker_args*)arg; grpc_handshaker_args* args = (grpc_handshaker_args*)arg;
server_connection_state* connection_state = server_connection_state* connection_state =
(server_connection_state*)args->user_data; (server_connection_state*)args->user_data;
@ -117,10 +115,10 @@ static void on_handshake_done(grpc_exec_ctx* exec_ctx, void* arg,
// before destroying them, even if we know that there are no // before destroying them, even if we know that there are no
// pending read/write callbacks. This should be fixed, at which // pending read/write callbacks. This should be fixed, at which
// point this can be removed. // point this can be removed.
grpc_endpoint_shutdown(exec_ctx, args->endpoint, GRPC_ERROR_NONE); grpc_endpoint_shutdown(args->endpoint, GRPC_ERROR_NONE);
grpc_endpoint_destroy(exec_ctx, args->endpoint); grpc_endpoint_destroy(args->endpoint);
grpc_channel_args_destroy(exec_ctx, args->args); grpc_channel_args_destroy(args->args);
grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer); grpc_slice_buffer_destroy_internal(args->read_buffer);
gpr_free(args->read_buffer); gpr_free(args->read_buffer);
} }
} else { } else {
@ -128,10 +126,10 @@ static void on_handshake_done(grpc_exec_ctx* exec_ctx, void* arg,
// handshaker may have handed off the connection to some external // handshaker may have handed off the connection to some external
// code, so we can just clean up here without creating a transport. // code, so we can just clean up here without creating a transport.
if (args->endpoint != nullptr) { if (args->endpoint != nullptr) {
grpc_transport* transport = grpc_create_chttp2_transport( grpc_transport* transport =
exec_ctx, args->args, args->endpoint, false); grpc_create_chttp2_transport(args->args, args->endpoint, false);
grpc_server_setup_transport( grpc_server_setup_transport(
exec_ctx, connection_state->svr_state->server, transport, connection_state->svr_state->server, transport,
connection_state->accepting_pollset, args->args); connection_state->accepting_pollset, args->args);
// Use notify_on_receive_settings callback to enforce the // Use notify_on_receive_settings callback to enforce the
// handshake deadline. // handshake deadline.
@ -141,16 +139,14 @@ static void on_handshake_done(grpc_exec_ctx* exec_ctx, void* arg,
on_receive_settings, connection_state, on_receive_settings, connection_state,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
grpc_chttp2_transport_start_reading( grpc_chttp2_transport_start_reading(
exec_ctx, transport, args->read_buffer, transport, args->read_buffer, &connection_state->on_receive_settings);
&connection_state->on_receive_settings); grpc_channel_args_destroy(args->args);
grpc_channel_args_destroy(exec_ctx, args->args);
gpr_ref(&connection_state->refs); gpr_ref(&connection_state->refs);
GRPC_CHTTP2_REF_TRANSPORT((grpc_chttp2_transport*)transport, GRPC_CHTTP2_REF_TRANSPORT((grpc_chttp2_transport*)transport,
"receive settings timeout"); "receive settings timeout");
GRPC_CLOSURE_INIT(&connection_state->on_timeout, on_timeout, GRPC_CLOSURE_INIT(&connection_state->on_timeout, on_timeout,
connection_state, grpc_schedule_on_exec_ctx); connection_state, grpc_schedule_on_exec_ctx);
grpc_timer_init(exec_ctx, &connection_state->timer, grpc_timer_init(&connection_state->timer, connection_state->deadline,
connection_state->deadline,
&connection_state->on_timeout); &connection_state->on_timeout);
} }
} }
@ -158,21 +154,21 @@ static void on_handshake_done(grpc_exec_ctx* exec_ctx, void* arg,
&connection_state->svr_state->pending_handshake_mgrs, &connection_state->svr_state->pending_handshake_mgrs,
connection_state->handshake_mgr); connection_state->handshake_mgr);
gpr_mu_unlock(&connection_state->svr_state->mu); gpr_mu_unlock(&connection_state->svr_state->mu);
grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr); grpc_handshake_manager_destroy(connection_state->handshake_mgr);
gpr_free(connection_state->acceptor); gpr_free(connection_state->acceptor);
grpc_tcp_server_unref(exec_ctx, connection_state->svr_state->tcp_server); grpc_tcp_server_unref(connection_state->svr_state->tcp_server);
server_connection_state_unref(exec_ctx, connection_state); server_connection_state_unref(connection_state);
} }
static void on_accept(grpc_exec_ctx* exec_ctx, void* arg, grpc_endpoint* tcp, static void on_accept(void* arg, grpc_endpoint* tcp,
grpc_pollset* accepting_pollset, grpc_pollset* accepting_pollset,
grpc_tcp_server_acceptor* acceptor) { grpc_tcp_server_acceptor* acceptor) {
server_state* state = (server_state*)arg; server_state* state = (server_state*)arg;
gpr_mu_lock(&state->mu); gpr_mu_lock(&state->mu);
if (state->shutdown) { if (state->shutdown) {
gpr_mu_unlock(&state->mu); gpr_mu_unlock(&state->mu);
grpc_endpoint_shutdown(exec_ctx, tcp, GRPC_ERROR_NONE); grpc_endpoint_shutdown(tcp, GRPC_ERROR_NONE);
grpc_endpoint_destroy(exec_ctx, tcp); grpc_endpoint_destroy(tcp);
gpr_free(acceptor); gpr_free(acceptor);
return; return;
} }
@ -188,59 +184,56 @@ static void on_accept(grpc_exec_ctx* exec_ctx, void* arg, grpc_endpoint* tcp,
connection_state->accepting_pollset = accepting_pollset; connection_state->accepting_pollset = accepting_pollset;
connection_state->acceptor = acceptor; connection_state->acceptor = acceptor;
connection_state->handshake_mgr = handshake_mgr; connection_state->handshake_mgr = handshake_mgr;
grpc_handshakers_add(exec_ctx, HANDSHAKER_SERVER, state->args, grpc_handshakers_add(HANDSHAKER_SERVER, state->args,
connection_state->handshake_mgr); connection_state->handshake_mgr);
const grpc_arg* timeout_arg = const grpc_arg* timeout_arg =
grpc_channel_args_find(state->args, GRPC_ARG_SERVER_HANDSHAKE_TIMEOUT_MS); grpc_channel_args_find(state->args, GRPC_ARG_SERVER_HANDSHAKE_TIMEOUT_MS);
connection_state->deadline = connection_state->deadline =
grpc_exec_ctx_now(exec_ctx) + grpc_core::ExecCtx::Get()->Now() +
grpc_channel_arg_get_integer(timeout_arg, grpc_channel_arg_get_integer(timeout_arg,
{120 * GPR_MS_PER_SEC, 1, INT_MAX}); {120 * GPR_MS_PER_SEC, 1, INT_MAX});
grpc_handshake_manager_do_handshake(exec_ctx, connection_state->handshake_mgr, grpc_handshake_manager_do_handshake(
nullptr /* interested_parties */, tcp, connection_state->handshake_mgr, nullptr /* interested_parties */, tcp,
state->args, connection_state->deadline, state->args, connection_state->deadline, acceptor, on_handshake_done,
acceptor, on_handshake_done,
connection_state); connection_state);
} }
/* Server callback: start listening on our ports */ /* Server callback: start listening on our ports */
static void server_start_listener(grpc_exec_ctx* exec_ctx, grpc_server* server, static void server_start_listener(grpc_server* server, void* arg,
void* arg, grpc_pollset** pollsets, grpc_pollset** pollsets,
size_t pollset_count) { size_t pollset_count) {
server_state* state = (server_state*)arg; server_state* state = (server_state*)arg;
gpr_mu_lock(&state->mu); gpr_mu_lock(&state->mu);
state->shutdown = false; state->shutdown = false;
gpr_mu_unlock(&state->mu); gpr_mu_unlock(&state->mu);
grpc_tcp_server_start(exec_ctx, state->tcp_server, pollsets, pollset_count, grpc_tcp_server_start(state->tcp_server, pollsets, pollset_count, on_accept,
on_accept, state); state);
} }
static void tcp_server_shutdown_complete(grpc_exec_ctx* exec_ctx, void* arg, static void tcp_server_shutdown_complete(void* arg, grpc_error* error) {
grpc_error* error) {
server_state* state = (server_state*)arg; server_state* state = (server_state*)arg;
/* ensure all threads have unlocked */ /* ensure all threads have unlocked */
gpr_mu_lock(&state->mu); gpr_mu_lock(&state->mu);
grpc_closure* destroy_done = state->server_destroy_listener_done; grpc_closure* destroy_done = state->server_destroy_listener_done;
GPR_ASSERT(state->shutdown); GPR_ASSERT(state->shutdown);
grpc_handshake_manager_pending_list_shutdown_all( grpc_handshake_manager_pending_list_shutdown_all(
exec_ctx, state->pending_handshake_mgrs, GRPC_ERROR_REF(error)); state->pending_handshake_mgrs, GRPC_ERROR_REF(error));
gpr_mu_unlock(&state->mu); gpr_mu_unlock(&state->mu);
// Flush queued work before destroying handshaker factory, since that // Flush queued work before destroying handshaker factory, since that
// may do a synchronous unref. // may do a synchronous unref.
grpc_exec_ctx_flush(exec_ctx); grpc_core::ExecCtx::Get()->Flush();
if (destroy_done != nullptr) { if (destroy_done != nullptr) {
destroy_done->cb(exec_ctx, destroy_done->cb_arg, GRPC_ERROR_REF(error)); destroy_done->cb(destroy_done->cb_arg, GRPC_ERROR_REF(error));
grpc_exec_ctx_flush(exec_ctx); grpc_core::ExecCtx::Get()->Flush();
} }
grpc_channel_args_destroy(exec_ctx, state->args); grpc_channel_args_destroy(state->args);
gpr_mu_destroy(&state->mu); gpr_mu_destroy(&state->mu);
gpr_free(state); gpr_free(state);
} }
/* Server callback: destroy the tcp listener (so we don't generate further /* Server callback: destroy the tcp listener (so we don't generate further
callbacks) */ callbacks) */
static void server_destroy_listener(grpc_exec_ctx* exec_ctx, static void server_destroy_listener(grpc_server* server, void* arg,
grpc_server* server, void* arg,
grpc_closure* destroy_done) { grpc_closure* destroy_done) {
server_state* state = (server_state*)arg; server_state* state = (server_state*)arg;
gpr_mu_lock(&state->mu); gpr_mu_lock(&state->mu);
@ -248,12 +241,11 @@ static void server_destroy_listener(grpc_exec_ctx* exec_ctx,
state->server_destroy_listener_done = destroy_done; state->server_destroy_listener_done = destroy_done;
grpc_tcp_server* tcp_server = state->tcp_server; grpc_tcp_server* tcp_server = state->tcp_server;
gpr_mu_unlock(&state->mu); gpr_mu_unlock(&state->mu);
grpc_tcp_server_shutdown_listeners(exec_ctx, tcp_server); grpc_tcp_server_shutdown_listeners(tcp_server);
grpc_tcp_server_unref(exec_ctx, tcp_server); grpc_tcp_server_unref(tcp_server);
} }
grpc_error* grpc_chttp2_server_add_port(grpc_exec_ctx* exec_ctx, grpc_error* grpc_chttp2_server_add_port(grpc_server* server, const char* addr,
grpc_server* server, const char* addr,
grpc_channel_args* args, grpc_channel_args* args,
int* port_num) { int* port_num) {
grpc_resolved_addresses* resolved = nullptr; grpc_resolved_addresses* resolved = nullptr;
@ -277,8 +269,8 @@ grpc_error* grpc_chttp2_server_add_port(grpc_exec_ctx* exec_ctx,
GRPC_CLOSURE_INIT(&state->tcp_server_shutdown_complete, GRPC_CLOSURE_INIT(&state->tcp_server_shutdown_complete,
tcp_server_shutdown_complete, state, tcp_server_shutdown_complete, state,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
err = grpc_tcp_server_create(exec_ctx, &state->tcp_server_shutdown_complete, err = grpc_tcp_server_create(&state->tcp_server_shutdown_complete, args,
args, &tcp_server); &tcp_server);
if (err != GRPC_ERROR_NONE) { if (err != GRPC_ERROR_NONE) {
goto error; goto error;
} }
@ -327,7 +319,7 @@ grpc_error* grpc_chttp2_server_add_port(grpc_exec_ctx* exec_ctx,
grpc_resolved_addresses_destroy(resolved); grpc_resolved_addresses_destroy(resolved);
/* Register with the server only upon success */ /* Register with the server only upon success */
grpc_server_add_listener(exec_ctx, server, state, server_start_listener, grpc_server_add_listener(server, state, server_start_listener,
server_destroy_listener); server_destroy_listener);
goto done; goto done;
@ -338,9 +330,9 @@ error:
grpc_resolved_addresses_destroy(resolved); grpc_resolved_addresses_destroy(resolved);
} }
if (tcp_server) { if (tcp_server) {
grpc_tcp_server_unref(exec_ctx, tcp_server); grpc_tcp_server_unref(tcp_server);
} else { } else {
grpc_channel_args_destroy(exec_ctx, args); grpc_channel_args_destroy(args);
gpr_free(state); gpr_free(state);
} }
*port_num = 0; *port_num = 0;

@ -25,8 +25,7 @@
/// Adds a port to \a server. Sets \a port_num to the port number. /// Adds a port to \a server. Sets \a port_num to the port number.
/// Takes ownership of \a args. /// Takes ownership of \a args.
grpc_error* grpc_chttp2_server_add_port(grpc_exec_ctx* exec_ctx, grpc_error* grpc_chttp2_server_add_port(grpc_server* server, const char* addr,
grpc_server* server, const char* addr,
grpc_channel_args* args, int* port_num); grpc_channel_args* args, int* port_num);
#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_SERVER_CHTTP2_SERVER_H */ #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_SERVER_CHTTP2_SERVER_H */

@ -26,12 +26,12 @@
#include "src/core/lib/surface/server.h" #include "src/core/lib/surface/server.h"
int grpc_server_add_insecure_http2_port(grpc_server* server, const char* addr) { int grpc_server_add_insecure_http2_port(grpc_server* server, const char* addr) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_core::ExecCtx exec_ctx;
int port_num = 0; int port_num = 0;
GRPC_API_TRACE("grpc_server_add_insecure_http2_port(server=%p, addr=%s)", 2, GRPC_API_TRACE("grpc_server_add_insecure_http2_port(server=%p, addr=%s)", 2,
(server, addr)); (server, addr));
grpc_error* err = grpc_chttp2_server_add_port( grpc_error* err = grpc_chttp2_server_add_port(
&exec_ctx, server, addr, server, addr,
grpc_channel_args_copy(grpc_server_get_channel_args(server)), &port_num); grpc_channel_args_copy(grpc_server_get_channel_args(server)), &port_num);
if (err != GRPC_ERROR_NONE) { if (err != GRPC_ERROR_NONE) {
const char* msg = grpc_error_string(err); const char* msg = grpc_error_string(err);
@ -39,6 +39,6 @@ int grpc_server_add_insecure_http2_port(grpc_server* server, const char* addr) {
GRPC_ERROR_UNREF(err); GRPC_ERROR_UNREF(err);
} }
grpc_exec_ctx_finish(&exec_ctx);
return port_num; return port_num;
} }

@ -38,32 +38,29 @@ void grpc_server_add_insecure_channel_from_fd(grpc_server* server,
void* reserved, int fd) { void* reserved, int fd) {
GPR_ASSERT(reserved == nullptr); GPR_ASSERT(reserved == nullptr);
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_core::ExecCtx exec_ctx;
char* name; char* name;
gpr_asprintf(&name, "fd:%d", fd); gpr_asprintf(&name, "fd:%d", fd);
grpc_endpoint* server_endpoint = grpc_endpoint* server_endpoint = grpc_tcp_create(
grpc_tcp_create(&exec_ctx, grpc_fd_create(fd, name), grpc_fd_create(fd, name), grpc_server_get_channel_args(server), name);
grpc_server_get_channel_args(server), name);
gpr_free(name); gpr_free(name);
const grpc_channel_args* server_args = grpc_server_get_channel_args(server); const grpc_channel_args* server_args = grpc_server_get_channel_args(server);
grpc_transport* transport = grpc_create_chttp2_transport( grpc_transport* transport = grpc_create_chttp2_transport(
&exec_ctx, server_args, server_endpoint, false /* is_client */); server_args, server_endpoint, false /* is_client */);
grpc_pollset** pollsets; grpc_pollset** pollsets;
size_t num_pollsets = 0; size_t num_pollsets = 0;
grpc_server_get_pollsets(server, &pollsets, &num_pollsets); grpc_server_get_pollsets(server, &pollsets, &num_pollsets);
for (size_t i = 0; i < num_pollsets; i++) { for (size_t i = 0; i < num_pollsets; i++) {
grpc_endpoint_add_to_pollset(&exec_ctx, server_endpoint, pollsets[i]); grpc_endpoint_add_to_pollset(server_endpoint, pollsets[i]);
} }
grpc_server_setup_transport(&exec_ctx, server, transport, nullptr, grpc_server_setup_transport(server, transport, nullptr, server_args);
server_args); grpc_chttp2_transport_start_reading(transport, nullptr, nullptr);
grpc_chttp2_transport_start_reading(&exec_ctx, transport, nullptr, nullptr);
grpc_exec_ctx_finish(&exec_ctx);
} }
#else // !GPR_SUPPORT_CHANNELS_FROM_FD #else // !GPR_SUPPORT_CHANNELS_FROM_FD

@ -36,7 +36,7 @@
int grpc_server_add_secure_http2_port(grpc_server* server, const char* addr, int grpc_server_add_secure_http2_port(grpc_server* server, const char* addr,
grpc_server_credentials* creds) { grpc_server_credentials* creds) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_core::ExecCtx exec_ctx;
grpc_error* err = GRPC_ERROR_NONE; grpc_error* err = GRPC_ERROR_NONE;
grpc_server_security_connector* sc = nullptr; grpc_server_security_connector* sc = nullptr;
int port_num = 0; int port_num = 0;
@ -52,8 +52,7 @@ int grpc_server_add_secure_http2_port(grpc_server* server, const char* addr,
"No credentials specified for secure server port (creds==NULL)"); "No credentials specified for secure server port (creds==NULL)");
goto done; goto done;
} }
status = status = grpc_server_credentials_create_security_connector(creds, &sc);
grpc_server_credentials_create_security_connector(&exec_ctx, creds, &sc);
if (status != GRPC_SECURITY_OK) { if (status != GRPC_SECURITY_OK) {
char* msg; char* msg;
gpr_asprintf(&msg, gpr_asprintf(&msg,
@ -72,12 +71,12 @@ int grpc_server_add_secure_http2_port(grpc_server* server, const char* addr,
grpc_channel_args_copy_and_add(grpc_server_get_channel_args(server), grpc_channel_args_copy_and_add(grpc_server_get_channel_args(server),
args_to_add, GPR_ARRAY_SIZE(args_to_add)); args_to_add, GPR_ARRAY_SIZE(args_to_add));
// Add server port. // Add server port.
err = grpc_chttp2_server_add_port(&exec_ctx, server, addr, args, &port_num); err = grpc_chttp2_server_add_port(server, addr, args, &port_num);
done: done:
if (sc != nullptr) { if (sc != nullptr) {
GRPC_SECURITY_CONNECTOR_UNREF(&exec_ctx, &sc->base, "server"); GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "server");
} }
grpc_exec_ctx_finish(&exec_ctx);
if (err != GRPC_ERROR_NONE) { if (err != GRPC_ERROR_NONE) {
const char* msg = grpc_error_string(err); const char* msg = grpc_error_string(err);
gpr_log(GPR_ERROR, "%s", msg); gpr_log(GPR_ERROR, "%s", msg);

@ -130,8 +130,7 @@ bool grpc_base64_decode_partial(struct grpc_base64_decode_context* ctx) {
return true; return true;
} }
grpc_slice grpc_chttp2_base64_decode(grpc_exec_ctx* exec_ctx, grpc_slice grpc_chttp2_base64_decode(grpc_slice input) {
grpc_slice input) {
size_t input_length = GRPC_SLICE_LENGTH(input); size_t input_length = GRPC_SLICE_LENGTH(input);
size_t output_length = input_length / 4 * 3; size_t output_length = input_length / 4 * 3;
struct grpc_base64_decode_context ctx; struct grpc_base64_decode_context ctx;
@ -167,7 +166,7 @@ grpc_slice grpc_chttp2_base64_decode(grpc_exec_ctx* exec_ctx,
char* s = grpc_slice_to_c_string(input); char* s = grpc_slice_to_c_string(input);
gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s); gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s);
gpr_free(s); gpr_free(s);
grpc_slice_unref_internal(exec_ctx, output); grpc_slice_unref_internal(output);
return grpc_empty_slice(); return grpc_empty_slice();
} }
GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output)); GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output));
@ -175,8 +174,7 @@ grpc_slice grpc_chttp2_base64_decode(grpc_exec_ctx* exec_ctx,
return output; return output;
} }
grpc_slice grpc_chttp2_base64_decode_with_length(grpc_exec_ctx* exec_ctx, grpc_slice grpc_chttp2_base64_decode_with_length(grpc_slice input,
grpc_slice input,
size_t output_length) { size_t output_length) {
size_t input_length = GRPC_SLICE_LENGTH(input); size_t input_length = GRPC_SLICE_LENGTH(input);
grpc_slice output = GRPC_SLICE_MALLOC(output_length); grpc_slice output = GRPC_SLICE_MALLOC(output_length);
@ -189,7 +187,7 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_exec_ctx* exec_ctx,
"grpc_chttp2_base64_decode_with_length has a length of %d, which " "grpc_chttp2_base64_decode_with_length has a length of %d, which "
"has a tail of 1 byte.\n", "has a tail of 1 byte.\n",
(int)input_length); (int)input_length);
grpc_slice_unref_internal(exec_ctx, output); grpc_slice_unref_internal(output);
return grpc_empty_slice(); return grpc_empty_slice();
} }
@ -199,7 +197,7 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_exec_ctx* exec_ctx,
"than the max possible output length %d.\n", "than the max possible output length %d.\n",
(int)output_length, (int)output_length,
(int)(input_length / 4 * 3 + tail_xtra[input_length % 4])); (int)(input_length / 4 * 3 + tail_xtra[input_length % 4]));
grpc_slice_unref_internal(exec_ctx, output); grpc_slice_unref_internal(output);
return grpc_empty_slice(); return grpc_empty_slice();
} }
@ -213,7 +211,7 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_exec_ctx* exec_ctx,
char* s = grpc_slice_to_c_string(input); char* s = grpc_slice_to_c_string(input);
gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s); gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s);
gpr_free(s); gpr_free(s);
grpc_slice_unref_internal(exec_ctx, output); grpc_slice_unref_internal(output);
return grpc_empty_slice(); return grpc_empty_slice();
} }
GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output)); GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output));

@ -40,13 +40,12 @@ bool grpc_base64_decode_partial(struct grpc_base64_decode_context* ctx);
/* base64 decode a slice with pad chars. Returns a new slice, does not take /* base64 decode a slice with pad chars. Returns a new slice, does not take
ownership of the input. Returns an empty slice if decoding is failed. */ ownership of the input. Returns an empty slice if decoding is failed. */
grpc_slice grpc_chttp2_base64_decode(grpc_exec_ctx* exec_ctx, grpc_slice input); grpc_slice grpc_chttp2_base64_decode(grpc_slice input);
/* base64 decode a slice without pad chars, data length is needed. Returns a new /* base64 decode a slice without pad chars, data length is needed. Returns a new
slice, does not take ownership of the input. Returns an empty slice if slice, does not take ownership of the input. Returns an empty slice if
decoding is failed. */ decoding is failed. */
grpc_slice grpc_chttp2_base64_decode_with_length(grpc_exec_ctx* exec_ctx, grpc_slice grpc_chttp2_base64_decode_with_length(grpc_slice input,
grpc_slice input,
size_t output_length); size_t output_length);
#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_DECODER_H */ #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_DECODER_H */

@ -32,7 +32,7 @@ grpc_slice grpc_chttp2_huffman_compress(grpc_slice input);
/* equivalent to: /* equivalent to:
grpc_slice x = grpc_chttp2_base64_encode(input); grpc_slice x = grpc_chttp2_base64_encode(input);
grpc_slice y = grpc_chttp2_huffman_compress(x); grpc_slice y = grpc_chttp2_huffman_compress(x);
grpc_slice_unref_internal(exec_ctx, x); grpc_slice_unref_internal( x);
return y; */ return y; */
grpc_slice grpc_chttp2_base64_encode_and_huffman_compress(grpc_slice input); grpc_slice grpc_chttp2_base64_encode_and_huffman_compress(grpc_slice input);

File diff suppressed because it is too large Load Diff

@ -28,15 +28,14 @@ extern grpc_core::TraceFlag grpc_trace_http2_stream_state;
extern grpc_core::DebugOnlyTraceFlag grpc_trace_chttp2_refcount; extern grpc_core::DebugOnlyTraceFlag grpc_trace_chttp2_refcount;
grpc_transport* grpc_create_chttp2_transport( grpc_transport* grpc_create_chttp2_transport(
grpc_exec_ctx* exec_ctx, const grpc_channel_args* channel_args, const grpc_channel_args* channel_args, grpc_endpoint* ep, bool is_client);
grpc_endpoint* ep, bool is_client);
/// Takes ownership of \a read_buffer, which (if non-NULL) contains /// Takes ownership of \a read_buffer, which (if non-NULL) contains
/// leftover bytes previously read from the endpoint (e.g., by handshakers). /// leftover bytes previously read from the endpoint (e.g., by handshakers).
/// If non-null, \a notify_on_receive_settings will be scheduled when /// If non-null, \a notify_on_receive_settings will be scheduled when
/// HTTP/2 settings are received from the peer. /// HTTP/2 settings are received from the peer.
void grpc_chttp2_transport_start_reading( void grpc_chttp2_transport_start_reading(
grpc_exec_ctx* exec_ctx, grpc_transport* transport, grpc_transport* transport, grpc_slice_buffer* read_buffer,
grpc_slice_buffer* read_buffer, grpc_closure* notify_on_receive_settings); grpc_closure* notify_on_receive_settings);
#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CHTTP2_TRANSPORT_H */ #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CHTTP2_TRANSPORT_H */

@ -149,8 +149,7 @@ void FlowControlAction::Trace(grpc_chttp2_transport* t) const {
gpr_free(mf_str); gpr_free(mf_str);
} }
TransportFlowControl::TransportFlowControl(grpc_exec_ctx* exec_ctx, TransportFlowControl::TransportFlowControl(const grpc_chttp2_transport* t,
const grpc_chttp2_transport* t,
bool enable_bdp_probe) bool enable_bdp_probe)
: t_(t), : t_(t),
enable_bdp_probe_(enable_bdp_probe), enable_bdp_probe_(enable_bdp_probe),
@ -163,7 +162,7 @@ TransportFlowControl::TransportFlowControl(grpc_exec_ctx* exec_ctx,
.set_min_control_value(-1) .set_min_control_value(-1)
.set_max_control_value(25) .set_max_control_value(25)
.set_integral_range(10)), .set_integral_range(10)),
last_pid_update_(grpc_exec_ctx_now(exec_ctx)) {} last_pid_update_(grpc_core::ExecCtx::Get()->Now()) {}
uint32_t TransportFlowControl::MaybeSendUpdate(bool writing_anyway) { uint32_t TransportFlowControl::MaybeSendUpdate(bool writing_anyway) {
FlowControlTrace trace("t updt sent", this, nullptr); FlowControlTrace trace("t updt sent", this, nullptr);
@ -308,9 +307,8 @@ double TransportFlowControl::TargetLogBdp() {
1 + log2(bdp_estimator_.EstimateBdp())); 1 + log2(bdp_estimator_.EstimateBdp()));
} }
double TransportFlowControl::SmoothLogBdp(grpc_exec_ctx* exec_ctx, double TransportFlowControl::SmoothLogBdp(double value) {
double value) { grpc_millis now = grpc_core::ExecCtx::Get()->Now();
grpc_millis now = grpc_exec_ctx_now(exec_ctx);
double bdp_error = value - pid_controller_.last_control_value(); double bdp_error = value - pid_controller_.last_control_value();
const double dt = (double)(now - last_pid_update_) * 1e-3; const double dt = (double)(now - last_pid_update_) * 1e-3;
last_pid_update_ = now; last_pid_update_ = now;
@ -331,15 +329,14 @@ FlowControlAction::Urgency TransportFlowControl::DeltaUrgency(
} }
} }
FlowControlAction TransportFlowControl::PeriodicUpdate( FlowControlAction TransportFlowControl::PeriodicUpdate() {
grpc_exec_ctx* exec_ctx) {
FlowControlAction action; FlowControlAction action;
if (enable_bdp_probe_) { if (enable_bdp_probe_) {
// get bdp estimate and update initial_window accordingly. // get bdp estimate and update initial_window accordingly.
// target might change based on how much memory pressure we are under // target might change based on how much memory pressure we are under
// TODO(ncteisen): experiment with setting target to be huge under low // TODO(ncteisen): experiment with setting target to be huge under low
// memory pressure. // memory pressure.
const double target = pow(2, SmoothLogBdp(exec_ctx, TargetLogBdp())); const double target = pow(2, SmoothLogBdp(TargetLogBdp()));
// Though initial window 'could' drop to 0, we keep the floor at 128 // Though initial window 'could' drop to 0, we keep the floor at 128
target_initial_window_size_ = (int32_t)GPR_CLAMP(target, 128, INT32_MAX); target_initial_window_size_ = (int32_t)GPR_CLAMP(target, 128, INT32_MAX);

@ -134,8 +134,7 @@ class FlowControlTrace {
class TransportFlowControl { class TransportFlowControl {
public: public:
TransportFlowControl(grpc_exec_ctx* exec_ctx, const grpc_chttp2_transport* t, TransportFlowControl(const grpc_chttp2_transport* t, bool enable_bdp_probe);
bool enable_bdp_probe);
~TransportFlowControl() {} ~TransportFlowControl() {}
bool bdp_probe() const { return enable_bdp_probe_; } bool bdp_probe() const { return enable_bdp_probe_; }
@ -153,7 +152,7 @@ class TransportFlowControl {
// Call periodically (at a low-ish rate, 100ms - 10s makes sense) // Call periodically (at a low-ish rate, 100ms - 10s makes sense)
// to perform more complex flow control calculations and return an action // to perform more complex flow control calculations and return an action
// to let chttp2 change its parameters // to let chttp2 change its parameters
FlowControlAction PeriodicUpdate(grpc_exec_ctx* exec_ctx); FlowControlAction PeriodicUpdate();
void StreamSentData(int64_t size) { remote_window_ -= size; } void StreamSentData(int64_t size) { remote_window_ -= size; }
@ -212,7 +211,7 @@ class TransportFlowControl {
private: private:
friend class ::grpc::testing::TrickledCHTTP2; friend class ::grpc::testing::TrickledCHTTP2;
double TargetLogBdp(); double TargetLogBdp();
double SmoothLogBdp(grpc_exec_ctx* exec_ctx, double value); double SmoothLogBdp(double value);
FlowControlAction::Urgency DeltaUrgency(int32_t value, FlowControlAction::Urgency DeltaUrgency(int32_t value,
grpc_chttp2_setting_id setting_id); grpc_chttp2_setting_id setting_id);

@ -36,11 +36,10 @@ grpc_error* grpc_chttp2_data_parser_init(grpc_chttp2_data_parser* parser) {
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
void grpc_chttp2_data_parser_destroy(grpc_exec_ctx* exec_ctx, void grpc_chttp2_data_parser_destroy(grpc_chttp2_data_parser* parser) {
grpc_chttp2_data_parser* parser) {
if (parser->parsing_frame != nullptr) { if (parser->parsing_frame != nullptr) {
GRPC_ERROR_UNREF(grpc_chttp2_incoming_byte_stream_finished( GRPC_ERROR_UNREF(grpc_chttp2_incoming_byte_stream_finished(
exec_ctx, parser->parsing_frame, parser->parsing_frame,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Parser destroyed"), false)); GRPC_ERROR_CREATE_FROM_STATIC_STRING("Parser destroyed"), false));
} }
GRPC_ERROR_UNREF(parser->error); GRPC_ERROR_UNREF(parser->error);
@ -98,7 +97,7 @@ void grpc_chttp2_encode_data(uint32_t id, grpc_slice_buffer* inbuf,
} }
grpc_error* grpc_deframe_unprocessed_incoming_frames( grpc_error* grpc_deframe_unprocessed_incoming_frames(
grpc_exec_ctx* exec_ctx, grpc_chttp2_data_parser* p, grpc_chttp2_stream* s, grpc_chttp2_data_parser* p, grpc_chttp2_stream* s,
grpc_slice_buffer* slices, grpc_slice* slice_out, grpc_slice_buffer* slices, grpc_slice* slice_out,
grpc_byte_stream** stream_out) { grpc_byte_stream** stream_out) {
grpc_error* error = GRPC_ERROR_NONE; grpc_error* error = GRPC_ERROR_NONE;
@ -118,14 +117,14 @@ grpc_error* grpc_deframe_unprocessed_incoming_frames(
char* msg; char* msg;
if (cur == end) { if (cur == end) {
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(slice);
continue; continue;
} }
switch (p->state) { switch (p->state) {
case GRPC_CHTTP2_DATA_ERROR: case GRPC_CHTTP2_DATA_ERROR:
p->state = GRPC_CHTTP2_DATA_ERROR; p->state = GRPC_CHTTP2_DATA_ERROR;
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(slice);
return GRPC_ERROR_REF(p->error); return GRPC_ERROR_REF(p->error);
case GRPC_CHTTP2_DATA_FH_0: case GRPC_CHTTP2_DATA_FH_0:
s->stats.incoming.framing_bytes++; s->stats.incoming.framing_bytes++;
@ -150,12 +149,12 @@ grpc_error* grpc_deframe_unprocessed_incoming_frames(
p->error = p->error =
grpc_error_set_int(p->error, GRPC_ERROR_INT_OFFSET, cur - beg); grpc_error_set_int(p->error, GRPC_ERROR_INT_OFFSET, cur - beg);
p->state = GRPC_CHTTP2_DATA_ERROR; p->state = GRPC_CHTTP2_DATA_ERROR;
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(slice);
return GRPC_ERROR_REF(p->error); return GRPC_ERROR_REF(p->error);
} }
if (++cur == end) { if (++cur == end) {
p->state = GRPC_CHTTP2_DATA_FH_1; p->state = GRPC_CHTTP2_DATA_FH_1;
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(slice);
continue; continue;
} }
/* fallthrough */ /* fallthrough */
@ -164,7 +163,7 @@ grpc_error* grpc_deframe_unprocessed_incoming_frames(
p->frame_size = ((uint32_t)*cur) << 24; p->frame_size = ((uint32_t)*cur) << 24;
if (++cur == end) { if (++cur == end) {
p->state = GRPC_CHTTP2_DATA_FH_2; p->state = GRPC_CHTTP2_DATA_FH_2;
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(slice);
continue; continue;
} }
/* fallthrough */ /* fallthrough */
@ -173,7 +172,7 @@ grpc_error* grpc_deframe_unprocessed_incoming_frames(
p->frame_size |= ((uint32_t)*cur) << 16; p->frame_size |= ((uint32_t)*cur) << 16;
if (++cur == end) { if (++cur == end) {
p->state = GRPC_CHTTP2_DATA_FH_3; p->state = GRPC_CHTTP2_DATA_FH_3;
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(slice);
continue; continue;
} }
/* fallthrough */ /* fallthrough */
@ -182,7 +181,7 @@ grpc_error* grpc_deframe_unprocessed_incoming_frames(
p->frame_size |= ((uint32_t)*cur) << 8; p->frame_size |= ((uint32_t)*cur) << 8;
if (++cur == end) { if (++cur == end) {
p->state = GRPC_CHTTP2_DATA_FH_4; p->state = GRPC_CHTTP2_DATA_FH_4;
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(slice);
continue; continue;
} }
/* fallthrough */ /* fallthrough */
@ -198,11 +197,11 @@ grpc_error* grpc_deframe_unprocessed_incoming_frames(
message_flags |= GRPC_WRITE_INTERNAL_COMPRESS; message_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
} }
p->parsing_frame = grpc_chttp2_incoming_byte_stream_create( p->parsing_frame = grpc_chttp2_incoming_byte_stream_create(
exec_ctx, t, s, p->frame_size, message_flags); t, s, p->frame_size, message_flags);
*stream_out = &p->parsing_frame->base; *stream_out = &p->parsing_frame->base;
if (p->parsing_frame->remaining_bytes == 0) { if (p->parsing_frame->remaining_bytes == 0) {
GRPC_ERROR_UNREF(grpc_chttp2_incoming_byte_stream_finished( GRPC_ERROR_UNREF(grpc_chttp2_incoming_byte_stream_finished(
exec_ctx, p->parsing_frame, GRPC_ERROR_NONE, true)); p->parsing_frame, GRPC_ERROR_NONE, true));
p->parsing_frame = nullptr; p->parsing_frame = nullptr;
p->state = GRPC_CHTTP2_DATA_FH_0; p->state = GRPC_CHTTP2_DATA_FH_0;
} }
@ -213,64 +212,64 @@ grpc_error* grpc_deframe_unprocessed_incoming_frames(
slices, slices,
grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg))); grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
} }
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(slice);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
case GRPC_CHTTP2_DATA_FRAME: { case GRPC_CHTTP2_DATA_FRAME: {
GPR_ASSERT(p->parsing_frame != nullptr); GPR_ASSERT(p->parsing_frame != nullptr);
GPR_ASSERT(slice_out != nullptr); GPR_ASSERT(slice_out != nullptr);
if (cur == end) { if (cur == end) {
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(slice);
continue; continue;
} }
uint32_t remaining = (uint32_t)(end - cur); uint32_t remaining = (uint32_t)(end - cur);
if (remaining == p->frame_size) { if (remaining == p->frame_size) {
s->stats.incoming.data_bytes += remaining; s->stats.incoming.data_bytes += remaining;
if (GRPC_ERROR_NONE != (error = grpc_chttp2_incoming_byte_stream_push( if (GRPC_ERROR_NONE != (error = grpc_chttp2_incoming_byte_stream_push(
exec_ctx, p->parsing_frame, p->parsing_frame,
grpc_slice_sub(slice, (size_t)(cur - beg), grpc_slice_sub(slice, (size_t)(cur - beg),
(size_t)(end - beg)), (size_t)(end - beg)),
slice_out))) { slice_out))) {
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(slice);
return error; return error;
} }
if (GRPC_ERROR_NONE != if (GRPC_ERROR_NONE !=
(error = grpc_chttp2_incoming_byte_stream_finished( (error = grpc_chttp2_incoming_byte_stream_finished(
exec_ctx, p->parsing_frame, GRPC_ERROR_NONE, true))) { p->parsing_frame, GRPC_ERROR_NONE, true))) {
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(slice);
return error; return error;
} }
p->parsing_frame = nullptr; p->parsing_frame = nullptr;
p->state = GRPC_CHTTP2_DATA_FH_0; p->state = GRPC_CHTTP2_DATA_FH_0;
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(slice);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} else if (remaining < p->frame_size) { } else if (remaining < p->frame_size) {
s->stats.incoming.data_bytes += remaining; s->stats.incoming.data_bytes += remaining;
if (GRPC_ERROR_NONE != (error = grpc_chttp2_incoming_byte_stream_push( if (GRPC_ERROR_NONE != (error = grpc_chttp2_incoming_byte_stream_push(
exec_ctx, p->parsing_frame, p->parsing_frame,
grpc_slice_sub(slice, (size_t)(cur - beg), grpc_slice_sub(slice, (size_t)(cur - beg),
(size_t)(end - beg)), (size_t)(end - beg)),
slice_out))) { slice_out))) {
return error; return error;
} }
p->frame_size -= remaining; p->frame_size -= remaining;
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(slice);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} else { } else {
GPR_ASSERT(remaining > p->frame_size); GPR_ASSERT(remaining > p->frame_size);
s->stats.incoming.data_bytes += p->frame_size; s->stats.incoming.data_bytes += p->frame_size;
if (GRPC_ERROR_NONE != if (GRPC_ERROR_NONE !=
(grpc_chttp2_incoming_byte_stream_push( (grpc_chttp2_incoming_byte_stream_push(
exec_ctx, p->parsing_frame, p->parsing_frame,
grpc_slice_sub(slice, (size_t)(cur - beg), grpc_slice_sub(slice, (size_t)(cur - beg),
(size_t)(cur + p->frame_size - beg)), (size_t)(cur + p->frame_size - beg)),
slice_out))) { slice_out))) {
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(slice);
return error; return error;
} }
if (GRPC_ERROR_NONE != if (GRPC_ERROR_NONE !=
(error = grpc_chttp2_incoming_byte_stream_finished( (error = grpc_chttp2_incoming_byte_stream_finished(
exec_ctx, p->parsing_frame, GRPC_ERROR_NONE, true))) { p->parsing_frame, GRPC_ERROR_NONE, true))) {
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(slice);
return error; return error;
} }
p->parsing_frame = nullptr; p->parsing_frame = nullptr;
@ -279,7 +278,7 @@ grpc_error* grpc_deframe_unprocessed_incoming_frames(
grpc_slice_buffer_undo_take_first( grpc_slice_buffer_undo_take_first(
slices, slices,
grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg))); grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(slice);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
} }
@ -289,19 +288,19 @@ grpc_error* grpc_deframe_unprocessed_incoming_frames(
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
grpc_error* grpc_chttp2_data_parser_parse(grpc_exec_ctx* exec_ctx, void* parser, grpc_error* grpc_chttp2_data_parser_parse(void* parser,
grpc_chttp2_transport* t, grpc_chttp2_transport* t,
grpc_chttp2_stream* s, grpc_chttp2_stream* s,
grpc_slice slice, int is_last) { grpc_slice slice, int is_last) {
if (!s->pending_byte_stream) { if (!s->pending_byte_stream) {
grpc_slice_ref_internal(slice); grpc_slice_ref_internal(slice);
grpc_slice_buffer_add(&s->frame_storage, slice); grpc_slice_buffer_add(&s->frame_storage, slice);
grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s); grpc_chttp2_maybe_complete_recv_message(t, s);
} else if (s->on_next) { } else if (s->on_next) {
GPR_ASSERT(s->frame_storage.length == 0); GPR_ASSERT(s->frame_storage.length == 0);
grpc_slice_ref_internal(slice); grpc_slice_ref_internal(slice);
grpc_slice_buffer_add(&s->unprocessed_incoming_frames_buffer, slice); grpc_slice_buffer_add(&s->unprocessed_incoming_frames_buffer, slice);
GRPC_CLOSURE_SCHED(exec_ctx, s->on_next, GRPC_ERROR_NONE); GRPC_CLOSURE_SCHED(s->on_next, GRPC_ERROR_NONE);
s->on_next = nullptr; s->on_next = nullptr;
s->unprocessed_incoming_frames_decompressed = false; s->unprocessed_incoming_frames_decompressed = false;
} else { } else {
@ -310,8 +309,7 @@ grpc_error* grpc_chttp2_data_parser_parse(grpc_exec_ctx* exec_ctx, void* parser,
} }
if (is_last && s->received_last_frame) { if (is_last && s->received_last_frame) {
grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, false, grpc_chttp2_mark_stream_closed(t, s, true, false, GRPC_ERROR_NONE);
GRPC_ERROR_NONE);
} }
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;

@ -54,8 +54,7 @@ typedef struct {
/* initialize per-stream state for data frame parsing */ /* initialize per-stream state for data frame parsing */
grpc_error* grpc_chttp2_data_parser_init(grpc_chttp2_data_parser* parser); grpc_error* grpc_chttp2_data_parser_init(grpc_chttp2_data_parser* parser);
void grpc_chttp2_data_parser_destroy(grpc_exec_ctx* exec_ctx, void grpc_chttp2_data_parser_destroy(grpc_chttp2_data_parser* parser);
grpc_chttp2_data_parser* parser);
/* start processing a new data frame */ /* start processing a new data frame */
grpc_error* grpc_chttp2_data_parser_begin_frame(grpc_chttp2_data_parser* parser, grpc_error* grpc_chttp2_data_parser_begin_frame(grpc_chttp2_data_parser* parser,
@ -65,7 +64,7 @@ grpc_error* grpc_chttp2_data_parser_begin_frame(grpc_chttp2_data_parser* parser,
/* handle a slice of a data frame - is_last indicates the last slice of a /* handle a slice of a data frame - is_last indicates the last slice of a
frame */ frame */
grpc_error* grpc_chttp2_data_parser_parse(grpc_exec_ctx* exec_ctx, void* parser, grpc_error* grpc_chttp2_data_parser_parse(void* parser,
grpc_chttp2_transport* t, grpc_chttp2_transport* t,
grpc_chttp2_stream* s, grpc_chttp2_stream* s,
grpc_slice slice, int is_last); grpc_slice slice, int is_last);
@ -76,7 +75,7 @@ void grpc_chttp2_encode_data(uint32_t id, grpc_slice_buffer* inbuf,
grpc_slice_buffer* outbuf); grpc_slice_buffer* outbuf);
grpc_error* grpc_deframe_unprocessed_incoming_frames( grpc_error* grpc_deframe_unprocessed_incoming_frames(
grpc_exec_ctx* exec_ctx, grpc_chttp2_data_parser* p, grpc_chttp2_stream* s, grpc_chttp2_data_parser* p, grpc_chttp2_stream* s,
grpc_slice_buffer* slices, grpc_slice* slice_out, grpc_slice_buffer* slices, grpc_slice* slice_out,
grpc_byte_stream** stream_out); grpc_byte_stream** stream_out);

@ -52,8 +52,7 @@ grpc_error* grpc_chttp2_goaway_parser_begin_frame(grpc_chttp2_goaway_parser* p,
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
grpc_error* grpc_chttp2_goaway_parser_parse(grpc_exec_ctx* exec_ctx, grpc_error* grpc_chttp2_goaway_parser_parse(void* parser,
void* parser,
grpc_chttp2_transport* t, grpc_chttp2_transport* t,
grpc_chttp2_stream* s, grpc_chttp2_stream* s,
grpc_slice slice, int is_last) { grpc_slice slice, int is_last) {
@ -135,7 +134,7 @@ grpc_error* grpc_chttp2_goaway_parser_parse(grpc_exec_ctx* exec_ctx,
p->state = GRPC_CHTTP2_GOAWAY_DEBUG; p->state = GRPC_CHTTP2_GOAWAY_DEBUG;
if (is_last) { if (is_last) {
grpc_chttp2_add_incoming_goaway( grpc_chttp2_add_incoming_goaway(
exec_ctx, t, (uint32_t)p->error_code, t, (uint32_t)p->error_code,
grpc_slice_new(p->debug_data, p->debug_length, gpr_free)); grpc_slice_new(p->debug_data, p->debug_length, gpr_free));
p->debug_data = nullptr; p->debug_data = nullptr;
} }

@ -50,8 +50,7 @@ void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser* p);
void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser* p); void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser* p);
grpc_error* grpc_chttp2_goaway_parser_begin_frame( grpc_error* grpc_chttp2_goaway_parser_begin_frame(
grpc_chttp2_goaway_parser* parser, uint32_t length, uint8_t flags); grpc_chttp2_goaway_parser* parser, uint32_t length, uint8_t flags);
grpc_error* grpc_chttp2_goaway_parser_parse(grpc_exec_ctx* exec_ctx, grpc_error* grpc_chttp2_goaway_parser_parse(void* parser,
void* parser,
grpc_chttp2_transport* t, grpc_chttp2_transport* t,
grpc_chttp2_stream* s, grpc_chttp2_stream* s,
grpc_slice slice, int is_last); grpc_slice slice, int is_last);

@ -68,7 +68,7 @@ grpc_error* grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser* parser,
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
grpc_error* grpc_chttp2_ping_parser_parse(grpc_exec_ctx* exec_ctx, void* parser, grpc_error* grpc_chttp2_ping_parser_parse(void* parser,
grpc_chttp2_transport* t, grpc_chttp2_transport* t,
grpc_chttp2_stream* s, grpc_chttp2_stream* s,
grpc_slice slice, int is_last) { grpc_slice slice, int is_last) {
@ -86,10 +86,10 @@ grpc_error* grpc_chttp2_ping_parser_parse(grpc_exec_ctx* exec_ctx, void* parser,
if (p->byte == 8) { if (p->byte == 8) {
GPR_ASSERT(is_last); GPR_ASSERT(is_last);
if (p->is_ack) { if (p->is_ack) {
grpc_chttp2_ack_ping(exec_ctx, t, p->opaque_8bytes); grpc_chttp2_ack_ping(t, p->opaque_8bytes);
} else { } else {
if (!t->is_client) { if (!t->is_client) {
grpc_millis now = grpc_exec_ctx_now(exec_ctx); grpc_millis now = grpc_core::ExecCtx::Get()->Now();
grpc_millis next_allowed_ping = grpc_millis next_allowed_ping =
t->ping_recv_state.last_ping_recv_time + t->ping_recv_state.last_ping_recv_time +
t->ping_policy.min_recv_ping_interval_without_data; t->ping_policy.min_recv_ping_interval_without_data;
@ -104,7 +104,7 @@ grpc_error* grpc_chttp2_ping_parser_parse(grpc_exec_ctx* exec_ctx, void* parser,
} }
if (next_allowed_ping > now) { if (next_allowed_ping > now) {
grpc_chttp2_add_ping_strike(exec_ctx, t); grpc_chttp2_add_ping_strike(t);
} }
t->ping_recv_state.last_ping_recv_time = now; t->ping_recv_state.last_ping_recv_time = now;
@ -116,8 +116,7 @@ grpc_error* grpc_chttp2_ping_parser_parse(grpc_exec_ctx* exec_ctx, void* parser,
t->ping_acks, t->ping_ack_capacity * sizeof(*t->ping_acks)); t->ping_acks, t->ping_ack_capacity * sizeof(*t->ping_acks));
} }
t->ping_acks[t->ping_ack_count++] = p->opaque_8bytes; t->ping_acks[t->ping_ack_count++] = p->opaque_8bytes;
grpc_chttp2_initiate_write(exec_ctx, t, grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_PING_RESPONSE);
GRPC_CHTTP2_INITIATE_WRITE_PING_RESPONSE);
} }
} }
} }

@ -33,7 +33,7 @@ grpc_slice grpc_chttp2_ping_create(uint8_t ack, uint64_t opaque_8bytes);
grpc_error* grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser* parser, grpc_error* grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser* parser,
uint32_t length, uint8_t flags); uint32_t length, uint8_t flags);
grpc_error* grpc_chttp2_ping_parser_parse(grpc_exec_ctx* exec_ctx, void* parser, grpc_error* grpc_chttp2_ping_parser_parse(void* parser,
grpc_chttp2_transport* t, grpc_chttp2_transport* t,
grpc_chttp2_stream* s, grpc_chttp2_stream* s,
grpc_slice slice, int is_last); grpc_slice slice, int is_last);

@ -69,8 +69,7 @@ grpc_error* grpc_chttp2_rst_stream_parser_begin_frame(
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
grpc_error* grpc_chttp2_rst_stream_parser_parse(grpc_exec_ctx* exec_ctx, grpc_error* grpc_chttp2_rst_stream_parser_parse(void* parser,
void* parser,
grpc_chttp2_transport* t, grpc_chttp2_transport* t,
grpc_chttp2_stream* s, grpc_chttp2_stream* s,
grpc_slice slice, int is_last) { grpc_slice slice, int is_last) {
@ -103,7 +102,7 @@ grpc_error* grpc_chttp2_rst_stream_parser_parse(grpc_exec_ctx* exec_ctx,
GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)reason); GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)reason);
gpr_free(message); gpr_free(message);
} }
grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, true, error); grpc_chttp2_mark_stream_closed(t, s, true, true, error);
} }
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;

@ -34,8 +34,7 @@ grpc_slice grpc_chttp2_rst_stream_create(uint32_t stream_id, uint32_t code,
grpc_error* grpc_chttp2_rst_stream_parser_begin_frame( grpc_error* grpc_chttp2_rst_stream_parser_begin_frame(
grpc_chttp2_rst_stream_parser* parser, uint32_t length, uint8_t flags); grpc_chttp2_rst_stream_parser* parser, uint32_t length, uint8_t flags);
grpc_error* grpc_chttp2_rst_stream_parser_parse(grpc_exec_ctx* exec_ctx, grpc_error* grpc_chttp2_rst_stream_parser_parse(void* parser,
void* parser,
grpc_chttp2_transport* t, grpc_chttp2_transport* t,
grpc_chttp2_stream* s, grpc_chttp2_stream* s,
grpc_slice slice, int is_last); grpc_slice slice, int is_last);

@ -108,8 +108,7 @@ grpc_error* grpc_chttp2_settings_parser_begin_frame(
} }
} }
grpc_error* grpc_chttp2_settings_parser_parse(grpc_exec_ctx* exec_ctx, void* p, grpc_error* grpc_chttp2_settings_parser_parse(void* p, grpc_chttp2_transport* t,
grpc_chttp2_transport* t,
grpc_chttp2_stream* s, grpc_chttp2_stream* s,
grpc_slice slice, int is_last) { grpc_slice slice, int is_last) {
grpc_chttp2_settings_parser* parser = (grpc_chttp2_settings_parser*)p; grpc_chttp2_settings_parser* parser = (grpc_chttp2_settings_parser*)p;
@ -132,7 +131,7 @@ grpc_error* grpc_chttp2_settings_parser_parse(grpc_exec_ctx* exec_ctx, void* p,
GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t)); GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
grpc_slice_buffer_add(&t->qbuf, grpc_chttp2_settings_ack_create()); grpc_slice_buffer_add(&t->qbuf, grpc_chttp2_settings_ack_create());
if (t->notify_on_receive_settings != nullptr) { if (t->notify_on_receive_settings != nullptr) {
GRPC_CLOSURE_SCHED(exec_ctx, t->notify_on_receive_settings, GRPC_CLOSURE_SCHED(t->notify_on_receive_settings,
GRPC_ERROR_NONE); GRPC_ERROR_NONE);
t->notify_on_receive_settings = nullptr; t->notify_on_receive_settings = nullptr;
} }

@ -52,8 +52,7 @@ grpc_slice grpc_chttp2_settings_ack_create(void);
grpc_error* grpc_chttp2_settings_parser_begin_frame( grpc_error* grpc_chttp2_settings_parser_begin_frame(
grpc_chttp2_settings_parser* parser, uint32_t length, uint8_t flags, grpc_chttp2_settings_parser* parser, uint32_t length, uint8_t flags,
uint32_t* settings); uint32_t* settings);
grpc_error* grpc_chttp2_settings_parser_parse(grpc_exec_ctx* exec_ctx, grpc_error* grpc_chttp2_settings_parser_parse(void* parser,
void* parser,
grpc_chttp2_transport* t, grpc_chttp2_transport* t,
grpc_chttp2_stream* s, grpc_chttp2_stream* s,
grpc_slice slice, int is_last); grpc_slice slice, int is_last);

@ -64,9 +64,11 @@ grpc_error* grpc_chttp2_window_update_parser_begin_frame(
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
grpc_error* grpc_chttp2_window_update_parser_parse( grpc_error* grpc_chttp2_window_update_parser_parse(void* parser,
grpc_exec_ctx* exec_ctx, void* parser, grpc_chttp2_transport* t, grpc_chttp2_transport* t,
grpc_chttp2_stream* s, grpc_slice slice, int is_last) { grpc_chttp2_stream* s,
grpc_slice slice,
int is_last) {
uint8_t* const beg = GRPC_SLICE_START_PTR(slice); uint8_t* const beg = GRPC_SLICE_START_PTR(slice);
uint8_t* const end = GRPC_SLICE_END_PTR(slice); uint8_t* const end = GRPC_SLICE_END_PTR(slice);
uint8_t* cur = beg; uint8_t* cur = beg;
@ -98,10 +100,9 @@ grpc_error* grpc_chttp2_window_update_parser_parse(
if (s != nullptr) { if (s != nullptr) {
s->flow_control->RecvUpdate(received_update); s->flow_control->RecvUpdate(received_update);
if (grpc_chttp2_list_remove_stalled_by_stream(t, s)) { if (grpc_chttp2_list_remove_stalled_by_stream(t, s)) {
grpc_chttp2_mark_stream_writable(exec_ctx, t, s); grpc_chttp2_mark_stream_writable(t, s);
grpc_chttp2_initiate_write( grpc_chttp2_initiate_write(
exec_ctx, t, t, GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_UPDATE);
GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_UPDATE);
} }
} }
} else { } else {
@ -110,8 +111,7 @@ grpc_error* grpc_chttp2_window_update_parser_parse(
bool is_zero = t->flow_control->remote_window() <= 0; bool is_zero = t->flow_control->remote_window() <= 0;
if (was_zero && !is_zero) { if (was_zero && !is_zero) {
grpc_chttp2_initiate_write( grpc_chttp2_initiate_write(
exec_ctx, t, t, GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL_UNSTALLED);
GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL_UNSTALLED);
} }
} }
} }

@ -35,8 +35,10 @@ grpc_slice grpc_chttp2_window_update_create(
grpc_error* grpc_chttp2_window_update_parser_begin_frame( grpc_error* grpc_chttp2_window_update_parser_begin_frame(
grpc_chttp2_window_update_parser* parser, uint32_t length, uint8_t flags); grpc_chttp2_window_update_parser* parser, uint32_t length, uint8_t flags);
grpc_error* grpc_chttp2_window_update_parser_parse( grpc_error* grpc_chttp2_window_update_parser_parse(void* parser,
grpc_exec_ctx* exec_ctx, void* parser, grpc_chttp2_transport* t, grpc_chttp2_transport* t,
grpc_chttp2_stream* s, grpc_slice slice, int is_last); grpc_chttp2_stream* s,
grpc_slice slice,
int is_last);
#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_WINDOW_UPDATE_H */ #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_WINDOW_UPDATE_H */

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

Loading…
Cancel
Save