aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Sree Kuchibhotla <sreek@google.com>2018-08-09 12:13:41 -0700
committerGravatar Sree Kuchibhotla <sreek@google.com>2018-08-09 12:13:41 -0700
commitf63b51be86142138337d2f3166df6954db18c454 (patch)
tree4ae6cde0cc0b2452478f7f3520c1325e9cf039b7 /src
parent82f0275998ee7b18f806514d4bad48b191d0ca53 (diff)
parentcb87dd9fef97d1e1fb2559be68188c0792a3ecd8 (diff)
Merge branch 'master' into rq-threads-2
Diffstat (limited to 'src')
-rw-r--r--src/core/ext/filters/client_channel/client_channel.cc11
-rw-r--r--src/core/ext/filters/client_channel/client_channel_plugin.cc2
-rw-r--r--src/core/ext/filters/client_channel/lb_policy.h5
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc12
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc8
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc8
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/subchannel_list.h27
-rw-r--r--src/core/ext/filters/client_channel/resolver.h8
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc9
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc17
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h22
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc18
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc508
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc2
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h7
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc9
-rw-r--r--src/core/ext/filters/client_channel/subchannel.cc18
-rw-r--r--src/core/ext/filters/client_channel/subchannel.h7
-rw-r--r--src/core/ext/filters/deadline/deadline_filter.cc4
-rw-r--r--src/core/ext/filters/http/client_authority_filter.cc12
-rw-r--r--src/core/ext/filters/http/http_filters_plugin.cc27
-rw-r--r--src/core/ext/filters/load_reporting/server_load_reporting_filter.cc3
-rw-r--r--src/core/ext/filters/max_age/max_age_filter.cc2
-rw-r--r--src/core/ext/filters/message_size/message_size_filter.cc6
-rw-r--r--src/core/lib/channel/connected_channel.cc4
-rw-r--r--src/core/lib/channel/connected_channel.h4
-rw-r--r--src/core/lib/iomgr/iocp_windows.cc13
-rw-r--r--src/core/lib/iomgr/socket_windows.cc4
-rw-r--r--src/core/lib/iomgr/socket_windows.h2
-rw-r--r--src/core/lib/iomgr/tcp_windows.cc4
-rw-r--r--src/core/lib/iomgr/tcp_windows.h2
-rw-r--r--src/core/lib/surface/channel.cc11
-rw-r--r--src/core/lib/surface/channel_init.h28
-rw-r--r--src/core/lib/surface/init.cc26
-rw-r--r--src/core/lib/surface/init_secure.cc11
-rw-r--r--src/core/lib/transport/transport.h2
-rw-r--r--src/cpp/client/channel_cc.cc8
-rw-r--r--src/cpp/common/channel_filter.cc9
-rw-r--r--src/cpp/common/channel_filter.h7
-rw-r--r--src/cpp/ext/filters/census/grpc_plugin.cc6
-rw-r--r--src/cpp/server/load_reporter/util.cc2
-rwxr-xr-xsrc/csharp/Grpc.Core/Version.csproj.include2
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Control.cs26
-rw-r--r--src/csharp/Grpc.IntegrationTesting/EchoMessages.cs55
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Messages.cs26
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Stats.cs6
-rw-r--r--src/csharp/Grpc.Reflection/Reflection.cs2
-rw-r--r--src/csharp/build_unitypackage.bat4
-rw-r--r--src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/android/arm64-v8a/libgrpc_csharp_ext.so.meta2
-rw-r--r--src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/android/armeabi-v7a/libgrpc_csharp_ext.so.meta2
-rw-r--r--src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/android/x86/libgrpc_csharp_ext.so.meta2
-rw-r--r--src/objective-c/!ProtoCompiler-gRPCPlugin.podspec2
-rw-r--r--src/objective-c/!ProtoCompiler.podspec2
-rw-r--r--src/python/grpcio_health_checking/setup.py2
-rw-r--r--src/python/grpcio_reflection/setup.py2
-rw-r--r--src/python/grpcio_testing/setup.py2
-rw-r--r--src/python/grpcio_tests/setup.py4
-rw-r--r--src/ruby/ext/grpc/rb_grpc_imports.generated.c2
-rw-r--r--src/ruby/ext/grpc/rb_grpc_imports.generated.h3
59 files changed, 891 insertions, 150 deletions
diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc
index fead8feb17..b06f09d8c7 100644
--- a/src/core/ext/filters/client_channel/client_channel.cc
+++ b/src/core/ext/filters/client_channel/client_channel.cc
@@ -622,6 +622,17 @@ static void start_transport_op_locked(void* arg, grpc_error* error_ignored) {
}
GRPC_ERROR_UNREF(op->disconnect_with_error);
}
+
+ if (op->reset_connect_backoff) {
+ if (chand->resolver != nullptr) {
+ chand->resolver->ResetBackoffLocked();
+ chand->resolver->RequestReresolutionLocked();
+ }
+ if (chand->lb_policy != nullptr) {
+ chand->lb_policy->ResetBackoffLocked();
+ }
+ }
+
GRPC_CHANNEL_STACK_UNREF(chand->owning_stack, "start_transport_op");
GRPC_CLOSURE_SCHED(op->on_consumed, GRPC_ERROR_NONE);
diff --git a/src/core/ext/filters/client_channel/client_channel_plugin.cc b/src/core/ext/filters/client_channel/client_channel_plugin.cc
index e0784b7e5c..71da648660 100644
--- a/src/core/ext/filters/client_channel/client_channel_plugin.cc
+++ b/src/core/ext/filters/client_channel/client_channel_plugin.cc
@@ -56,7 +56,7 @@ void grpc_client_channel_init(void) {
grpc_register_http_proxy_mapper();
grpc_subchannel_index_init();
grpc_channel_init_register_stage(
- GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, append_filter,
+ GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_MAX, append_filter,
(void*)&grpc_client_channel_filter);
grpc_http_connect_register_handshaker_factory();
}
diff --git a/src/core/ext/filters/client_channel/lb_policy.h b/src/core/ext/filters/client_channel/lb_policy.h
index 31c08246ae..3c0a9c1118 100644
--- a/src/core/ext/filters/client_channel/lb_policy.h
+++ b/src/core/ext/filters/client_channel/lb_policy.h
@@ -144,7 +144,10 @@ class LoadBalancingPolicy
/// consider whether this method is still needed.
virtual void ExitIdleLocked() GRPC_ABSTRACT;
- /// populates child_subchannels and child_channels with the uuids of this
+ /// Resets connection backoff.
+ virtual void ResetBackoffLocked() GRPC_ABSTRACT;
+
+ /// Populates child_subchannels and child_channels with the uuids of this
/// LB policy's referenced children. This is not invoked from the
/// client_channel's combiner. The implementation is responsible for
/// providing its own synchronization.
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
index 2d1f777474..6581385ff9 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
@@ -134,6 +134,7 @@ class GrpcLb : public LoadBalancingPolicy {
grpc_error** connectivity_error) override;
void HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) override;
void ExitIdleLocked() override;
+ void ResetBackoffLocked() override;
void FillChildRefsForChannelz(ChildRefsList* child_subchannels,
ChildRefsList* child_channels) override;
@@ -1214,6 +1215,15 @@ void GrpcLb::ExitIdleLocked() {
}
}
+void GrpcLb::ResetBackoffLocked() {
+ if (lb_channel_ != nullptr) {
+ grpc_channel_reset_connect_backoff(lb_channel_);
+ }
+ if (rr_policy_ != nullptr) {
+ rr_policy_->ResetBackoffLocked();
+ }
+}
+
bool GrpcLb::PickLocked(PickState* pick, grpc_error** error) {
PendingPick* pp = PendingPickCreate(pick);
bool pick_done = false;
@@ -1880,7 +1890,7 @@ void grpc_lb_policy_grpclb_init() {
grpc_core::UniquePtr<grpc_core::LoadBalancingPolicyFactory>(
grpc_core::New<grpc_core::GrpcLbFactory>()));
grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL,
- GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+ GRPC_CHANNEL_INIT_PRIORITY_LOW,
maybe_add_client_load_reporting_filter,
(void*)&grpc_client_load_reporting_filter);
}
diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
index 46acbf628b..2b6a9ba8c5 100644
--- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
@@ -57,6 +57,7 @@ class PickFirst : public LoadBalancingPolicy {
grpc_error** connectivity_error) override;
void HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) override;
void ExitIdleLocked() override;
+ void ResetBackoffLocked() override;
void FillChildRefsForChannelz(ChildRefsList* child_subchannels,
ChildRefsList* ignored) override;
@@ -259,6 +260,13 @@ void PickFirst::ExitIdleLocked() {
}
}
+void PickFirst::ResetBackoffLocked() {
+ subchannel_list_->ResetBackoffLocked();
+ if (latest_pending_subchannel_list_ != nullptr) {
+ latest_pending_subchannel_list_->ResetBackoffLocked();
+ }
+}
+
bool PickFirst::PickLocked(PickState* pick, grpc_error** error) {
// If we have a selected subchannel already, return synchronously.
if (selected_ != nullptr) {
diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
index 9c3a15c67b..fea84331d8 100644
--- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
@@ -68,6 +68,7 @@ class RoundRobin : public LoadBalancingPolicy {
grpc_error** connectivity_error) override;
void HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) override;
void ExitIdleLocked() override;
+ void ResetBackoffLocked() override;
void FillChildRefsForChannelz(ChildRefsList* child_subchannels,
ChildRefsList* ignored) override;
@@ -333,6 +334,13 @@ void RoundRobin::ExitIdleLocked() {
}
}
+void RoundRobin::ResetBackoffLocked() {
+ subchannel_list_->ResetBackoffLocked();
+ if (latest_pending_subchannel_list_ != nullptr) {
+ latest_pending_subchannel_list_->ResetBackoffLocked();
+ }
+}
+
bool RoundRobin::DoPickLocked(PickState* pick) {
const size_t next_ready_index =
subchannel_list_->GetNextReadySubchannelIndexLocked();
diff --git a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
index 018ac3bb86..0fa2f04e73 100644
--- a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
+++ b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
@@ -107,6 +107,11 @@ class SubchannelData {
// being unreffed.
virtual void UnrefSubchannelLocked(const char* reason);
+ // Resets the connection backoff.
+ // TODO(roth): This method should go away when we move the backoff
+ // code out of the subchannel and into the LB policies.
+ void ResetBackoffLocked();
+
// Starts watching the connectivity state of the subchannel.
// ProcessConnectivityChangeLocked() will be called when the
// connectivity state changes.
@@ -206,6 +211,11 @@ class SubchannelList
LoadBalancingPolicy* policy() const { return policy_; }
TraceFlag* tracer() const { return tracer_; }
+ // Resets connection backoff of all subchannels.
+ // TODO(roth): We will probably need to rethink this as part of moving
+ // the backoff code out of subchannels and into LB policies.
+ void ResetBackoffLocked();
+
// Note: Caller must ensure that this is invoked inside of the combiner.
void Orphan() override {
ShutdownLocked();
@@ -300,6 +310,14 @@ void SubchannelData<SubchannelListType, SubchannelDataType>::
template <typename SubchannelListType, typename SubchannelDataType>
void SubchannelData<SubchannelListType,
+ SubchannelDataType>::ResetBackoffLocked() {
+ if (subchannel_ != nullptr) {
+ grpc_subchannel_reset_backoff(subchannel_);
+ }
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelData<SubchannelListType,
SubchannelDataType>::StartConnectivityWatchLocked() {
if (subchannel_list_->tracer()->enabled()) {
gpr_log(GPR_INFO,
@@ -544,6 +562,15 @@ void SubchannelList<SubchannelListType, SubchannelDataType>::ShutdownLocked() {
}
}
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelList<SubchannelListType,
+ SubchannelDataType>::ResetBackoffLocked() {
+ for (size_t i = 0; i < subchannels_.size(); i++) {
+ SubchannelDataType* sd = &subchannels_[i];
+ sd->ResetBackoffLocked();
+ }
+}
+
} // namespace grpc_core
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_SUBCHANNEL_LIST_H */
diff --git a/src/core/ext/filters/client_channel/resolver.h b/src/core/ext/filters/client_channel/resolver.h
index c7e37e4468..48f2e89095 100644
--- a/src/core/ext/filters/client_channel/resolver.h
+++ b/src/core/ext/filters/client_channel/resolver.h
@@ -94,6 +94,14 @@ class Resolver : public InternallyRefCountedWithTracing<Resolver> {
/// throw away unselected subchannels.
virtual void RequestReresolutionLocked() GRPC_ABSTRACT;
+ /// Resets the re-resolution backoff, if any.
+ /// This needs to be implemented only by pull-based implementations;
+ /// for push-based implementations, it will be a no-op.
+ /// TODO(roth): Pull the backoff code out of resolver and into
+ /// client_channel, so that it can be shared across resolver
+ /// implementations. At that point, this method can go away.
+ virtual void ResetBackoffLocked() {}
+
void Orphan() override {
// Invoke ShutdownAndUnrefLocked() inside of the combiner.
GRPC_CLOSURE_SCHED(
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
index 7050e82121..f2bb5f3c71 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
@@ -66,6 +66,8 @@ class AresDnsResolver : public Resolver {
void RequestReresolutionLocked() override;
+ void ResetBackoffLocked() override;
+
void ShutdownLocked() override;
private:
@@ -187,6 +189,13 @@ void AresDnsResolver::RequestReresolutionLocked() {
}
}
+void AresDnsResolver::ResetBackoffLocked() {
+ if (have_next_resolution_timer_) {
+ grpc_timer_cancel(&next_resolution_timer_);
+ }
+ backoff_.Reset();
+}
+
void AresDnsResolver::ShutdownLocked() {
if (have_next_resolution_timer_) {
grpc_timer_cancel(&next_resolution_timer_);
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc
index 0068d0d5f4..fdbd07ebf5 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc
@@ -74,6 +74,8 @@ struct grpc_ares_ev_driver {
bool shutting_down;
/** request object that's using this ev driver */
grpc_ares_request* request;
+ /** Owned by the ev_driver. Creates new GrpcPolledFd's */
+ grpc_core::UniquePtr<grpc_core::GrpcPolledFdFactory> polled_fd_factory;
};
static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver);
@@ -93,7 +95,7 @@ static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver* ev_driver) {
GRPC_COMBINER_UNREF(ev_driver->combiner, "free ares event driver");
ares_destroy(ev_driver->channel);
grpc_ares_complete_request_locked(ev_driver->request);
- gpr_free(ev_driver);
+ grpc_core::Delete(ev_driver);
}
}
@@ -118,13 +120,11 @@ grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
grpc_pollset_set* pollset_set,
grpc_combiner* combiner,
grpc_ares_request* request) {
- *ev_driver = static_cast<grpc_ares_ev_driver*>(
- gpr_malloc(sizeof(grpc_ares_ev_driver)));
+ *ev_driver = grpc_core::New<grpc_ares_ev_driver>();
ares_options opts;
memset(&opts, 0, sizeof(opts));
opts.flags |= ARES_FLAG_STAYOPEN;
int status = ares_init_options(&(*ev_driver)->channel, &opts, ARES_OPT_FLAGS);
- grpc_core::ConfigureAresChannelLocked(&(*ev_driver)->channel);
gpr_log(GPR_DEBUG, "grpc_ares_ev_driver_create_locked");
if (status != ARES_SUCCESS) {
char* err_msg;
@@ -142,6 +142,10 @@ grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
(*ev_driver)->working = false;
(*ev_driver)->shutting_down = false;
(*ev_driver)->request = request;
+ (*ev_driver)->polled_fd_factory =
+ grpc_core::NewGrpcPolledFdFactory((*ev_driver)->combiner);
+ (*ev_driver)
+ ->polled_fd_factory->ConfigureAresChannelLocked((*ev_driver)->channel);
return GRPC_ERROR_NONE;
}
@@ -245,8 +249,9 @@ static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver) {
// Create a new fd_node if sock[i] is not in the fd_node list.
if (fdn == nullptr) {
fdn = static_cast<fd_node*>(gpr_malloc(sizeof(fd_node)));
- fdn->grpc_polled_fd = grpc_core::NewGrpcPolledFdLocked(
- socks[i], ev_driver->pollset_set);
+ fdn->grpc_polled_fd =
+ ev_driver->polled_fd_factory->NewGrpcPolledFdLocked(
+ socks[i], ev_driver->pollset_set, ev_driver->combiner);
gpr_log(GPR_DEBUG, "new fd: %s", fdn->grpc_polled_fd->GetName());
fdn->ev_driver = ev_driver;
fdn->readable_registered = false;
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h
index 2c9db71011..671c537fe7 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h
@@ -81,10 +81,24 @@ class GrpcPolledFd {
GRPC_ABSTRACT_BASE_CLASS
};
-/* Creates a new wrapped fd for the current platform */
-GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as,
- grpc_pollset_set* driver_pollset_set);
-void ConfigureAresChannelLocked(ares_channel* channel);
+/* A GrpcPolledFdFactory is 1-to-1 with and owned by the
+ * ares event driver. It knows how to create GrpcPolledFd's
+ * for the current platform, and the ares driver uses it for all of
+ * its fd's. */
+class GrpcPolledFdFactory {
+ public:
+ virtual ~GrpcPolledFdFactory() {}
+ /* Creates a new wrapped fd for the current platform */
+ virtual GrpcPolledFd* NewGrpcPolledFdLocked(
+ ares_socket_t as, grpc_pollset_set* driver_pollset_set,
+ grpc_combiner* combiner) GRPC_ABSTRACT;
+ /* Optionally configures the ares channel after creation */
+ virtual void ConfigureAresChannelLocked(ares_channel channel) GRPC_ABSTRACT;
+
+ GRPC_ABSTRACT_BASE_CLASS
+};
+
+UniquePtr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(grpc_combiner* combiner);
} // namespace grpc_core
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
index fffe9eda8e..aa58e1aaf5 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
@@ -86,12 +86,20 @@ class GrpcPolledFdPosix : public GrpcPolledFd {
grpc_pollset_set* driver_pollset_set_;
};
-GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as,
- grpc_pollset_set* driver_pollset_set) {
- return grpc_core::New<GrpcPolledFdPosix>(as, driver_pollset_set);
-}
+class GrpcPolledFdFactoryPosix : public GrpcPolledFdFactory {
+ public:
+ GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as,
+ grpc_pollset_set* driver_pollset_set,
+ grpc_combiner* combiner) override {
+ return New<GrpcPolledFdPosix>(as, driver_pollset_set);
+ }
-void ConfigureAresChannelLocked(ares_channel* channel) {}
+ void ConfigureAresChannelLocked(ares_channel channel) override {}
+};
+
+UniquePtr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(grpc_combiner* combiner) {
+ return UniquePtr<GrpcPolledFdFactory>(New<GrpcPolledFdFactoryPosix>());
+}
} // namespace grpc_core
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc
index 5d65ae3ab3..02121aa0ab 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc
@@ -21,38 +21,516 @@
#if GRPC_ARES == 1 && defined(GPR_WINDOWS)
#include <ares.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/log_windows.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/time.h>
#include <string.h>
+#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/memory.h"
+#include "src/core/lib/iomgr/combiner.h"
+#include "src/core/lib/iomgr/socket_windows.h"
+#include "src/core/lib/iomgr/tcp_windows.h"
+#include "src/core/lib/slice/slice_internal.h"
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"
+#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
+
+/* TODO(apolcyn): remove this hack after fixing upstream.
+ * Our grpc/c-ares code on Windows uses the ares_set_socket_functions API,
+ * which uses "struct iovec" type, which on Windows is defined inside of
+ * a c-ares header that is not public.
+ * See https://github.com/c-ares/c-ares/issues/206. */
+struct iovec {
+ void* iov_base;
+ size_t iov_len;
+};
namespace grpc_core {
-/* TODO: fill in the body of GrpcPolledFdWindows to enable c-ares on Windows.
- This dummy implementation only allows grpc to compile on windows with
- GRPC_ARES=1. */
+/* c-ares creates its own sockets and is meant to read them when readable and
+ * write them when writeable. To fit this socket usage model into the grpc
+ * windows poller (which gives notifications when attempted reads and writes are
+ * actually fulfilled rather than possible), this GrpcPolledFdWindows class
+ * takes advantage of the ares_set_socket_functions API and acts as a virtual
+ * socket. It holds its own read and write buffers which are written to and read
+ * from c-ares and are used with the grpc windows poller, and it, e.g.,
+ * manufactures virtual socket error codes when it e.g. needs to tell the c-ares
+ * library to wait for an async read. */
class GrpcPolledFdWindows : public GrpcPolledFd {
public:
- GrpcPolledFdWindows() { abort(); }
- ~GrpcPolledFdWindows() { abort(); }
+ enum WriteState {
+ WRITE_IDLE,
+ WRITE_REQUESTED,
+ WRITE_PENDING,
+ WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY,
+ };
+
+ GrpcPolledFdWindows(ares_socket_t as, grpc_combiner* combiner)
+ : read_buf_(grpc_empty_slice()),
+ write_buf_(grpc_empty_slice()),
+ write_state_(WRITE_IDLE),
+ gotten_into_driver_list_(false) {
+ gpr_asprintf(&name_, "c-ares socket: %" PRIdPTR, as);
+ winsocket_ = grpc_winsocket_create(as, name_);
+ combiner_ = GRPC_COMBINER_REF(combiner, name_);
+ GRPC_CLOSURE_INIT(&outer_read_closure_,
+ &GrpcPolledFdWindows::OnIocpReadable, this,
+ grpc_combiner_scheduler(combiner_));
+ GRPC_CLOSURE_INIT(&outer_write_closure_,
+ &GrpcPolledFdWindows::OnIocpWriteable, this,
+ grpc_combiner_scheduler(combiner_));
+ }
+
+ ~GrpcPolledFdWindows() {
+ GRPC_COMBINER_UNREF(combiner_, name_);
+ grpc_slice_unref_internal(read_buf_);
+ grpc_slice_unref_internal(write_buf_);
+ GPR_ASSERT(read_closure_ == nullptr);
+ GPR_ASSERT(write_closure_ == nullptr);
+ grpc_winsocket_destroy(winsocket_);
+ gpr_free(name_);
+ }
+
+ void ScheduleAndNullReadClosure(grpc_error* error) {
+ GRPC_CLOSURE_SCHED(read_closure_, error);
+ read_closure_ = nullptr;
+ }
+
+ void ScheduleAndNullWriteClosure(grpc_error* error) {
+ GRPC_CLOSURE_SCHED(write_closure_, error);
+ write_closure_ = nullptr;
+ }
+
void RegisterForOnReadableLocked(grpc_closure* read_closure) override {
- abort();
+ GPR_ASSERT(read_closure_ == nullptr);
+ read_closure_ = read_closure;
+ GPR_ASSERT(GRPC_SLICE_LENGTH(read_buf_) == 0);
+ grpc_slice_unref_internal(read_buf_);
+ read_buf_ = GRPC_SLICE_MALLOC(4192);
+ WSABUF buffer;
+ buffer.buf = (char*)GRPC_SLICE_START_PTR(read_buf_);
+ buffer.len = GRPC_SLICE_LENGTH(read_buf_);
+ memset(&winsocket_->read_info.overlapped, 0, sizeof(OVERLAPPED));
+ recv_from_source_addr_len_ = sizeof(recv_from_source_addr_);
+ DWORD flags = 0;
+ if (WSARecvFrom(grpc_winsocket_wrapped_socket(winsocket_), &buffer, 1,
+ nullptr, &flags, (sockaddr*)recv_from_source_addr_,
+ &recv_from_source_addr_len_,
+ &winsocket_->read_info.overlapped, nullptr)) {
+ char* msg = gpr_format_message(WSAGetLastError());
+ grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
+ GRPC_CARES_TRACE_LOG(
+ "RegisterForOnReadableLocked: WSARecvFrom error:|%s|. fd:|%s|", msg,
+ GetName());
+ gpr_free(msg);
+ if (WSAGetLastError() != WSA_IO_PENDING) {
+ ScheduleAndNullReadClosure(error);
+ return;
+ }
+ }
+ grpc_socket_notify_on_read(winsocket_, &outer_read_closure_);
}
+
void RegisterForOnWriteableLocked(grpc_closure* write_closure) override {
+ GRPC_CARES_TRACE_LOG(
+ "RegisterForOnWriteableLocked. fd:|%s|. Current write state: %d",
+ GetName(), write_state_);
+ GPR_ASSERT(write_closure_ == nullptr);
+ write_closure_ = write_closure;
+ switch (write_state_) {
+ case WRITE_IDLE:
+ ScheduleAndNullWriteClosure(GRPC_ERROR_NONE);
+ break;
+ case WRITE_REQUESTED:
+ write_state_ = WRITE_PENDING;
+ SendWriteBuf(nullptr, &winsocket_->write_info.overlapped);
+ grpc_socket_notify_on_write(winsocket_, &outer_write_closure_);
+ break;
+ case WRITE_PENDING:
+ case WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY:
+ abort();
+ }
+ }
+
+ bool IsFdStillReadableLocked() override {
+ return GRPC_SLICE_LENGTH(read_buf_) > 0;
+ }
+
+ void ShutdownLocked(grpc_error* error) override {
+ grpc_winsocket_shutdown(winsocket_);
+ }
+
+ ares_socket_t GetWrappedAresSocketLocked() override {
+ return grpc_winsocket_wrapped_socket(winsocket_);
+ }
+
+ const char* GetName() override { return name_; }
+
+ ares_ssize_t RecvFrom(void* data, ares_socket_t data_len, int flags,
+ struct sockaddr* from, ares_socklen_t* from_len) {
+ GRPC_CARES_TRACE_LOG(
+ "RecvFrom called on fd:|%s|. Current read buf length:|%d|", GetName(),
+ GRPC_SLICE_LENGTH(read_buf_));
+ if (GRPC_SLICE_LENGTH(read_buf_) == 0) {
+ WSASetLastError(WSAEWOULDBLOCK);
+ return -1;
+ }
+ ares_ssize_t bytes_read = 0;
+ for (size_t i = 0; i < GRPC_SLICE_LENGTH(read_buf_) && i < data_len; i++) {
+ ((char*)data)[i] = GRPC_SLICE_START_PTR(read_buf_)[i];
+ bytes_read++;
+ }
+ read_buf_ = grpc_slice_sub_no_ref(read_buf_, bytes_read,
+ GRPC_SLICE_LENGTH(read_buf_));
+ /* c-ares overloads this recv_from virtual socket function to receive
+ * data on both UDP and TCP sockets, and from is nullptr for TCP. */
+ if (from != nullptr) {
+ GPR_ASSERT(*from_len <= recv_from_source_addr_len_);
+ memcpy(from, &recv_from_source_addr_, recv_from_source_addr_len_);
+ *from_len = recv_from_source_addr_len_;
+ }
+ return bytes_read;
+ }
+
+ grpc_slice FlattenIovec(const struct iovec* iov, int iov_count) {
+ int total = 0;
+ for (int i = 0; i < iov_count; i++) {
+ total += iov[i].iov_len;
+ }
+ grpc_slice out = GRPC_SLICE_MALLOC(total);
+ size_t cur = 0;
+ for (int i = 0; i < iov_count; i++) {
+ for (int k = 0; k < iov[i].iov_len; k++) {
+ GRPC_SLICE_START_PTR(out)[cur++] = ((char*)iov[i].iov_base)[k];
+ }
+ }
+ return out;
+ }
+
+ int SendWriteBuf(LPDWORD bytes_sent_ptr, LPWSAOVERLAPPED overlapped) {
+ WSABUF buf;
+ buf.len = GRPC_SLICE_LENGTH(write_buf_);
+ buf.buf = (char*)GRPC_SLICE_START_PTR(write_buf_);
+ DWORD flags = 0;
+ int out = WSASend(grpc_winsocket_wrapped_socket(winsocket_), &buf, 1,
+ bytes_sent_ptr, flags, overlapped, nullptr);
+ GRPC_CARES_TRACE_LOG(
+ "WSASend: name:%s. buf len:%d. bytes sent: %d. overlapped %p. return "
+ "val: %d",
+ GetName(), buf.len, *bytes_sent_ptr, overlapped, out);
+ return out;
+ }
+
+ ares_ssize_t TrySendWriteBufSyncNonBlocking() {
+ GPR_ASSERT(write_state_ == WRITE_IDLE);
+ ares_ssize_t total_sent;
+ DWORD bytes_sent = 0;
+ if (SendWriteBuf(&bytes_sent, nullptr) != 0) {
+ char* msg = gpr_format_message(WSAGetLastError());
+ GRPC_CARES_TRACE_LOG(
+ "TrySendWriteBufSyncNonBlocking: SendWriteBuf error:|%s|. fd:|%s|",
+ msg, GetName());
+ gpr_free(msg);
+ if (WSAGetLastError() == WSA_IO_PENDING) {
+ WSASetLastError(WSAEWOULDBLOCK);
+ write_state_ = WRITE_REQUESTED;
+ }
+ }
+ write_buf_ = grpc_slice_sub_no_ref(write_buf_, bytes_sent,
+ GRPC_SLICE_LENGTH(write_buf_));
+ return bytes_sent;
+ }
+
+ ares_ssize_t SendV(const struct iovec* iov, int iov_count) {
+ GRPC_CARES_TRACE_LOG("SendV called on fd:|%s|. Current write state: %d",
+ GetName(), write_state_);
+ switch (write_state_) {
+ case WRITE_IDLE:
+ GPR_ASSERT(GRPC_SLICE_LENGTH(write_buf_) == 0);
+ grpc_slice_unref_internal(write_buf_);
+ write_buf_ = FlattenIovec(iov, iov_count);
+ return TrySendWriteBufSyncNonBlocking();
+ case WRITE_REQUESTED:
+ case WRITE_PENDING:
+ WSASetLastError(WSAEWOULDBLOCK);
+ return -1;
+ case WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY:
+ grpc_slice currently_attempted = FlattenIovec(iov, iov_count);
+ GPR_ASSERT(GRPC_SLICE_LENGTH(currently_attempted) >=
+ GRPC_SLICE_LENGTH(write_buf_));
+ ares_ssize_t total_sent = 0;
+ for (size_t i = 0; i < GRPC_SLICE_LENGTH(write_buf_); i++) {
+ GPR_ASSERT(GRPC_SLICE_START_PTR(currently_attempted)[i] ==
+ GRPC_SLICE_START_PTR(write_buf_)[i]);
+ total_sent++;
+ }
+ grpc_slice_unref_internal(write_buf_);
+ write_buf_ =
+ grpc_slice_sub_no_ref(currently_attempted, total_sent,
+ GRPC_SLICE_LENGTH(currently_attempted));
+ write_state_ = WRITE_IDLE;
+ total_sent += TrySendWriteBufSyncNonBlocking();
+ return total_sent;
+ }
abort();
}
- bool IsFdStillReadableLocked() override { abort(); }
- void ShutdownLocked(grpc_error* error) override { abort(); }
- ares_socket_t GetWrappedAresSocketLocked() override { abort(); }
- const char* GetName() override { abort(); }
+
+ int Connect(const struct sockaddr* target, ares_socklen_t target_len) {
+ SOCKET s = grpc_winsocket_wrapped_socket(winsocket_);
+ GRPC_CARES_TRACE_LOG("Connect: fd:|%s|", GetName());
+ int out =
+ WSAConnect(s, target, target_len, nullptr, nullptr, nullptr, nullptr);
+ if (out != 0) {
+ char* msg = gpr_format_message(WSAGetLastError());
+ GRPC_CARES_TRACE_LOG("Connect error code:|%d|, msg:|%s|. fd:|%s|",
+ WSAGetLastError(), msg, GetName());
+ gpr_free(msg);
+ // c-ares expects a posix-style connect API
+ out = -1;
+ }
+ return out;
+ }
+
+ static void OnIocpReadable(void* arg, grpc_error* error) {
+ GrpcPolledFdWindows* polled_fd = static_cast<GrpcPolledFdWindows*>(arg);
+ polled_fd->OnIocpReadableInner(error);
+ }
+
+ void OnIocpReadableInner(grpc_error* error) {
+ if (error == GRPC_ERROR_NONE) {
+ if (winsocket_->read_info.wsa_error != 0) {
+ /* WSAEMSGSIZE would be due to receiving more data
+ * than our read buffer's fixed capacity. Assume that
+ * the connection is TCP and read the leftovers
+ * in subsequent c-ares reads. */
+ if (winsocket_->read_info.wsa_error != WSAEMSGSIZE) {
+ GRPC_ERROR_UNREF(error);
+ char* msg = gpr_format_message(winsocket_->read_info.wsa_error);
+ GRPC_CARES_TRACE_LOG(
+ "OnIocpReadableInner. winsocket error:|%s|. fd:|%s|", msg,
+ GetName());
+ error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
+ gpr_free(msg);
+ }
+ }
+ }
+ if (error == GRPC_ERROR_NONE) {
+ read_buf_ = grpc_slice_sub_no_ref(read_buf_, 0,
+ winsocket_->read_info.bytes_transfered);
+ } else {
+ grpc_slice_unref_internal(read_buf_);
+ read_buf_ = grpc_empty_slice();
+ }
+ GRPC_CARES_TRACE_LOG(
+ "OnIocpReadable finishing. read buf length now:|%d|. :fd:|%s|",
+ GRPC_SLICE_LENGTH(read_buf_), GetName());
+ ScheduleAndNullReadClosure(error);
+ }
+
+ static void OnIocpWriteable(void* arg, grpc_error* error) {
+ GrpcPolledFdWindows* polled_fd = static_cast<GrpcPolledFdWindows*>(arg);
+ polled_fd->OnIocpWriteableInner(error);
+ }
+
+ void OnIocpWriteableInner(grpc_error* error) {
+ GRPC_CARES_TRACE_LOG("OnIocpWriteableInner. fd:|%s|", GetName());
+ if (error == GRPC_ERROR_NONE) {
+ if (winsocket_->write_info.wsa_error != 0) {
+ char* msg = gpr_format_message(winsocket_->write_info.wsa_error);
+ GRPC_CARES_TRACE_LOG(
+ "OnIocpWriteableInner. winsocket error:|%s|. fd:|%s|", msg,
+ GetName());
+ GRPC_ERROR_UNREF(error);
+ error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
+ gpr_free(msg);
+ }
+ }
+ GPR_ASSERT(write_state_ == WRITE_PENDING);
+ if (error == GRPC_ERROR_NONE) {
+ write_state_ = WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY;
+ write_buf_ = grpc_slice_sub_no_ref(
+ write_buf_, 0, winsocket_->write_info.bytes_transfered);
+ } else {
+ grpc_slice_unref_internal(write_buf_);
+ write_buf_ = grpc_empty_slice();
+ }
+ ScheduleAndNullWriteClosure(error);
+ }
+
+ bool gotten_into_driver_list() const { return gotten_into_driver_list_; }
+ void set_gotten_into_driver_list() { gotten_into_driver_list_ = true; }
+
+ grpc_combiner* combiner_;
+ char recv_from_source_addr_[200];
+ ares_socklen_t recv_from_source_addr_len_;
+ grpc_slice read_buf_;
+ grpc_slice write_buf_;
+ grpc_closure* read_closure_ = nullptr;
+ grpc_closure* write_closure_ = nullptr;
+ grpc_closure outer_read_closure_;
+ grpc_closure outer_write_closure_;
+ grpc_winsocket* winsocket_;
+ WriteState write_state_;
+ char* name_ = nullptr;
+ bool gotten_into_driver_list_;
};
-GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as,
- grpc_pollset_set* driver_pollset_set) {
- return nullptr;
-}
+struct SockToPolledFdEntry {
+ SockToPolledFdEntry(SOCKET s, GrpcPolledFdWindows* fd)
+ : socket(s), polled_fd(fd) {}
+ SOCKET socket;
+ GrpcPolledFdWindows* polled_fd;
+ SockToPolledFdEntry* next = nullptr;
+};
+
+/* A SockToPolledFdMap can make ares_socket_t types (SOCKET's on windows)
+ * to GrpcPolledFdWindow's, and is used to find the appropriate
+ * GrpcPolledFdWindows to handle a virtual socket call when c-ares makes that
+ * socket call on the ares_socket_t type. Instances are owned by and one-to-one
+ * with a GrpcPolledFdWindows factory and event driver */
+class SockToPolledFdMap {
+ public:
+ SockToPolledFdMap(grpc_combiner* combiner) {
+ combiner_ = GRPC_COMBINER_REF(combiner, "sock to polled fd map");
+ }
+
+ ~SockToPolledFdMap() {
+ GPR_ASSERT(head_ == nullptr);
+ GRPC_COMBINER_UNREF(combiner_, "sock to polled fd map");
+ }
+
+ void AddNewSocket(SOCKET s, GrpcPolledFdWindows* polled_fd) {
+ SockToPolledFdEntry* new_node = New<SockToPolledFdEntry>(s, polled_fd);
+ new_node->next = head_;
+ head_ = new_node;
+ }
+
+ GrpcPolledFdWindows* LookupPolledFd(SOCKET s) {
+ for (SockToPolledFdEntry* node = head_; node != nullptr;
+ node = node->next) {
+ if (node->socket == s) {
+ GPR_ASSERT(node->polled_fd != nullptr);
+ return node->polled_fd;
+ }
+ }
+ abort();
+ }
+
+ void RemoveEntry(SOCKET s) {
+ GPR_ASSERT(head_ != nullptr);
+ SockToPolledFdEntry** prev = &head_;
+ for (SockToPolledFdEntry* node = head_; node != nullptr;
+ node = node->next) {
+ if (node->socket == s) {
+ *prev = node->next;
+ Delete(node);
+ return;
+ }
+ prev = &node->next;
+ }
+ abort();
+ }
+
+ /* These virtual socket functions are called from within the c-ares
+ * library. These methods generally dispatch those socket calls to the
+ * appropriate methods. The virtual "socket" and "close" methods are
+ * special and instead create/add and remove/destroy GrpcPolledFdWindows
+ * objects.
+ */
+ static ares_socket_t Socket(int af, int type, int protocol, void* user_data) {
+ SockToPolledFdMap* map = static_cast<SockToPolledFdMap*>(user_data);
+ SOCKET s = WSASocket(af, type, protocol, nullptr, 0, WSA_FLAG_OVERLAPPED);
+ if (s == INVALID_SOCKET) {
+ return s;
+ }
+ grpc_tcp_set_non_block(s);
+ GrpcPolledFdWindows* polled_fd =
+ New<GrpcPolledFdWindows>(s, map->combiner_);
+ map->AddNewSocket(s, polled_fd);
+ return s;
+ }
+
+ static int Connect(ares_socket_t as, const struct sockaddr* target,
+ ares_socklen_t target_len, void* user_data) {
+ SockToPolledFdMap* map = static_cast<SockToPolledFdMap*>(user_data);
+ GrpcPolledFdWindows* polled_fd = map->LookupPolledFd(as);
+ return polled_fd->Connect(target, target_len);
+ }
+
+ static ares_ssize_t SendV(ares_socket_t as, const struct iovec* iov,
+ int iovec_count, void* user_data) {
+ SockToPolledFdMap* map = static_cast<SockToPolledFdMap*>(user_data);
+ GrpcPolledFdWindows* polled_fd = map->LookupPolledFd(as);
+ return polled_fd->SendV(iov, iovec_count);
+ }
+
+ static ares_ssize_t RecvFrom(ares_socket_t as, void* data, size_t data_len,
+ int flags, struct sockaddr* from,
+ ares_socklen_t* from_len, void* user_data) {
+ SockToPolledFdMap* map = static_cast<SockToPolledFdMap*>(user_data);
+ GrpcPolledFdWindows* polled_fd = map->LookupPolledFd(as);
+ return polled_fd->RecvFrom(data, data_len, flags, from, from_len);
+ }
+
+ static int CloseSocket(SOCKET s, void* user_data) {
+ SockToPolledFdMap* map = static_cast<SockToPolledFdMap*>(user_data);
+ GrpcPolledFdWindows* polled_fd = map->LookupPolledFd(s);
+ map->RemoveEntry(s);
+ // If a gRPC polled fd has not made it in to the driver's list yet, then
+ // the driver has not and will never see this socket.
+ if (!polled_fd->gotten_into_driver_list()) {
+ polled_fd->ShutdownLocked(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "Shut down c-ares fd before without it ever having made it into the "
+ "driver's list"));
+ return 0;
+ }
+ return 0;
+ }
+
+ private:
+ SockToPolledFdEntry* head_ = nullptr;
+ grpc_combiner* combiner_;
+};
+
+const struct ares_socket_functions custom_ares_sock_funcs = {
+ &SockToPolledFdMap::Socket /* socket */,
+ &SockToPolledFdMap::CloseSocket /* close */,
+ &SockToPolledFdMap::Connect /* connect */,
+ &SockToPolledFdMap::RecvFrom /* recvfrom */,
+ &SockToPolledFdMap::SendV /* sendv */,
+};
+
+class GrpcPolledFdFactoryWindows : public GrpcPolledFdFactory {
+ public:
+ GrpcPolledFdFactoryWindows(grpc_combiner* combiner)
+ : sock_to_polled_fd_map_(combiner) {}
+
+ GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as,
+ grpc_pollset_set* driver_pollset_set,
+ grpc_combiner* combiner) override {
+ GrpcPolledFdWindows* polled_fd = sock_to_polled_fd_map_.LookupPolledFd(as);
+ // Set a flag so that the virtual socket "close" method knows it
+ // doesn't need to call ShutdownLocked, since now the driver will.
+ polled_fd->set_gotten_into_driver_list();
+ return polled_fd;
+ }
-void ConfigureAresChannelLocked(ares_channel* channel) { abort(); }
+ void ConfigureAresChannelLocked(ares_channel channel) override {
+ ares_set_socket_functions(channel, &custom_ares_sock_funcs,
+ &sock_to_polled_fd_map_);
+ }
+
+ private:
+ SockToPolledFdMap sock_to_polled_fd_map_;
+};
+
+UniquePtr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(grpc_combiner* combiner) {
+ return UniquePtr<GrpcPolledFdFactory>(
+ New<GrpcPolledFdFactoryWindows>(combiner));
+}
} // namespace grpc_core
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
index b3d6437e9a..485998f5e4 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
@@ -49,6 +49,8 @@ static gpr_mu g_init_mu;
grpc_core::TraceFlag grpc_trace_cares_address_sorting(false,
"cares_address_sorting");
+grpc_core::TraceFlag grpc_trace_cares_resolver(false, "cares_resolver");
+
struct grpc_ares_request {
/** indicates the DNS server to use, if specified */
struct ares_addr_port_node dns_server_addr;
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
index 17eaa7ccf0..ca5779e1d7 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
@@ -28,6 +28,13 @@
extern grpc_core::TraceFlag grpc_trace_cares_address_sorting;
+extern grpc_core::TraceFlag grpc_trace_cares_resolver;
+
+#define GRPC_CARES_TRACE_LOG(format, ...) \
+ if (grpc_trace_cares_resolver.enabled()) { \
+ gpr_log(GPR_DEBUG, "(c-ares resolver) " format, __VA_ARGS__); \
+ }
+
typedef struct grpc_ares_request grpc_ares_request;
/* Asynchronously resolve \a name. Use \a default_port if a port isn't
diff --git a/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc b/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
index fae4c33a17..282caf215c 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
+++ b/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
@@ -58,6 +58,8 @@ class NativeDnsResolver : public Resolver {
void RequestReresolutionLocked() override;
+ void ResetBackoffLocked() override;
+
void ShutdownLocked() override;
private:
@@ -158,6 +160,13 @@ void NativeDnsResolver::RequestReresolutionLocked() {
}
}
+void NativeDnsResolver::ResetBackoffLocked() {
+ if (have_next_resolution_timer_) {
+ grpc_timer_cancel(&next_resolution_timer_);
+ }
+ backoff_.Reset();
+}
+
void NativeDnsResolver::ShutdownLocked() {
if (have_next_resolution_timer_) {
grpc_timer_cancel(&next_resolution_timer_);
diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc
index 71ef8c518b..48c6030c89 100644
--- a/src/core/ext/filters/client_channel/subchannel.cc
+++ b/src/core/ext/filters/client_channel/subchannel.cc
@@ -132,6 +132,8 @@ struct grpc_subchannel {
bool have_alarm;
/** have we started the backoff loop */
bool backoff_begun;
+ // reset_backoff() was called while alarm was pending
+ bool deferred_reset_backoff;
/** our alarm */
grpc_timer alarm;
@@ -438,6 +440,9 @@ static void on_alarm(void* arg, grpc_error* error) {
if (c->disconnected) {
error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected",
&error, 1);
+ } else if (c->deferred_reset_backoff) {
+ c->deferred_reset_backoff = false;
+ error = GRPC_ERROR_NONE;
} else {
GRPC_ERROR_REF(error);
}
@@ -675,6 +680,19 @@ static void on_subchannel_connected(void* arg, grpc_error* error) {
grpc_channel_args_destroy(delete_channel_args);
}
+void grpc_subchannel_reset_backoff(grpc_subchannel* subchannel) {
+ gpr_mu_lock(&subchannel->mu);
+ if (subchannel->have_alarm) {
+ subchannel->deferred_reset_backoff = true;
+ grpc_timer_cancel(&subchannel->alarm);
+ } else {
+ subchannel->backoff_begun = false;
+ subchannel->backoff->Reset();
+ maybe_start_connecting_locked(subchannel);
+ }
+ gpr_mu_unlock(&subchannel->mu);
+}
+
/*
* grpc_subchannel_call implementation
*/
diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h
index 9e53f7d542..a135035d62 100644
--- a/src/core/ext/filters/client_channel/subchannel.h
+++ b/src/core/ext/filters/client_channel/subchannel.h
@@ -145,6 +145,13 @@ grpc_subchannel_get_connected_subchannel(grpc_subchannel* c);
const grpc_subchannel_key* grpc_subchannel_get_key(
const grpc_subchannel* subchannel);
+// Resets the connection backoff of the subchannel.
+// TODO(roth): Move connection backoff out of subchannels and up into LB
+// policy code (probably by adding a SubchannelGroup between
+// SubchannelList and SubchannelData), at which point this method can
+// go away.
+void grpc_subchannel_reset_backoff(grpc_subchannel* subchannel);
+
/** continue processing a transport op */
void grpc_subchannel_call_process_op(grpc_subchannel_call* subchannel_call,
grpc_transport_stream_op_batch* op);
diff --git a/src/core/ext/filters/deadline/deadline_filter.cc b/src/core/ext/filters/deadline/deadline_filter.cc
index d23ad67ad5..3bd3059312 100644
--- a/src/core/ext/filters/deadline/deadline_filter.cc
+++ b/src/core/ext/filters/deadline/deadline_filter.cc
@@ -379,10 +379,10 @@ static bool maybe_add_deadline_filter(grpc_channel_stack_builder* builder,
void grpc_deadline_filter_init(void) {
grpc_channel_init_register_stage(
- GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+ GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_VERY_HIGH,
maybe_add_deadline_filter, (void*)&grpc_client_deadline_filter);
grpc_channel_init_register_stage(
- GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+ GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_VERY_HIGH,
maybe_add_deadline_filter, (void*)&grpc_server_deadline_filter);
}
diff --git a/src/core/ext/filters/http/client_authority_filter.cc b/src/core/ext/filters/http/client_authority_filter.cc
index ddc939ed12..3c0ae47e8d 100644
--- a/src/core/ext/filters/http/client_authority_filter.cc
+++ b/src/core/ext/filters/http/client_authority_filter.cc
@@ -146,12 +146,12 @@ static bool add_client_authority_filter(grpc_channel_stack_builder* builder,
}
void grpc_client_authority_filter_init(void) {
- grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX,
- add_client_authority_filter,
- (void*)&grpc_client_authority_filter);
- grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX,
- add_client_authority_filter,
- (void*)&grpc_client_authority_filter);
+ grpc_channel_init_register_stage(
+ GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_PRIORITY_HIGH,
+ add_client_authority_filter, (void*)&grpc_client_authority_filter);
+ grpc_channel_init_register_stage(
+ GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_HIGH,
+ add_client_authority_filter, (void*)&grpc_client_authority_filter);
}
void grpc_client_authority_filter_shutdown(void) {}
diff --git a/src/core/ext/filters/http/http_filters_plugin.cc b/src/core/ext/filters/http/http_filters_plugin.cc
index f03fa0141d..38757710f3 100644
--- a/src/core/ext/filters/http/http_filters_plugin.cc
+++ b/src/core/ext/filters/http/http_filters_plugin.cc
@@ -18,6 +18,7 @@
#include <grpc/support/port_platform.h>
+#include <limits.h>
#include <string.h>
#include "src/core/ext/filters/http/client/http_client_filter.h"
@@ -51,15 +52,15 @@ static bool maybe_add_optional_filter(grpc_channel_stack_builder* builder,
bool enable = grpc_channel_arg_get_bool(
grpc_channel_args_find(channel_args, filtarg->control_channel_arg),
!grpc_channel_args_want_minimal_stack(channel_args));
- return enable ? grpc_channel_stack_builder_prepend_filter(
+ return enable ? grpc_channel_stack_builder_append_filter(
builder, filtarg->filter, nullptr, nullptr)
: true;
}
-static bool maybe_add_required_filter(grpc_channel_stack_builder* builder,
- void* arg) {
+static bool maybe_append_required_filter(grpc_channel_stack_builder* builder,
+ void* arg) {
return is_building_http_like_transport(builder)
- ? grpc_channel_stack_builder_prepend_filter(
+ ? grpc_channel_stack_builder_append_filter(
builder, static_cast<const grpc_channel_filter*>(arg),
nullptr, nullptr)
: true;
@@ -67,23 +68,23 @@ static bool maybe_add_required_filter(grpc_channel_stack_builder* builder,
void grpc_http_filters_init(void) {
grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL,
- GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+ GRPC_CHANNEL_INIT_PRIORITY_HIGH,
maybe_add_optional_filter, &compress_filter);
grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL,
- GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+ GRPC_CHANNEL_INIT_PRIORITY_HIGH,
maybe_add_optional_filter, &compress_filter);
grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL,
- GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+ GRPC_CHANNEL_INIT_PRIORITY_HIGH,
maybe_add_optional_filter, &compress_filter);
grpc_channel_init_register_stage(
- GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
- maybe_add_required_filter, (void*)&grpc_http_client_filter);
+ GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_PRIORITY_HIGH,
+ maybe_append_required_filter, (void*)&grpc_http_client_filter);
grpc_channel_init_register_stage(
- GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
- maybe_add_required_filter, (void*)&grpc_http_client_filter);
+ GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_HIGH,
+ maybe_append_required_filter, (void*)&grpc_http_client_filter);
grpc_channel_init_register_stage(
- GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
- maybe_add_required_filter, (void*)&grpc_http_server_filter);
+ GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_HIGH,
+ maybe_append_required_filter, (void*)&grpc_http_server_filter);
}
void grpc_http_filters_shutdown(void) {}
diff --git a/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc b/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
index 6529046a5e..0c4ffea27b 100644
--- a/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
+++ b/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
@@ -345,7 +345,8 @@ struct ServerLoadReportingFilterStaticRegistrar {
if (registered) return;
RegisterChannelFilter<ServerLoadReportingChannelData,
ServerLoadReportingCallData>(
- "server_load_reporting", GRPC_SERVER_CHANNEL, INT_MAX,
+ "server_load_reporting", GRPC_SERVER_CHANNEL,
+ GRPC_CHANNEL_INIT_PRIORITY_LOW, true,
MaybeAddServerLoadReportingFilter);
// Access measures to ensure they are initialized. Otherwise, we can't
// create any valid view before the first RPC.
diff --git a/src/core/ext/filters/max_age/max_age_filter.cc b/src/core/ext/filters/max_age/max_age_filter.cc
index 1fe8288bd0..7db30d5b48 100644
--- a/src/core/ext/filters/max_age/max_age_filter.cc
+++ b/src/core/ext/filters/max_age/max_age_filter.cc
@@ -536,7 +536,7 @@ static bool maybe_add_max_age_filter(grpc_channel_stack_builder* builder,
void grpc_max_age_filter_init(void) {
grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL,
- GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+ GRPC_CHANNEL_INIT_PRIORITY_LOW,
maybe_add_max_age_filter, nullptr);
}
diff --git a/src/core/ext/filters/message_size/message_size_filter.cc b/src/core/ext/filters/message_size/message_size_filter.cc
index c7fc3f2e62..1bd9cf1426 100644
--- a/src/core/ext/filters/message_size/message_size_filter.cc
+++ b/src/core/ext/filters/message_size/message_size_filter.cc
@@ -311,13 +311,13 @@ static bool maybe_add_message_size_filter(grpc_channel_stack_builder* builder,
void grpc_message_size_filter_init(void) {
grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL,
- GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+ GRPC_CHANNEL_INIT_PRIORITY_LOW,
maybe_add_message_size_filter, nullptr);
grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL,
- GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+ GRPC_CHANNEL_INIT_PRIORITY_LOW,
maybe_add_message_size_filter, nullptr);
grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL,
- GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+ GRPC_CHANNEL_INIT_PRIORITY_LOW,
maybe_add_message_size_filter, nullptr);
}
diff --git a/src/core/lib/channel/connected_channel.cc b/src/core/lib/channel/connected_channel.cc
index e2ea334ded..c78849a29b 100644
--- a/src/core/lib/channel/connected_channel.cc
+++ b/src/core/lib/channel/connected_channel.cc
@@ -228,8 +228,8 @@ static void bind_transport(grpc_channel_stack* channel_stack,
grpc_transport_stream_size(static_cast<grpc_transport*>(t));
}
-bool grpc_add_connected_filter(grpc_channel_stack_builder* builder,
- void* arg_must_be_null) {
+bool grpc_append_connected_filter(grpc_channel_stack_builder* builder,
+ void* arg_must_be_null) {
GPR_ASSERT(arg_must_be_null == nullptr);
grpc_transport* t = grpc_channel_stack_builder_get_transport(builder);
GPR_ASSERT(t != nullptr);
diff --git a/src/core/lib/channel/connected_channel.h b/src/core/lib/channel/connected_channel.h
index faa1c73a21..280daf040d 100644
--- a/src/core/lib/channel/connected_channel.h
+++ b/src/core/lib/channel/connected_channel.h
@@ -25,8 +25,8 @@
extern const grpc_channel_filter grpc_connected_filter;
-bool grpc_add_connected_filter(grpc_channel_stack_builder* builder,
- void* arg_must_be_null);
+bool grpc_append_connected_filter(grpc_channel_stack_builder* builder,
+ void* arg_must_be_null);
/* Debug helper to dig the transport stream out of a call element */
grpc_stream* grpc_connected_channel_get_stream(grpc_call_element* elem);
diff --git a/src/core/lib/iomgr/iocp_windows.cc b/src/core/lib/iomgr/iocp_windows.cc
index ce77231036..ad325fe215 100644
--- a/src/core/lib/iomgr/iocp_windows.cc
+++ b/src/core/lib/iomgr/iocp_windows.cc
@@ -89,10 +89,15 @@ grpc_iocp_work_status grpc_iocp_work(grpc_millis deadline) {
} else {
abort();
}
- success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes,
- FALSE, &flags);
- info->bytes_transfered = bytes;
- info->wsa_error = success ? 0 : WSAGetLastError();
+ if (socket->shutdown_called) {
+ info->bytes_transfered = 0;
+ info->wsa_error = WSA_OPERATION_ABORTED;
+ } else {
+ success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes,
+ FALSE, &flags);
+ info->bytes_transfered = bytes;
+ info->wsa_error = success ? 0 : WSAGetLastError();
+ }
GPR_ASSERT(overlapped == &info->overlapped);
grpc_socket_become_ready(socket, info);
return GRPC_IOCP_WORK_WORK;
diff --git a/src/core/lib/iomgr/socket_windows.cc b/src/core/lib/iomgr/socket_windows.cc
index 4ad31cb35d..999c6646ad 100644
--- a/src/core/lib/iomgr/socket_windows.cc
+++ b/src/core/lib/iomgr/socket_windows.cc
@@ -52,6 +52,10 @@ grpc_winsocket* grpc_winsocket_create(SOCKET socket, const char* name) {
return r;
}
+SOCKET grpc_winsocket_wrapped_socket(grpc_winsocket* socket) {
+ return socket->socket;
+}
+
/* Schedule a shutdown of the socket operations. Will call the pending
operations to abort them. We need to do that this way because of the
various callsites of that function, which happens to be in various
diff --git a/src/core/lib/iomgr/socket_windows.h b/src/core/lib/iomgr/socket_windows.h
index b09b9da562..46d7d58356 100644
--- a/src/core/lib/iomgr/socket_windows.h
+++ b/src/core/lib/iomgr/socket_windows.h
@@ -92,6 +92,8 @@ typedef struct grpc_winsocket {
it will be responsible for closing it. */
grpc_winsocket* grpc_winsocket_create(SOCKET socket, const char* name);
+SOCKET grpc_winsocket_wrapped_socket(grpc_winsocket* socket);
+
/* Initiate an asynchronous shutdown of the socket. Will call off any pending
operation to cancel them. */
void grpc_winsocket_shutdown(grpc_winsocket* socket);
diff --git a/src/core/lib/iomgr/tcp_windows.cc b/src/core/lib/iomgr/tcp_windows.cc
index 5d316d477b..b3cb442f18 100644
--- a/src/core/lib/iomgr/tcp_windows.cc
+++ b/src/core/lib/iomgr/tcp_windows.cc
@@ -53,7 +53,7 @@
extern grpc_core::TraceFlag grpc_tcp_trace;
-static grpc_error* set_non_block(SOCKET sock) {
+grpc_error* grpc_tcp_set_non_block(SOCKET sock) {
int status;
uint32_t param = 1;
DWORD ret;
@@ -90,7 +90,7 @@ static grpc_error* enable_loopback_fast_path(SOCKET sock) {
grpc_error* grpc_tcp_prepare_socket(SOCKET sock) {
grpc_error* err;
- err = set_non_block(sock);
+ err = grpc_tcp_set_non_block(sock);
if (err != GRPC_ERROR_NONE) return err;
err = set_dualstack(sock);
if (err != GRPC_ERROR_NONE) return err;
diff --git a/src/core/lib/iomgr/tcp_windows.h b/src/core/lib/iomgr/tcp_windows.h
index 161a545a2a..04ef8102b6 100644
--- a/src/core/lib/iomgr/tcp_windows.h
+++ b/src/core/lib/iomgr/tcp_windows.h
@@ -46,6 +46,8 @@ grpc_endpoint* grpc_tcp_create(grpc_winsocket* socket,
grpc_error* grpc_tcp_prepare_socket(SOCKET sock);
+grpc_error* grpc_tcp_set_non_block(SOCKET sock);
+
#endif
#endif /* GRPC_CORE_LIB_IOMGR_TCP_WINDOWS_H */
diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc
index 7cbd61adef..82635d3c21 100644
--- a/src/core/lib/surface/channel.cc
+++ b/src/core/lib/surface/channel.cc
@@ -281,6 +281,17 @@ void grpc_channel_get_info(grpc_channel* channel,
elem->filter->get_channel_info(elem, channel_info);
}
+void grpc_channel_reset_connect_backoff(grpc_channel* channel) {
+ grpc_core::ExecCtx exec_ctx;
+ GRPC_API_TRACE("grpc_channel_reset_connect_backoff(channel=%p)", 1,
+ (channel));
+ grpc_transport_op* op = grpc_make_transport_op(nullptr);
+ op->reset_connect_backoff = true;
+ grpc_channel_element* elem =
+ grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0);
+ elem->filter->start_transport_op(elem, op);
+}
+
static grpc_call* grpc_channel_create_call_internal(
grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask,
grpc_completion_queue* cq, grpc_pollset_set* pollset_set_alternative,
diff --git a/src/core/lib/surface/channel_init.h b/src/core/lib/surface/channel_init.h
index f01852473b..6543796b4c 100644
--- a/src/core/lib/surface/channel_init.h
+++ b/src/core/lib/surface/channel_init.h
@@ -21,11 +21,37 @@
#include <grpc/support/port_platform.h>
+#include <limits.h>
+
#include "src/core/lib/channel/channel_stack_builder.h"
#include "src/core/lib/surface/channel_stack_type.h"
#include "src/core/lib/transport/transport.h"
-#define GRPC_CHANNEL_INIT_BUILTIN_PRIORITY 10000
+// Priority for channel registration functions to be used in
+// grpc_channel_init_register_stage(). The priority dictates the
+// order in which the registration functions run.
+//
+// When used to register a filter, the filter can either be appended or
+// prepended, thus dictating whether the filter goes at the top or bottom of
+// the stack. Higher priority functions can get closer to the top or bottom
+// of the stack than lower priority functions.
+enum {
+ // Default level. Most of filters should use this level if their location in
+ // the stack does not matter.
+ GRPC_CHANNEL_INIT_PRIORITY_LOW = 0,
+ // For filters that should be added after the group of filters with default
+ // priority, such as auth filters.
+ GRPC_CHANNEL_INIT_PRIORITY_MED = 10000,
+ // For filters that need to be close to top or bottom, such as protocol-level
+ // filters (client_authority, http-client, http-server).
+ GRPC_CHANNEL_INIT_PRIORITY_HIGH = 20000,
+ // For filters that need to be very close to the wire or surface, such as
+ // stats filters (census).
+ GRPC_CHANNEL_INIT_PRIORITY_VERY_HIGH = 30000,
+ // For things that have to happen last, such as connected channel filter or
+ // surface server filter. Consider as reserved for gRPC internals.
+ GRPC_CHANNEL_INIT_PRIORITY_MAX = INT_MAX
+};
/// This module provides a way for plugins (and the grpc core library itself)
/// to register mutators for channel stacks.
diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc
index 0ad82fed99..7807b261d4 100644
--- a/src/core/lib/surface/init.cc
+++ b/src/core/lib/surface/init.cc
@@ -70,11 +70,6 @@ static void do_basic_init(void) {
g_initializations = 0;
}
-static bool append_filter(grpc_channel_stack_builder* builder, void* arg) {
- return grpc_channel_stack_builder_append_filter(
- builder, static_cast<const grpc_channel_filter*>(arg), nullptr, nullptr);
-}
-
static bool prepend_filter(grpc_channel_stack_builder* builder, void* arg) {
return grpc_channel_stack_builder_prepend_filter(
builder, static_cast<const grpc_channel_filter*>(arg), nullptr, nullptr);
@@ -82,19 +77,20 @@ static bool prepend_filter(grpc_channel_stack_builder* builder, void* arg) {
static void register_builtin_channel_init() {
grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL,
- GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
- grpc_add_connected_filter, nullptr);
+ GRPC_CHANNEL_INIT_PRIORITY_MAX,
+ grpc_append_connected_filter, nullptr);
grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL,
- GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
- grpc_add_connected_filter, nullptr);
+ GRPC_CHANNEL_INIT_PRIORITY_MAX,
+ grpc_append_connected_filter, nullptr);
grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL,
- GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
- grpc_add_connected_filter, nullptr);
+ GRPC_CHANNEL_INIT_PRIORITY_MAX,
+ grpc_append_connected_filter, nullptr);
grpc_channel_init_register_stage(GRPC_CLIENT_LAME_CHANNEL,
- GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
- append_filter, (void*)&grpc_lame_filter);
- grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, prepend_filter,
- (void*)&grpc_server_top_filter);
+ GRPC_CHANNEL_INIT_PRIORITY_MAX,
+ prepend_filter, (void*)&grpc_lame_filter);
+ grpc_channel_init_register_stage(
+ GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_MAX, prepend_filter,
+ (void*)&grpc_server_top_filter);
}
typedef struct grpc_plugin {
diff --git a/src/core/lib/surface/init_secure.cc b/src/core/lib/surface/init_secure.cc
index 28c6f7b121..8058aaa804 100644
--- a/src/core/lib/surface/init_secure.cc
+++ b/src/core/lib/surface/init_secure.cc
@@ -67,14 +67,17 @@ static bool maybe_prepend_server_auth_filter(
}
void grpc_register_security_filters(void) {
- // Register the auth client with a priority < INT_MAX to allow the authority
+ // Register the auth client with a medium priority to allow the authority
// filter -on which the auth filter depends- to be higher on the channel
// stack.
- grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX - 1,
+ grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL,
+ GRPC_CHANNEL_INIT_PRIORITY_MED,
maybe_prepend_client_auth_filter, nullptr);
- grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX - 1,
+ grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL,
+ GRPC_CHANNEL_INIT_PRIORITY_MED,
maybe_prepend_client_auth_filter, nullptr);
- grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
+ grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL,
+ GRPC_CHANNEL_INIT_PRIORITY_MED,
maybe_prepend_server_auth_filter, nullptr);
}
diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h
index 585b9dfae9..9e784635c6 100644
--- a/src/core/lib/transport/transport.h
+++ b/src/core/lib/transport/transport.h
@@ -282,6 +282,8 @@ typedef struct grpc_transport_op {
/** Called when the ping ack is received */
grpc_closure* on_ack;
} send_ping;
+ // If true, will reset the channel's connection backoff.
+ bool reset_connect_backoff;
/***************************************************************************
* remaining fields are initialized and used at the discretion of the
diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc
index 867f31f025..39b891c2e1 100644
--- a/src/cpp/client/channel_cc.cc
+++ b/src/cpp/client/channel_cc.cc
@@ -84,6 +84,14 @@ grpc::string Channel::GetServiceConfigJSON() const {
&channel_info.service_config_json);
}
+namespace experimental {
+
+void ChannelResetConnectionBackoff(Channel* channel) {
+ grpc_channel_reset_connect_backoff(channel->c_channel_);
+}
+
+} // namespace experimental
+
internal::Call Channel::CreateCall(const internal::RpcMethod& method,
ClientContext* context,
CompletionQueue* cq) {
diff --git a/src/cpp/common/channel_filter.cc b/src/cpp/common/channel_filter.cc
index 422e7bb65e..0634b0416f 100644
--- a/src/cpp/common/channel_filter.cc
+++ b/src/cpp/common/channel_filter.cc
@@ -78,8 +78,13 @@ bool MaybeAddFilter(grpc_channel_stack_builder* builder, void* arg) {
grpc_channel_stack_builder_get_channel_arguments(builder);
if (!filter.include_filter(*args)) return true;
}
- return grpc_channel_stack_builder_prepend_filter(builder, &filter.filter,
- nullptr, nullptr);
+ if (filter.prepend) {
+ return grpc_channel_stack_builder_prepend_filter(builder, &filter.filter,
+ nullptr, nullptr);
+ } else {
+ return grpc_channel_stack_builder_append_filter(builder, &filter.filter,
+ nullptr, nullptr);
+ }
}
} // namespace
diff --git a/src/cpp/common/channel_filter.h b/src/cpp/common/channel_filter.h
index 5e569c97e6..359c72737c 100644
--- a/src/cpp/common/channel_filter.h
+++ b/src/cpp/common/channel_filter.h
@@ -36,7 +36,8 @@
/// \c ChannelData. Then register the filter using something like this:
/// \code{.cpp}
/// RegisterChannelFilter<MyChannelDataSubclass, MyCallDataSubclass>(
-/// "name-of-filter", GRPC_SERVER_CHANNEL, INT_MAX, nullptr);
+/// "name-of-filter", GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_PRIORITY_LOW,
+/// true, nullptr);
/// \endcode
namespace grpc {
@@ -351,6 +352,7 @@ class ChannelFilter final {
struct FilterRecord {
grpc_channel_stack_type stack_type;
int priority;
+ bool prepend;
std::function<bool(const grpc_channel_args&)> include_filter;
grpc_channel_filter filter;
};
@@ -363,12 +365,14 @@ void ChannelFilterPluginShutdown();
/// Registers a new filter.
/// Must be called by only one thread at a time.
+/// The \a prepend argument decides whether to prepend or append the filter.
/// The \a include_filter argument specifies a function that will be called
/// to determine at run-time whether or not to add the filter. If the
/// value is nullptr, the filter will be added unconditionally.
template <typename ChannelDataType, typename CallDataType>
void RegisterChannelFilter(
const char* name, grpc_channel_stack_type stack_type, int priority,
+ bool prepend,
std::function<bool(const grpc_channel_args&)> include_filter) {
// If we haven't been called before, initialize channel_filters and
// call grpc_register_plugin().
@@ -383,6 +387,7 @@ void RegisterChannelFilter(
internal::FilterRecord filter_record = {
stack_type,
priority,
+ prepend,
include_filter,
{FilterType::StartTransportStreamOpBatch, FilterType::StartTransportOp,
FilterType::call_data_size, FilterType::InitCallElement,
diff --git a/src/cpp/ext/filters/census/grpc_plugin.cc b/src/cpp/ext/filters/census/grpc_plugin.cc
index f978ed3bf5..f79e0e0e96 100644
--- a/src/cpp/ext/filters/census/grpc_plugin.cc
+++ b/src/cpp/ext/filters/census/grpc_plugin.cc
@@ -32,10 +32,12 @@ namespace grpc {
void RegisterOpenCensusPlugin() {
RegisterChannelFilter<CensusChannelData, CensusClientCallData>(
- "opencensus_client", GRPC_CLIENT_CHANNEL, INT_MAX /* priority */,
+ "opencensus_client", GRPC_CLIENT_CHANNEL,
+ GRPC_CHANNEL_INIT_PRIORITY_VERY_HIGH, true /* prepend */,
nullptr /* condition function */);
RegisterChannelFilter<CensusChannelData, CensusServerCallData>(
- "opencensus_server", GRPC_SERVER_CHANNEL, INT_MAX /* priority */,
+ "opencensus_server", GRPC_SERVER_CHANNEL,
+ GRPC_CHANNEL_INIT_PRIORITY_VERY_HIGH, true /* prepend */,
nullptr /* condition function */);
// Access measures to ensure they are initialized. Otherwise, creating a view
diff --git a/src/cpp/server/load_reporter/util.cc b/src/cpp/server/load_reporter/util.cc
index a2f2f11e70..89bdf57049 100644
--- a/src/cpp/server/load_reporter/util.cc
+++ b/src/cpp/server/load_reporter/util.cc
@@ -20,6 +20,8 @@
#include <grpcpp/ext/server_load_reporting.h>
+#include <cmath>
+
#include <grpc/support/log.h>
namespace grpc {
diff --git a/src/csharp/Grpc.Core/Version.csproj.include b/src/csharp/Grpc.Core/Version.csproj.include
index 1a746acdd4..6b0731eb40 100755
--- a/src/csharp/Grpc.Core/Version.csproj.include
+++ b/src/csharp/Grpc.Core/Version.csproj.include
@@ -2,6 +2,6 @@
<Project>
<PropertyGroup>
<GrpcCsharpVersion>1.15.0-dev</GrpcCsharpVersion>
- <GoogleProtobufVersion>3.5.1</GoogleProtobufVersion>
+ <GoogleProtobufVersion>3.6.0</GoogleProtobufVersion>
</PropertyGroup>
</Project>
diff --git a/src/csharp/Grpc.IntegrationTesting/Control.cs b/src/csharp/Grpc.IntegrationTesting/Control.cs
index f3284a5390..6e00348451 100644
--- a/src/csharp/Grpc.IntegrationTesting/Control.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Control.cs
@@ -1039,14 +1039,14 @@ namespace Grpc.Testing {
public ClientConfig(ClientConfig other) : this() {
serverTargets_ = other.serverTargets_.Clone();
clientType_ = other.clientType_;
- SecurityParams = other.securityParams_ != null ? other.SecurityParams.Clone() : null;
+ securityParams_ = other.securityParams_ != null ? other.securityParams_.Clone() : null;
outstandingRpcsPerChannel_ = other.outstandingRpcsPerChannel_;
clientChannels_ = other.clientChannels_;
asyncClientThreads_ = other.asyncClientThreads_;
rpcType_ = other.rpcType_;
- LoadParams = other.loadParams_ != null ? other.LoadParams.Clone() : null;
- PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null;
- HistogramParams = other.histogramParams_ != null ? other.HistogramParams.Clone() : null;
+ loadParams_ = other.loadParams_ != null ? other.loadParams_.Clone() : null;
+ payloadConfig_ = other.payloadConfig_ != null ? other.payloadConfig_.Clone() : null;
+ histogramParams_ = other.histogramParams_ != null ? other.histogramParams_.Clone() : null;
coreList_ = other.coreList_.Clone();
coreLimit_ = other.coreLimit_;
otherClientApi_ = other.otherClientApi_;
@@ -1647,7 +1647,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ClientStatus(ClientStatus other) : this() {
- Stats = other.stats_ != null ? other.Stats.Clone() : null;
+ stats_ = other.stats_ != null ? other.stats_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@@ -2122,11 +2122,11 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ServerConfig(ServerConfig other) : this() {
serverType_ = other.serverType_;
- SecurityParams = other.securityParams_ != null ? other.SecurityParams.Clone() : null;
+ securityParams_ = other.securityParams_ != null ? other.securityParams_.Clone() : null;
port_ = other.port_;
asyncServerThreads_ = other.asyncServerThreads_;
coreLimit_ = other.coreLimit_;
- PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null;
+ payloadConfig_ = other.payloadConfig_ != null ? other.payloadConfig_.Clone() : null;
coreList_ = other.coreList_.Clone();
otherServerApi_ = other.otherServerApi_;
threadsPerCq_ = other.threadsPerCq_;
@@ -2758,7 +2758,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ServerStatus(ServerStatus other) : this() {
- Stats = other.stats_ != null ? other.Stats.Clone() : null;
+ stats_ = other.stats_ != null ? other.stats_.Clone() : null;
port_ = other.port_;
cores_ = other.cores_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@@ -3293,9 +3293,9 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Scenario(Scenario other) : this() {
name_ = other.name_;
- ClientConfig = other.clientConfig_ != null ? other.ClientConfig.Clone() : null;
+ clientConfig_ = other.clientConfig_ != null ? other.clientConfig_.Clone() : null;
numClients_ = other.numClients_;
- ServerConfig = other.serverConfig_ != null ? other.ServerConfig.Clone() : null;
+ serverConfig_ = other.serverConfig_ != null ? other.serverConfig_.Clone() : null;
numServers_ = other.numServers_;
warmupSeconds_ = other.warmupSeconds_;
benchmarkSeconds_ = other.benchmarkSeconds_;
@@ -4422,12 +4422,12 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ScenarioResult(ScenarioResult other) : this() {
- Scenario = other.scenario_ != null ? other.Scenario.Clone() : null;
- Latencies = other.latencies_ != null ? other.Latencies.Clone() : null;
+ scenario_ = other.scenario_ != null ? other.scenario_.Clone() : null;
+ latencies_ = other.latencies_ != null ? other.latencies_.Clone() : null;
clientStats_ = other.clientStats_.Clone();
serverStats_ = other.serverStats_.Clone();
serverCores_ = other.serverCores_.Clone();
- Summary = other.summary_ != null ? other.Summary.Clone() : null;
+ summary_ = other.summary_ != null ? other.summary_.Clone() : null;
clientSuccess_ = other.clientSuccess_.Clone();
serverSuccess_ = other.serverSuccess_.Clone();
requestResults_ = other.requestResults_.Clone();
diff --git a/src/csharp/Grpc.IntegrationTesting/EchoMessages.cs b/src/csharp/Grpc.IntegrationTesting/EchoMessages.cs
index 39c3d76ce8..80a1007e9a 100644
--- a/src/csharp/Grpc.IntegrationTesting/EchoMessages.cs
+++ b/src/csharp/Grpc.IntegrationTesting/EchoMessages.cs
@@ -28,7 +28,7 @@ namespace Grpc.Testing {
"DGdycGMudGVzdGluZyIyCglEZWJ1Z0luZm8SFQoNc3RhY2tfZW50cmllcxgB",
"IAMoCRIOCgZkZXRhaWwYAiABKAkiUAoLRXJyb3JTdGF0dXMSDAoEY29kZRgB",
"IAEoBRIVCg1lcnJvcl9tZXNzYWdlGAIgASgJEhwKFGJpbmFyeV9lcnJvcl9k",
- "ZXRhaWxzGAMgASgJIuIDCg1SZXF1ZXN0UGFyYW1zEhUKDWVjaG9fZGVhZGxp",
+ "ZXRhaWxzGAMgASgJIv8DCg1SZXF1ZXN0UGFyYW1zEhUKDWVjaG9fZGVhZGxp",
"bmUYASABKAgSHgoWY2xpZW50X2NhbmNlbF9hZnRlcl91cxgCIAEoBRIeChZz",
"ZXJ2ZXJfY2FuY2VsX2FmdGVyX3VzGAMgASgFEhUKDWVjaG9fbWV0YWRhdGEY",
"BCABKAgSGgoSY2hlY2tfYXV0aF9jb250ZXh0GAUgASgIEh8KF3Jlc3BvbnNl",
@@ -39,18 +39,18 @@ namespace Grpc.Testing {
"Zy5EZWJ1Z0luZm8SEgoKc2VydmVyX2RpZRgMIAEoCBIcChRiaW5hcnlfZXJy",
"b3JfZGV0YWlscxgNIAEoCRIxCg5leHBlY3RlZF9lcnJvchgOIAEoCzIZLmdy",
"cGMudGVzdGluZy5FcnJvclN0YXR1cxIXCg9zZXJ2ZXJfc2xlZXBfdXMYDyAB",
- "KAUiSgoLRWNob1JlcXVlc3QSDwoHbWVzc2FnZRgBIAEoCRIqCgVwYXJhbRgC",
- "IAEoCzIbLmdycGMudGVzdGluZy5SZXF1ZXN0UGFyYW1zIkYKDlJlc3BvbnNl",
- "UGFyYW1zEhgKEHJlcXVlc3RfZGVhZGxpbmUYASABKAMSDAoEaG9zdBgCIAEo",
- "CRIMCgRwZWVyGAMgASgJIkwKDEVjaG9SZXNwb25zZRIPCgdtZXNzYWdlGAEg",
- "ASgJEisKBXBhcmFtGAIgASgLMhwuZ3JwYy50ZXN0aW5nLlJlc3BvbnNlUGFy",
- "YW1zYgZwcm90bzM="));
+ "KAUSGwoTYmFja2VuZF9jaGFubmVsX2lkeBgQIAEoBSJKCgtFY2hvUmVxdWVz",
+ "dBIPCgdtZXNzYWdlGAEgASgJEioKBXBhcmFtGAIgASgLMhsuZ3JwYy50ZXN0",
+ "aW5nLlJlcXVlc3RQYXJhbXMiRgoOUmVzcG9uc2VQYXJhbXMSGAoQcmVxdWVz",
+ "dF9kZWFkbGluZRgBIAEoAxIMCgRob3N0GAIgASgJEgwKBHBlZXIYAyABKAki",
+ "TAoMRWNob1Jlc3BvbnNlEg8KB21lc3NhZ2UYASABKAkSKwoFcGFyYW0YAiAB",
+ "KAsyHC5ncnBjLnRlc3RpbmcuUmVzcG9uc2VQYXJhbXNiBnByb3RvMw=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.DebugInfo), global::Grpc.Testing.DebugInfo.Parser, new[]{ "StackEntries", "Detail" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ErrorStatus), global::Grpc.Testing.ErrorStatus.Parser, new[]{ "Code", "ErrorMessage", "BinaryErrorDetails" }, null, null, null),
- new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.RequestParams), global::Grpc.Testing.RequestParams.Parser, new[]{ "EchoDeadline", "ClientCancelAfterUs", "ServerCancelAfterUs", "EchoMetadata", "CheckAuthContext", "ResponseMessageLength", "EchoPeer", "ExpectedClientIdentity", "SkipCancelledCheck", "ExpectedTransportSecurityType", "DebugInfo", "ServerDie", "BinaryErrorDetails", "ExpectedError", "ServerSleepUs" }, null, null, null),
+ new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.RequestParams), global::Grpc.Testing.RequestParams.Parser, new[]{ "EchoDeadline", "ClientCancelAfterUs", "ServerCancelAfterUs", "EchoMetadata", "CheckAuthContext", "ResponseMessageLength", "EchoPeer", "ExpectedClientIdentity", "SkipCancelledCheck", "ExpectedTransportSecurityType", "DebugInfo", "ServerDie", "BinaryErrorDetails", "ExpectedError", "ServerSleepUs", "BackendChannelIdx" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.EchoRequest), global::Grpc.Testing.EchoRequest.Parser, new[]{ "Message", "Param" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ResponseParams), global::Grpc.Testing.ResponseParams.Parser, new[]{ "RequestDeadline", "Host", "Peer" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.EchoResponse), global::Grpc.Testing.EchoResponse.Parser, new[]{ "Message", "Param" }, null, null, null)
@@ -435,11 +435,12 @@ namespace Grpc.Testing {
expectedClientIdentity_ = other.expectedClientIdentity_;
skipCancelledCheck_ = other.skipCancelledCheck_;
expectedTransportSecurityType_ = other.expectedTransportSecurityType_;
- DebugInfo = other.debugInfo_ != null ? other.DebugInfo.Clone() : null;
+ debugInfo_ = other.debugInfo_ != null ? other.debugInfo_.Clone() : null;
serverDie_ = other.serverDie_;
binaryErrorDetails_ = other.binaryErrorDetails_;
- ExpectedError = other.expectedError_ != null ? other.ExpectedError.Clone() : null;
+ expectedError_ = other.expectedError_ != null ? other.expectedError_.Clone() : null;
serverSleepUs_ = other.serverSleepUs_;
+ backendChannelIdx_ = other.backendChannelIdx_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@@ -622,6 +623,20 @@ namespace Grpc.Testing {
}
}
+ /// <summary>Field number for the "backend_channel_idx" field.</summary>
+ public const int BackendChannelIdxFieldNumber = 16;
+ private int backendChannelIdx_;
+ /// <summary>
+ /// which backend to send request to
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public int BackendChannelIdx {
+ get { return backendChannelIdx_; }
+ set {
+ backendChannelIdx_ = value;
+ }
+ }
+
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as RequestParams);
@@ -650,6 +665,7 @@ namespace Grpc.Testing {
if (BinaryErrorDetails != other.BinaryErrorDetails) return false;
if (!object.Equals(ExpectedError, other.ExpectedError)) return false;
if (ServerSleepUs != other.ServerSleepUs) return false;
+ if (BackendChannelIdx != other.BackendChannelIdx) return false;
return Equals(_unknownFields, other._unknownFields);
}
@@ -671,6 +687,7 @@ namespace Grpc.Testing {
if (BinaryErrorDetails.Length != 0) hash ^= BinaryErrorDetails.GetHashCode();
if (expectedError_ != null) hash ^= ExpectedError.GetHashCode();
if (ServerSleepUs != 0) hash ^= ServerSleepUs.GetHashCode();
+ if (BackendChannelIdx != 0) hash ^= BackendChannelIdx.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
@@ -744,6 +761,10 @@ namespace Grpc.Testing {
output.WriteRawTag(120);
output.WriteInt32(ServerSleepUs);
}
+ if (BackendChannelIdx != 0) {
+ output.WriteRawTag(128, 1);
+ output.WriteInt32(BackendChannelIdx);
+ }
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
@@ -797,6 +818,9 @@ namespace Grpc.Testing {
if (ServerSleepUs != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(ServerSleepUs);
}
+ if (BackendChannelIdx != 0) {
+ size += 2 + pb::CodedOutputStream.ComputeInt32Size(BackendChannelIdx);
+ }
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
@@ -859,6 +883,9 @@ namespace Grpc.Testing {
if (other.ServerSleepUs != 0) {
ServerSleepUs = other.ServerSleepUs;
}
+ if (other.BackendChannelIdx != 0) {
+ BackendChannelIdx = other.BackendChannelIdx;
+ }
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
@@ -936,6 +963,10 @@ namespace Grpc.Testing {
ServerSleepUs = input.ReadInt32();
break;
}
+ case 128: {
+ BackendChannelIdx = input.ReadInt32();
+ break;
+ }
}
}
}
@@ -968,7 +999,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public EchoRequest(EchoRequest other) : this() {
message_ = other.message_;
- Param = other.param_ != null ? other.Param.Clone() : null;
+ param_ = other.param_ != null ? other.param_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@@ -1316,7 +1347,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public EchoResponse(EchoResponse other) : this() {
message_ = other.message_;
- Param = other.param_ != null ? other.Param.Clone() : null;
+ param_ = other.param_ != null ? other.param_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
diff --git a/src/csharp/Grpc.IntegrationTesting/Messages.cs b/src/csharp/Grpc.IntegrationTesting/Messages.cs
index b5c93babd2..35546f1b67 100644
--- a/src/csharp/Grpc.IntegrationTesting/Messages.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Messages.cs
@@ -77,7 +77,6 @@ namespace Grpc.Testing {
}
#region Enums
/// <summary>
- /// DEPRECATED, don't use. To be removed shortly.
/// The type of payload that should be returned.
/// </summary>
public enum PayloadType {
@@ -269,7 +268,6 @@ namespace Grpc.Testing {
public const int TypeFieldNumber = 1;
private global::Grpc.Testing.PayloadType type_ = 0;
/// <summary>
- /// DEPRECATED, don't use. To be removed shortly.
/// The type of data in body.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -585,12 +583,12 @@ namespace Grpc.Testing {
public SimpleRequest(SimpleRequest other) : this() {
responseType_ = other.responseType_;
responseSize_ = other.responseSize_;
- Payload = other.payload_ != null ? other.Payload.Clone() : null;
+ payload_ = other.payload_ != null ? other.payload_.Clone() : null;
fillUsername_ = other.fillUsername_;
fillOauthScope_ = other.fillOauthScope_;
- ResponseCompressed = other.responseCompressed_ != null ? other.ResponseCompressed.Clone() : null;
- ResponseStatus = other.responseStatus_ != null ? other.ResponseStatus.Clone() : null;
- ExpectCompressed = other.expectCompressed_ != null ? other.ExpectCompressed.Clone() : null;
+ responseCompressed_ = other.responseCompressed_ != null ? other.responseCompressed_.Clone() : null;
+ responseStatus_ = other.responseStatus_ != null ? other.responseStatus_.Clone() : null;
+ expectCompressed_ = other.expectCompressed_ != null ? other.expectCompressed_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@@ -603,7 +601,6 @@ namespace Grpc.Testing {
public const int ResponseTypeFieldNumber = 1;
private global::Grpc.Testing.PayloadType responseType_ = 0;
/// <summary>
- /// DEPRECATED, don't use. To be removed shortly.
/// Desired payload type in the response from the server.
/// If response_type is RANDOM, server randomly chooses one from other formats.
/// </summary>
@@ -964,7 +961,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public SimpleResponse(SimpleResponse other) : this() {
- Payload = other.payload_ != null ? other.Payload.Clone() : null;
+ payload_ = other.payload_ != null ? other.payload_.Clone() : null;
username_ = other.username_;
oauthScope_ = other.oauthScope_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@@ -1168,8 +1165,8 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public StreamingInputCallRequest(StreamingInputCallRequest other) : this() {
- Payload = other.payload_ != null ? other.Payload.Clone() : null;
- ExpectCompressed = other.expectCompressed_ != null ? other.ExpectCompressed.Clone() : null;
+ payload_ = other.payload_ != null ? other.payload_.Clone() : null;
+ expectCompressed_ = other.expectCompressed_ != null ? other.expectCompressed_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@@ -1486,7 +1483,7 @@ namespace Grpc.Testing {
public ResponseParameters(ResponseParameters other) : this() {
size_ = other.size_;
intervalUs_ = other.intervalUs_;
- Compressed = other.compressed_ != null ? other.Compressed.Clone() : null;
+ compressed_ = other.compressed_ != null ? other.compressed_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@@ -1693,8 +1690,8 @@ namespace Grpc.Testing {
public StreamingOutputCallRequest(StreamingOutputCallRequest other) : this() {
responseType_ = other.responseType_;
responseParameters_ = other.responseParameters_.Clone();
- Payload = other.payload_ != null ? other.Payload.Clone() : null;
- ResponseStatus = other.responseStatus_ != null ? other.ResponseStatus.Clone() : null;
+ payload_ = other.payload_ != null ? other.payload_.Clone() : null;
+ responseStatus_ = other.responseStatus_ != null ? other.responseStatus_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@@ -1707,7 +1704,6 @@ namespace Grpc.Testing {
public const int ResponseTypeFieldNumber = 1;
private global::Grpc.Testing.PayloadType responseType_ = 0;
/// <summary>
- /// DEPRECATED, don't use. To be removed shortly.
/// Desired payload type in the response from the server.
/// If response_type is RANDOM, the payload from each response in the stream
/// might be of different types. This is to simulate a mixed type of payload
@@ -1927,7 +1923,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public StreamingOutputCallResponse(StreamingOutputCallResponse other) : this() {
- Payload = other.payload_ != null ? other.Payload.Clone() : null;
+ payload_ = other.payload_ != null ? other.payload_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
diff --git a/src/csharp/Grpc.IntegrationTesting/Stats.cs b/src/csharp/Grpc.IntegrationTesting/Stats.cs
index 8160646215..af83eef7ba 100644
--- a/src/csharp/Grpc.IntegrationTesting/Stats.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Stats.cs
@@ -86,7 +86,7 @@ namespace Grpc.Testing {
totalCpuTime_ = other.totalCpuTime_;
idleCpuTime_ = other.idleCpuTime_;
cqPollCount_ = other.cqPollCount_;
- CoreStats = other.coreStats_ != null ? other.CoreStats.Clone() : null;
+ coreStats_ = other.coreStats_ != null ? other.coreStats_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@@ -993,13 +993,13 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ClientStats(ClientStats other) : this() {
- Latencies = other.latencies_ != null ? other.Latencies.Clone() : null;
+ latencies_ = other.latencies_ != null ? other.latencies_.Clone() : null;
timeElapsed_ = other.timeElapsed_;
timeUser_ = other.timeUser_;
timeSystem_ = other.timeSystem_;
requestResults_ = other.requestResults_.Clone();
cqPollCount_ = other.cqPollCount_;
- CoreStats = other.coreStats_ != null ? other.CoreStats.Clone() : null;
+ coreStats_ = other.coreStats_ != null ? other.coreStats_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
diff --git a/src/csharp/Grpc.Reflection/Reflection.cs b/src/csharp/Grpc.Reflection/Reflection.cs
index 84b2a0a842..e319be5bff 100644
--- a/src/csharp/Grpc.Reflection/Reflection.cs
+++ b/src/csharp/Grpc.Reflection/Reflection.cs
@@ -610,7 +610,7 @@ namespace Grpc.Reflection.V1Alpha {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ServerReflectionResponse(ServerReflectionResponse other) : this() {
validHost_ = other.validHost_;
- OriginalRequest = other.originalRequest_ != null ? other.OriginalRequest.Clone() : null;
+ originalRequest_ = other.originalRequest_ != null ? other.originalRequest_.Clone() : null;
switch (other.MessageResponseCase) {
case MessageResponseOneofCase.FileDescriptorResponse:
FileDescriptorResponse = other.FileDescriptorResponse.Clone();
diff --git a/src/csharp/build_unitypackage.bat b/src/csharp/build_unitypackage.bat
index 0dcc38ee96..9c53114b84 100644
--- a/src/csharp/build_unitypackage.bat
+++ b/src/csharp/build_unitypackage.bat
@@ -68,7 +68,9 @@ copy /Y Grpc.Core\bin\Release\net45\System.Interactive.Async.dll unitypackage\un
copy /Y Grpc.HealthCheck\bin\Release\net45\Google.Protobuf.dll unitypackage\unitypackage_skeleton\Plugins\Google.Protobuf\lib\net45\Google.Protobuf.dll || goto :error
@rem create a zipfile that will act as a Unity package
-powershell -Command "Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('unitypackage\unitypackage_skeleton', 'grpc_unity_package.zip');"
+cd unitypackage\unitypackage_skeleton
+zip -r ..\..\grpc_unity_package.zip Plugins
+cd ..\..
copy /Y grpc_unity_package.zip ..\..\artifacts\grpc_unity_package.%VERSION%.zip || goto :error
goto :EOF
diff --git a/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/android/arm64-v8a/libgrpc_csharp_ext.so.meta b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/android/arm64-v8a/libgrpc_csharp_ext.so.meta
index ccaf0c20ec..6f93617280 100644
--- a/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/android/arm64-v8a/libgrpc_csharp_ext.so.meta
+++ b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/android/arm64-v8a/libgrpc_csharp_ext.so.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: e5beceb1c8fb2403ab3dea319dcd9a2e
+guid: e1f44cc7ecd4244448817ccae6de42a3
PluginImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/android/armeabi-v7a/libgrpc_csharp_ext.so.meta b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/android/armeabi-v7a/libgrpc_csharp_ext.so.meta
index 1560e207fb..82578436b8 100644
--- a/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/android/armeabi-v7a/libgrpc_csharp_ext.so.meta
+++ b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/android/armeabi-v7a/libgrpc_csharp_ext.so.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: e5beceb1c8fb2403ab3dea319dcd9a2e
+guid: 04fe0e4dcf310416b991e57c99e5d55f
PluginImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/android/x86/libgrpc_csharp_ext.so.meta b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/android/x86/libgrpc_csharp_ext.so.meta
index 4e216b8b42..3ebdd010e8 100644
--- a/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/android/x86/libgrpc_csharp_ext.so.meta
+++ b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/android/x86/libgrpc_csharp_ext.so.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: e5beceb1c8fb2403ab3dea319dcd9a2e
+guid: 245e3d515096b414fbcdd1fd4160161a
PluginImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
index 6ad9166b32..5e9a9a4513 100644
--- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
+++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
@@ -101,7 +101,7 @@ Pod::Spec.new do |s|
s.preserve_paths = plugin
# Restrict the protoc version to the one supported by this plugin.
- s.dependency '!ProtoCompiler', '3.5.0'
+ s.dependency '!ProtoCompiler', '3.6.0'
# For the Protobuf dependency not to complain:
s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.9'
diff --git a/src/objective-c/!ProtoCompiler.podspec b/src/objective-c/!ProtoCompiler.podspec
index 12598e616a..b98339941e 100644
--- a/src/objective-c/!ProtoCompiler.podspec
+++ b/src/objective-c/!ProtoCompiler.podspec
@@ -36,7 +36,7 @@ Pod::Spec.new do |s|
# exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
# before them.
s.name = '!ProtoCompiler'
- v = '3.5.0'
+ v = '3.6.0'
s.version = v
s.summary = 'The Protobuf Compiler (protoc) generates Objective-C files from .proto files'
s.description = <<-DESC
diff --git a/src/python/grpcio_health_checking/setup.py b/src/python/grpcio_health_checking/setup.py
index 35c09827ba..db2edae2ce 100644
--- a/src/python/grpcio_health_checking/setup.py
+++ b/src/python/grpcio_health_checking/setup.py
@@ -57,7 +57,7 @@ PACKAGE_DIRECTORIES = {
}
INSTALL_REQUIRES = (
- 'protobuf>=3.5.2.post1',
+ 'protobuf>=3.6.0',
'grpcio>={version}'.format(version=grpc_version.VERSION),
)
diff --git a/src/python/grpcio_reflection/setup.py b/src/python/grpcio_reflection/setup.py
index 589d0ff556..b4087d87b4 100644
--- a/src/python/grpcio_reflection/setup.py
+++ b/src/python/grpcio_reflection/setup.py
@@ -58,7 +58,7 @@ PACKAGE_DIRECTORIES = {
}
INSTALL_REQUIRES = (
- 'protobuf>=3.5.2.post1',
+ 'protobuf>=3.6.0',
'grpcio>={version}'.format(version=grpc_version.VERSION),
)
diff --git a/src/python/grpcio_testing/setup.py b/src/python/grpcio_testing/setup.py
index eb480a5464..6ceb1fc5c9 100644
--- a/src/python/grpcio_testing/setup.py
+++ b/src/python/grpcio_testing/setup.py
@@ -29,7 +29,7 @@ PACKAGE_DIRECTORIES = {
}
INSTALL_REQUIRES = (
- 'protobuf>=3.5.2.post1',
+ 'protobuf>=3.6.0',
'grpcio>={version}'.format(version=grpc_version.VERSION),
)
diff --git a/src/python/grpcio_tests/setup.py b/src/python/grpcio_tests/setup.py
index 1262e48571..a94c0963ec 100644
--- a/src/python/grpcio_tests/setup.py
+++ b/src/python/grpcio_tests/setup.py
@@ -41,8 +41,8 @@ INSTALL_REQUIRES = (
'grpcio>={version}'.format(version=grpc_version.VERSION),
'grpcio-tools>={version}'.format(version=grpc_version.VERSION),
'grpcio-health-checking>={version}'.format(version=grpc_version.VERSION),
- 'oauth2client>=1.4.7', 'protobuf>=3.5.2.post1', 'six>=1.10',
- 'google-auth>=1.0.0', 'requests>=2.14.2')
+ 'oauth2client>=1.4.7', 'protobuf>=3.6.0', 'six>=1.10', 'google-auth>=1.0.0',
+ 'requests>=2.14.2')
if not PY3:
INSTALL_REQUIRES += ('futures>=2.2.0',)
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index 78090afd6c..77f8ecf0b2 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -65,6 +65,7 @@ grpc_census_call_set_context_type grpc_census_call_set_context_import;
grpc_census_call_get_context_type grpc_census_call_get_context_import;
grpc_channel_get_target_type grpc_channel_get_target_import;
grpc_channel_get_info_type grpc_channel_get_info_import;
+grpc_channel_reset_connect_backoff_type grpc_channel_reset_connect_backoff_import;
grpc_insecure_channel_create_type grpc_insecure_channel_create_import;
grpc_lame_client_channel_create_type grpc_lame_client_channel_create_import;
grpc_channel_destroy_type grpc_channel_destroy_import;
@@ -316,6 +317,7 @@ void grpc_rb_load_imports(HMODULE library) {
grpc_census_call_get_context_import = (grpc_census_call_get_context_type) GetProcAddress(library, "grpc_census_call_get_context");
grpc_channel_get_target_import = (grpc_channel_get_target_type) GetProcAddress(library, "grpc_channel_get_target");
grpc_channel_get_info_import = (grpc_channel_get_info_type) GetProcAddress(library, "grpc_channel_get_info");
+ grpc_channel_reset_connect_backoff_import = (grpc_channel_reset_connect_backoff_type) GetProcAddress(library, "grpc_channel_reset_connect_backoff");
grpc_insecure_channel_create_import = (grpc_insecure_channel_create_type) GetProcAddress(library, "grpc_insecure_channel_create");
grpc_lame_client_channel_create_import = (grpc_lame_client_channel_create_type) GetProcAddress(library, "grpc_lame_client_channel_create");
grpc_channel_destroy_import = (grpc_channel_destroy_type) GetProcAddress(library, "grpc_channel_destroy");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index 1807efa761..0cb84c763c 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -170,6 +170,9 @@ extern grpc_channel_get_target_type grpc_channel_get_target_import;
typedef void(*grpc_channel_get_info_type)(grpc_channel* channel, const grpc_channel_info* channel_info);
extern grpc_channel_get_info_type grpc_channel_get_info_import;
#define grpc_channel_get_info grpc_channel_get_info_import
+typedef void(*grpc_channel_reset_connect_backoff_type)(grpc_channel* channel);
+extern grpc_channel_reset_connect_backoff_type grpc_channel_reset_connect_backoff_import;
+#define grpc_channel_reset_connect_backoff grpc_channel_reset_connect_backoff_import
typedef grpc_channel*(*grpc_insecure_channel_create_type)(const char* target, const grpc_channel_args* args, void* reserved);
extern grpc_insecure_channel_create_type grpc_insecure_channel_create_import;
#define grpc_insecure_channel_create grpc_insecure_channel_create_import