grpc 1.22.0 → 1.23.0

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

Potentially problematic release.


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

Files changed (176) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +487 -649
  3. data/include/grpc/grpc_security.h +25 -0
  4. data/include/grpc/impl/codegen/grpc_types.h +11 -2
  5. data/include/grpc/impl/codegen/port_platform.h +12 -0
  6. data/src/core/ext/filters/client_channel/backup_poller.cc +4 -2
  7. data/src/core/ext/filters/client_channel/client_channel.cc +477 -182
  8. data/src/core/ext/filters/client_channel/client_channel_channelz.cc +25 -16
  9. data/src/core/ext/filters/client_channel/client_channel_channelz.h +11 -6
  10. data/src/core/ext/filters/client_channel/connector.h +10 -2
  11. data/src/core/ext/filters/client_channel/health/health_check_client.cc +3 -3
  12. data/src/core/ext/filters/client_channel/http_proxy.cc +9 -10
  13. data/src/core/ext/filters/client_channel/lb_policy.cc +2 -17
  14. data/src/core/ext/filters/client_channel/lb_policy.h +36 -8
  15. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc +22 -8
  16. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +86 -52
  17. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h +7 -0
  18. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +73 -72
  19. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +8 -12
  20. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +25 -101
  21. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +5 -5
  22. data/src/core/ext/filters/client_channel/parse_address.cc +29 -26
  23. data/src/core/ext/filters/client_channel/resolver.h +3 -11
  24. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +5 -3
  25. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +405 -82
  26. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +44 -51
  27. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_libuv.cc +0 -1
  28. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +0 -1
  29. data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +11 -6
  30. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +130 -65
  31. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h +8 -3
  32. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +31 -14
  33. data/src/core/ext/filters/client_channel/resolver_factory.h +4 -0
  34. data/src/core/ext/filters/client_channel/resolver_registry.cc +11 -0
  35. data/src/core/ext/filters/client_channel/resolver_registry.h +3 -0
  36. data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +10 -49
  37. data/src/core/ext/filters/client_channel/resolving_lb_policy.h +1 -14
  38. data/src/core/ext/filters/client_channel/retry_throttle.h +2 -3
  39. data/src/core/ext/filters/client_channel/subchannel.cc +65 -58
  40. data/src/core/ext/filters/client_channel/subchannel.h +65 -45
  41. data/src/core/ext/filters/client_channel/subchannel_interface.h +15 -30
  42. data/src/core/ext/filters/client_idle/client_idle_filter.cc +262 -0
  43. data/src/core/ext/filters/http/client/http_client_filter.cc +4 -5
  44. data/src/core/ext/filters/http/client_authority_filter.cc +2 -2
  45. data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +140 -152
  46. data/src/core/ext/filters/max_age/max_age_filter.cc +3 -3
  47. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +3 -4
  48. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +7 -6
  49. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +63 -38
  50. data/src/core/ext/transport/chttp2/transport/context_list.cc +3 -1
  51. data/src/core/ext/transport/chttp2/transport/frame_data.cc +4 -4
  52. data/src/core/ext/transport/chttp2/transport/frame_goaway.cc +1 -1
  53. data/src/core/ext/transport/chttp2/transport/frame_ping.cc +1 -0
  54. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +8 -0
  55. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.h +7 -0
  56. data/src/core/ext/transport/chttp2/transport/frame_settings.cc +1 -0
  57. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +37 -22
  58. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +136 -81
  59. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +8 -0
  60. data/src/core/ext/transport/chttp2/transport/hpack_table.cc +7 -166
  61. data/src/core/ext/transport/chttp2/transport/hpack_table.h +41 -15
  62. data/src/core/ext/transport/chttp2/transport/internal.h +13 -2
  63. data/src/core/ext/transport/chttp2/transport/parsing.cc +35 -22
  64. data/src/core/ext/transport/chttp2/transport/stream_map.cc +28 -18
  65. data/src/core/ext/transport/chttp2/transport/writing.cc +1 -0
  66. data/src/core/ext/transport/inproc/inproc_transport.cc +1 -1
  67. data/src/core/lib/channel/channelz.cc +80 -33
  68. data/src/core/lib/channel/channelz.h +28 -13
  69. data/src/core/lib/compression/compression.cc +1 -2
  70. data/src/core/lib/compression/compression_args.cc +13 -6
  71. data/src/core/lib/compression/compression_args.h +3 -2
  72. data/src/core/lib/compression/compression_internal.cc +1 -1
  73. data/src/core/lib/gpr/env_linux.cc +10 -21
  74. data/src/core/lib/gpr/env_posix.cc +0 -5
  75. data/src/core/lib/gpr/string.cc +7 -2
  76. data/src/core/lib/gpr/string.h +1 -0
  77. data/src/core/lib/gpr/sync_posix.cc +0 -129
  78. data/src/core/lib/gprpp/debug_location.h +3 -2
  79. data/src/core/lib/gprpp/fork.cc +14 -21
  80. data/src/core/lib/gprpp/fork.h +15 -4
  81. data/src/core/lib/gprpp/host_port.cc +118 -0
  82. data/src/core/lib/{gpr → gprpp}/host_port.h +27 -11
  83. data/src/core/lib/gprpp/map.h +25 -0
  84. data/src/core/lib/gprpp/memory.h +26 -9
  85. data/src/core/lib/gprpp/ref_counted.h +63 -21
  86. data/src/core/lib/gprpp/string_view.h +143 -0
  87. data/src/core/lib/gprpp/thd.h +10 -1
  88. data/src/core/lib/gprpp/thd_posix.cc +25 -0
  89. data/src/core/lib/gprpp/thd_windows.cc +9 -1
  90. data/src/core/lib/http/httpcli_security_connector.cc +3 -1
  91. data/src/core/lib/iomgr/cfstream_handle.cc +6 -1
  92. data/src/core/lib/iomgr/cfstream_handle.h +8 -2
  93. data/src/core/lib/iomgr/combiner.cc +4 -4
  94. data/src/core/lib/iomgr/error.cc +18 -8
  95. data/src/core/lib/iomgr/error.h +2 -0
  96. data/src/core/lib/iomgr/ev_posix.cc +4 -2
  97. data/src/core/lib/iomgr/executor.cc +4 -1
  98. data/src/core/lib/iomgr/executor/mpmcqueue.cc +183 -0
  99. data/src/core/lib/iomgr/executor/mpmcqueue.h +178 -0
  100. data/src/core/lib/iomgr/executor/threadpool.cc +138 -0
  101. data/src/core/lib/iomgr/executor/threadpool.h +153 -0
  102. data/src/core/lib/iomgr/fork_posix.cc +4 -2
  103. data/src/core/lib/iomgr/iocp_windows.cc +2 -2
  104. data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +14 -0
  105. data/src/core/lib/iomgr/iomgr_uv.cc +3 -0
  106. data/src/core/lib/iomgr/lockfree_event.cc +3 -3
  107. data/src/core/lib/iomgr/resolve_address_custom.cc +16 -20
  108. data/src/core/lib/iomgr/resolve_address_posix.cc +8 -10
  109. data/src/core/lib/iomgr/resolve_address_windows.cc +6 -8
  110. data/src/core/lib/iomgr/sockaddr_utils.cc +5 -3
  111. data/src/core/lib/iomgr/socket_utils_common_posix.cc +0 -1
  112. data/src/core/lib/iomgr/socket_windows.h +1 -1
  113. data/src/core/lib/iomgr/tcp_client_cfstream.cc +7 -6
  114. data/src/core/lib/iomgr/tcp_client_custom.cc +1 -0
  115. data/src/core/lib/iomgr/tcp_custom.cc +4 -0
  116. data/src/core/lib/iomgr/tcp_posix.cc +8 -2
  117. data/src/core/lib/iomgr/tcp_server_custom.cc +1 -0
  118. data/src/core/lib/iomgr/tcp_server_windows.cc +1 -1
  119. data/src/core/lib/iomgr/tcp_windows.cc +7 -7
  120. data/src/core/lib/iomgr/timer_custom.cc +1 -0
  121. data/src/core/lib/iomgr/timer_manager.cc +0 -29
  122. data/src/core/lib/security/credentials/credentials.cc +84 -0
  123. data/src/core/lib/security/credentials/credentials.h +58 -2
  124. data/src/core/lib/security/credentials/jwt/json_token.cc +6 -2
  125. data/src/core/lib/security/credentials/jwt/json_token.h +1 -1
  126. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +245 -24
  127. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.h +16 -0
  128. data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +3 -2
  129. data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +21 -25
  130. data/src/core/lib/security/security_connector/local/local_security_connector.cc +3 -2
  131. data/src/core/lib/security/security_connector/security_connector.cc +1 -1
  132. data/src/core/lib/security/security_connector/security_connector.h +1 -1
  133. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +19 -19
  134. data/src/core/lib/security/security_connector/ssl_utils.cc +26 -31
  135. data/src/core/lib/security/security_connector/ssl_utils.h +11 -8
  136. data/src/core/lib/security/security_connector/tls/spiffe_security_connector.cc +16 -20
  137. data/src/core/lib/security/security_connector/tls/spiffe_security_connector.h +4 -3
  138. data/src/core/lib/security/transport/client_auth_filter.cc +1 -2
  139. data/src/core/lib/security/util/json_util.cc +19 -5
  140. data/src/core/lib/security/util/json_util.h +3 -1
  141. data/src/core/lib/slice/slice.cc +69 -50
  142. data/src/core/lib/slice/slice_buffer.cc +6 -5
  143. data/src/core/lib/slice/slice_hash_table.h +3 -7
  144. data/src/core/lib/slice/slice_intern.cc +130 -39
  145. data/src/core/lib/slice/slice_internal.h +8 -0
  146. data/src/core/lib/slice/slice_utils.h +120 -0
  147. data/src/core/lib/slice/slice_weak_hash_table.h +2 -7
  148. data/src/core/lib/surface/call.cc +8 -3
  149. data/src/core/lib/surface/channel.cc +31 -8
  150. data/src/core/lib/surface/completion_queue.cc +17 -7
  151. data/src/core/lib/surface/init_secure.cc +4 -1
  152. data/src/core/lib/surface/lame_client.cc +2 -2
  153. data/src/core/lib/surface/server.cc +34 -35
  154. data/src/core/lib/surface/server.h +8 -17
  155. data/src/core/lib/surface/version.cc +1 -1
  156. data/src/core/lib/transport/byte_stream.cc +3 -5
  157. data/src/core/lib/transport/byte_stream.h +1 -2
  158. data/src/core/lib/transport/error_utils.cc +10 -1
  159. data/src/core/lib/transport/metadata.cc +202 -35
  160. data/src/core/lib/transport/metadata.h +81 -6
  161. data/src/core/lib/transport/static_metadata.cc +1257 -465
  162. data/src/core/lib/transport/static_metadata.h +190 -347
  163. data/src/core/lib/transport/timeout_encoding.cc +7 -0
  164. data/src/core/lib/transport/timeout_encoding.h +3 -2
  165. data/src/core/plugin_registry/grpc_plugin_registry.cc +4 -0
  166. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +0 -1
  167. data/src/core/tsi/ssl/session_cache/ssl_session_cache.h +2 -7
  168. data/src/core/tsi/ssl_transport_security.cc +35 -43
  169. data/src/core/tsi/ssl_transport_security.h +2 -1
  170. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  171. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +3 -0
  172. data/src/ruby/lib/grpc/generic/rpc_server.rb +1 -1
  173. data/src/ruby/lib/grpc/grpc.rb +1 -1
  174. data/src/ruby/lib/grpc/version.rb +1 -1
  175. metadata +39 -33
  176. data/src/core/lib/gpr/host_port.cc +0 -98
@@ -84,7 +84,6 @@
84
84
  #include "src/core/lib/backoff/backoff.h"
85
85
  #include "src/core/lib/channel/channel_args.h"
86
86
  #include "src/core/lib/channel/channel_stack.h"
87
- #include "src/core/lib/gpr/host_port.h"
88
87
  #include "src/core/lib/gpr/string.h"
89
88
  #include "src/core/lib/gprpp/manual_constructor.h"
90
89
  #include "src/core/lib/gprpp/map.h"
@@ -185,9 +184,7 @@ class XdsLb : public LoadBalancingPolicy {
185
184
  bool seen_initial_response() const { return seen_initial_response_; }
186
185
 
187
186
  private:
188
- // So Delete() can access our private dtor.
189
- template <typename T>
190
- friend void grpc_core::Delete(T*);
187
+ GRPC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
191
188
 
192
189
  ~BalancerCallState();
193
190
 
@@ -570,7 +567,7 @@ XdsLb::PickResult XdsLb::Picker::Pick(PickArgs args) {
570
567
  PickResult result = PickFromLocality(key, args);
571
568
  // If pick succeeded, add client stats.
572
569
  if (result.type == PickResult::PICK_COMPLETE &&
573
- result.connected_subchannel != nullptr && client_stats_ != nullptr) {
570
+ result.subchannel != nullptr && client_stats_ != nullptr) {
574
571
  // TODO(roth): Add support for client stats.
575
572
  }
576
573
  return result;
@@ -1989,6 +1986,9 @@ void XdsLb::LocalityMap::LocalityEntry::ShutdownLocked() {
1989
1986
  parent_->interested_parties());
1990
1987
  pending_child_policy_.reset();
1991
1988
  }
1989
+ // Drop our ref to the child's picker, in case it's holding a ref to
1990
+ // the child.
1991
+ picker_ref_.reset();
1992
1992
  }
1993
1993
 
1994
1994
  void XdsLb::LocalityMap::LocalityEntry::ResetBackoffLocked() {
@@ -33,8 +33,8 @@
33
33
  #include <grpc/support/log.h>
34
34
  #include <grpc/support/string_util.h>
35
35
 
36
- #include "src/core/lib/gpr/host_port.h"
37
36
  #include "src/core/lib/gpr/string.h"
37
+ #include "src/core/lib/gprpp/host_port.h"
38
38
 
39
39
  #ifdef GRPC_POSIX_SOCKET
40
40
  #include <errno.h>
@@ -73,9 +73,9 @@ bool grpc_parse_ipv4_hostport(const char* hostport, grpc_resolved_address* addr,
73
73
  bool log_errors) {
74
74
  bool success = false;
75
75
  // Split host and port.
76
- char* host;
77
- char* port;
78
- if (!gpr_split_host_port(hostport, &host, &port)) {
76
+ grpc_core::UniquePtr<char> host;
77
+ grpc_core::UniquePtr<char> port;
78
+ if (!grpc_core::SplitHostPort(hostport, &host, &port)) {
79
79
  if (log_errors) {
80
80
  gpr_log(GPR_ERROR, "Failed gpr_split_host_port(%s, ...)", hostport);
81
81
  }
@@ -86,8 +86,10 @@ bool grpc_parse_ipv4_hostport(const char* hostport, grpc_resolved_address* addr,
86
86
  addr->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in));
87
87
  grpc_sockaddr_in* in = reinterpret_cast<grpc_sockaddr_in*>(addr->addr);
88
88
  in->sin_family = GRPC_AF_INET;
89
- if (grpc_inet_pton(GRPC_AF_INET, host, &in->sin_addr) == 0) {
90
- if (log_errors) gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host);
89
+ if (grpc_inet_pton(GRPC_AF_INET, host.get(), &in->sin_addr) == 0) {
90
+ if (log_errors) {
91
+ gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host.get());
92
+ }
91
93
  goto done;
92
94
  }
93
95
  // Parse port.
@@ -96,15 +98,14 @@ bool grpc_parse_ipv4_hostport(const char* hostport, grpc_resolved_address* addr,
96
98
  goto done;
97
99
  }
98
100
  int port_num;
99
- if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 || port_num > 65535) {
100
- if (log_errors) gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port);
101
+ if (sscanf(port.get(), "%d", &port_num) != 1 || port_num < 0 ||
102
+ port_num > 65535) {
103
+ if (log_errors) gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port.get());
101
104
  goto done;
102
105
  }
103
106
  in->sin_port = grpc_htons(static_cast<uint16_t>(port_num));
104
107
  success = true;
105
108
  done:
106
- gpr_free(host);
107
- gpr_free(port);
108
109
  return success;
109
110
  }
110
111
 
@@ -124,9 +125,9 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr,
124
125
  bool log_errors) {
125
126
  bool success = false;
126
127
  // Split host and port.
127
- char* host;
128
- char* port;
129
- if (!gpr_split_host_port(hostport, &host, &port)) {
128
+ grpc_core::UniquePtr<char> host;
129
+ grpc_core::UniquePtr<char> port;
130
+ if (!grpc_core::SplitHostPort(hostport, &host, &port)) {
130
131
  if (log_errors) {
131
132
  gpr_log(GPR_ERROR, "Failed gpr_split_host_port(%s, ...)", hostport);
132
133
  }
@@ -138,11 +139,12 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr,
138
139
  grpc_sockaddr_in6* in6 = reinterpret_cast<grpc_sockaddr_in6*>(addr->addr);
139
140
  in6->sin6_family = GRPC_AF_INET6;
140
141
  // Handle the RFC6874 syntax for IPv6 zone identifiers.
141
- char* host_end = static_cast<char*>(gpr_memrchr(host, '%', strlen(host)));
142
+ char* host_end =
143
+ static_cast<char*>(gpr_memrchr(host.get(), '%', strlen(host.get())));
142
144
  if (host_end != nullptr) {
143
- GPR_ASSERT(host_end >= host);
145
+ GPR_ASSERT(host_end >= host.get());
144
146
  char host_without_scope[GRPC_INET6_ADDRSTRLEN + 1];
145
- size_t host_without_scope_len = static_cast<size_t>(host_end - host);
147
+ size_t host_without_scope_len = static_cast<size_t>(host_end - host.get());
146
148
  uint32_t sin6_scope_id = 0;
147
149
  if (host_without_scope_len > GRPC_INET6_ADDRSTRLEN) {
148
150
  if (log_errors) {
@@ -154,7 +156,7 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr,
154
156
  }
155
157
  goto done;
156
158
  }
157
- strncpy(host_without_scope, host, host_without_scope_len);
159
+ strncpy(host_without_scope, host.get(), host_without_scope_len);
158
160
  host_without_scope[host_without_scope_len] = '\0';
159
161
  if (grpc_inet_pton(GRPC_AF_INET6, host_without_scope, &in6->sin6_addr) ==
160
162
  0) {
@@ -163,9 +165,9 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr,
163
165
  }
164
166
  goto done;
165
167
  }
166
- if (gpr_parse_bytes_to_uint32(host_end + 1,
167
- strlen(host) - host_without_scope_len - 1,
168
- &sin6_scope_id) == 0) {
168
+ if (gpr_parse_bytes_to_uint32(
169
+ host_end + 1, strlen(host.get()) - host_without_scope_len - 1,
170
+ &sin6_scope_id) == 0) {
169
171
  if ((sin6_scope_id = grpc_if_nametoindex(host_end + 1)) == 0) {
170
172
  gpr_log(GPR_ERROR,
171
173
  "Invalid interface name: '%s'. "
@@ -177,8 +179,10 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr,
177
179
  // Handle "sin6_scope_id" being type "u_long". See grpc issue #10027.
178
180
  in6->sin6_scope_id = sin6_scope_id;
179
181
  } else {
180
- if (grpc_inet_pton(GRPC_AF_INET6, host, &in6->sin6_addr) == 0) {
181
- if (log_errors) gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host);
182
+ if (grpc_inet_pton(GRPC_AF_INET6, host.get(), &in6->sin6_addr) == 0) {
183
+ if (log_errors) {
184
+ gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host.get());
185
+ }
182
186
  goto done;
183
187
  }
184
188
  }
@@ -188,15 +192,14 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr,
188
192
  goto done;
189
193
  }
190
194
  int port_num;
191
- if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 || port_num > 65535) {
192
- if (log_errors) gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port);
195
+ if (sscanf(port.get(), "%d", &port_num) != 1 || port_num < 0 ||
196
+ port_num > 65535) {
197
+ if (log_errors) gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port.get());
193
198
  goto done;
194
199
  }
195
200
  in6->sin6_port = grpc_htons(static_cast<uint16_t>(port_num));
196
201
  success = true;
197
202
  done:
198
- gpr_free(host);
199
- gpr_free(port);
200
203
  return success;
201
204
  }
202
205
 
@@ -117,12 +117,10 @@ class Resolver : public InternallyRefCounted<Resolver> {
117
117
  /// implementations. At that point, this method can go away.
118
118
  virtual void ResetBackoffLocked() {}
119
119
 
120
+ // Note: This must be invoked while holding the combiner.
120
121
  void Orphan() override {
121
- // Invoke ShutdownAndUnrefLocked() inside of the combiner.
122
- GRPC_CLOSURE_SCHED(
123
- GRPC_CLOSURE_CREATE(&Resolver::ShutdownAndUnrefLocked, this,
124
- grpc_combiner_scheduler(combiner_)),
125
- GRPC_ERROR_NONE);
122
+ ShutdownLocked();
123
+ Unref();
126
124
  }
127
125
 
128
126
  GRPC_ABSTRACT_BASE_CLASS
@@ -147,12 +145,6 @@ class Resolver : public InternallyRefCounted<Resolver> {
147
145
  ResultHandler* result_handler() const { return result_handler_.get(); }
148
146
 
149
147
  private:
150
- static void ShutdownAndUnrefLocked(void* arg, grpc_error* ignored) {
151
- Resolver* resolver = static_cast<Resolver*>(arg);
152
- resolver->ShutdownLocked();
153
- resolver->Unref();
154
- }
155
-
156
148
  UniquePtr<ResultHandler> result_handler_;
157
149
  grpc_combiner* combiner_;
158
150
  };
@@ -38,7 +38,6 @@
38
38
  #include "src/core/ext/filters/client_channel/service_config.h"
39
39
  #include "src/core/lib/backoff/backoff.h"
40
40
  #include "src/core/lib/channel/channel_args.h"
41
- #include "src/core/lib/gpr/host_port.h"
42
41
  #include "src/core/lib/gpr/string.h"
43
42
  #include "src/core/lib/gprpp/manual_constructor.h"
44
43
  #include "src/core/lib/iomgr/combiner.h"
@@ -145,7 +144,7 @@ AresDnsResolver::AresDnsResolver(ResolverArgs args)
145
144
  arg = grpc_channel_args_find(channel_args_,
146
145
  GRPC_ARG_DNS_MIN_TIME_BETWEEN_RESOLUTIONS_MS);
147
146
  min_time_between_resolutions_ =
148
- grpc_channel_arg_get_integer(arg, {1000, 0, INT_MAX});
147
+ grpc_channel_arg_get_integer(arg, {1000 * 30, 0, INT_MAX});
149
148
  // Enable SRV queries option
150
149
  arg = grpc_channel_args_find(channel_args_, GRPC_ARG_DNS_ENABLE_SRV_QUERIES);
151
150
  enable_srv_queries_ = grpc_channel_arg_get_bool(arg, false);
@@ -401,7 +400,8 @@ void AresDnsResolver::MaybeStartResolvingLocked() {
401
400
  // new closure API is done, find a way to track this ref with the timer
402
401
  // callback as part of the type system.
403
402
  Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown").release();
404
- grpc_timer_init(&next_resolution_timer_, ms_until_next_resolution,
403
+ grpc_timer_init(&next_resolution_timer_,
404
+ ExecCtx::Get()->Now() + ms_until_next_resolution,
405
405
  &on_next_resolution_);
406
406
  return;
407
407
  }
@@ -433,6 +433,8 @@ void AresDnsResolver::StartResolvingLocked() {
433
433
 
434
434
  class AresDnsResolverFactory : public ResolverFactory {
435
435
  public:
436
+ bool IsValidUri(const grpc_uri* uri) const override { return true; }
437
+
436
438
  OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
437
439
  return OrphanablePtr<Resolver>(New<AresDnsResolver>(std::move(args)));
438
440
  }
@@ -31,6 +31,9 @@
31
31
  #include "src/core/lib/gpr/string.h"
32
32
  #include "src/core/lib/gprpp/memory.h"
33
33
  #include "src/core/lib/iomgr/combiner.h"
34
+ #include "src/core/lib/iomgr/iocp_windows.h"
35
+ #include "src/core/lib/iomgr/sockaddr_utils.h"
36
+ #include "src/core/lib/iomgr/sockaddr_windows.h"
34
37
  #include "src/core/lib/iomgr/socket_windows.h"
35
38
  #include "src/core/lib/iomgr/tcp_windows.h"
36
39
  #include "src/core/lib/slice/slice_internal.h"
@@ -50,6 +53,32 @@ struct iovec {
50
53
 
51
54
  namespace grpc_core {
52
55
 
56
+ /* c-ares reads and takes action on the error codes of the
57
+ * "virtual socket operations" in this file, via the WSAGetLastError
58
+ * APIs. If code in this file wants to set a specific WSA error that
59
+ * c-ares should read, it must do so by calling SetWSAError() on the
60
+ * WSAErrorContext instance passed to it. A WSAErrorContext must only be
61
+ * instantiated at the top of the virtual socket function callstack. */
62
+ class WSAErrorContext {
63
+ public:
64
+ explicit WSAErrorContext(){};
65
+
66
+ ~WSAErrorContext() {
67
+ if (error_ != 0) {
68
+ WSASetLastError(error_);
69
+ }
70
+ }
71
+
72
+ /* Disallow copy and assignment operators */
73
+ WSAErrorContext(const WSAErrorContext&) = delete;
74
+ WSAErrorContext& operator=(const WSAErrorContext&) = delete;
75
+
76
+ void SetWSAError(int error) { error_ = error; }
77
+
78
+ private:
79
+ int error_ = 0;
80
+ };
81
+
53
82
  /* c-ares creates its own sockets and is meant to read them when readable and
54
83
  * write them when writeable. To fit this socket usage model into the grpc
55
84
  * windows poller (which gives notifications when attempted reads and writes are
@@ -68,11 +97,14 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
68
97
  WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY,
69
98
  };
70
99
 
71
- GrpcPolledFdWindows(ares_socket_t as, grpc_combiner* combiner)
100
+ GrpcPolledFdWindows(ares_socket_t as, grpc_combiner* combiner,
101
+ int address_family, int socket_type)
72
102
  : read_buf_(grpc_empty_slice()),
73
103
  write_buf_(grpc_empty_slice()),
74
- write_state_(WRITE_IDLE),
75
- gotten_into_driver_list_(false) {
104
+ tcp_write_state_(WRITE_IDLE),
105
+ gotten_into_driver_list_(false),
106
+ address_family_(address_family),
107
+ socket_type_(socket_type) {
76
108
  gpr_asprintf(&name_, "c-ares socket: %" PRIdPTR, as);
77
109
  winsocket_ = grpc_winsocket_create(as, name_);
78
110
  combiner_ = GRPC_COMBINER_REF(combiner, name_);
@@ -82,6 +114,16 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
82
114
  GRPC_CLOSURE_INIT(&outer_write_closure_,
83
115
  &GrpcPolledFdWindows::OnIocpWriteable, this,
84
116
  grpc_combiner_scheduler(combiner_));
117
+ GRPC_CLOSURE_INIT(&on_tcp_connect_locked_,
118
+ &GrpcPolledFdWindows::OnTcpConnectLocked, this,
119
+ grpc_combiner_scheduler(combiner_));
120
+ GRPC_CLOSURE_INIT(&continue_register_for_on_readable_locked_,
121
+ &GrpcPolledFdWindows::ContinueRegisterForOnReadableLocked,
122
+ this, grpc_combiner_scheduler(combiner_));
123
+ GRPC_CLOSURE_INIT(
124
+ &continue_register_for_on_writeable_locked_,
125
+ &GrpcPolledFdWindows::ContinueRegisterForOnWriteableLocked, this,
126
+ grpc_combiner_scheduler(combiner_));
85
127
  }
86
128
 
87
129
  ~GrpcPolledFdWindows() {
@@ -111,6 +153,33 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
111
153
  grpc_slice_unref_internal(read_buf_);
112
154
  GPR_ASSERT(!read_buf_has_data_);
113
155
  read_buf_ = GRPC_SLICE_MALLOC(4192);
156
+ if (connect_done_) {
157
+ GRPC_CLOSURE_SCHED(&continue_register_for_on_readable_locked_,
158
+ GRPC_ERROR_NONE);
159
+ } else {
160
+ GPR_ASSERT(pending_continue_register_for_on_readable_locked_ == nullptr);
161
+ pending_continue_register_for_on_readable_locked_ =
162
+ &continue_register_for_on_readable_locked_;
163
+ }
164
+ }
165
+
166
+ static void ContinueRegisterForOnReadableLocked(void* arg,
167
+ grpc_error* unused_error) {
168
+ GrpcPolledFdWindows* grpc_polled_fd =
169
+ static_cast<GrpcPolledFdWindows*>(arg);
170
+ grpc_polled_fd->InnerContinueRegisterForOnReadableLocked(GRPC_ERROR_NONE);
171
+ }
172
+
173
+ void InnerContinueRegisterForOnReadableLocked(grpc_error* unused_error) {
174
+ GRPC_CARES_TRACE_LOG(
175
+ "fd:|%s| InnerContinueRegisterForOnReadableLocked "
176
+ "wsa_connect_error_:%d",
177
+ GetName(), wsa_connect_error_);
178
+ GPR_ASSERT(connect_done_);
179
+ if (wsa_connect_error_ != 0) {
180
+ ScheduleAndNullReadClosure(GRPC_WSA_ERROR(wsa_connect_error_, "connect"));
181
+ return;
182
+ }
114
183
  WSABUF buffer;
115
184
  buffer.buf = (char*)GRPC_SLICE_START_PTR(read_buf_);
116
185
  buffer.len = GRPC_SLICE_LENGTH(read_buf_);
@@ -123,13 +192,14 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
123
192
  &winsocket_->read_info.overlapped, nullptr)) {
124
193
  int wsa_last_error = WSAGetLastError();
125
194
  char* msg = gpr_format_message(wsa_last_error);
126
- grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
127
195
  GRPC_CARES_TRACE_LOG(
128
- "RegisterForOnReadableLocked: WSARecvFrom error:|%s|. fd:|%s|", msg,
129
- GetName());
196
+ "fd:|%s| RegisterForOnReadableLocked WSARecvFrom error code:|%d| "
197
+ "msg:|%s|",
198
+ GetName(), wsa_last_error, msg);
130
199
  gpr_free(msg);
131
200
  if (wsa_last_error != WSA_IO_PENDING) {
132
- ScheduleAndNullReadClosure(error);
201
+ ScheduleAndNullReadClosure(
202
+ GRPC_WSA_ERROR(wsa_last_error, "WSARecvFrom"));
133
203
  return;
134
204
  }
135
205
  }
@@ -137,23 +207,68 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
137
207
  }
138
208
 
139
209
  void RegisterForOnWriteableLocked(grpc_closure* write_closure) override {
140
- GRPC_CARES_TRACE_LOG(
141
- "RegisterForOnWriteableLocked. fd:|%s|. Current write state: %d",
142
- GetName(), write_state_);
210
+ if (socket_type_ == SOCK_DGRAM) {
211
+ GRPC_CARES_TRACE_LOG("fd:|%s| RegisterForOnWriteableLocked called",
212
+ GetName());
213
+ } else {
214
+ GPR_ASSERT(socket_type_ == SOCK_STREAM);
215
+ GRPC_CARES_TRACE_LOG(
216
+ "fd:|%s| RegisterForOnWriteableLocked called tcp_write_state_: %d",
217
+ GetName(), tcp_write_state_);
218
+ }
143
219
  GPR_ASSERT(write_closure_ == nullptr);
144
220
  write_closure_ = write_closure;
145
- switch (write_state_) {
146
- case WRITE_IDLE:
147
- ScheduleAndNullWriteClosure(GRPC_ERROR_NONE);
148
- break;
149
- case WRITE_REQUESTED:
150
- write_state_ = WRITE_PENDING;
151
- SendWriteBuf(nullptr, &winsocket_->write_info.overlapped);
152
- grpc_socket_notify_on_write(winsocket_, &outer_write_closure_);
153
- break;
154
- case WRITE_PENDING:
155
- case WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY:
156
- abort();
221
+ if (connect_done_) {
222
+ GRPC_CLOSURE_SCHED(&continue_register_for_on_writeable_locked_,
223
+ GRPC_ERROR_NONE);
224
+ } else {
225
+ GPR_ASSERT(pending_continue_register_for_on_writeable_locked_ == nullptr);
226
+ pending_continue_register_for_on_writeable_locked_ =
227
+ &continue_register_for_on_writeable_locked_;
228
+ }
229
+ }
230
+
231
+ static void ContinueRegisterForOnWriteableLocked(void* arg,
232
+ grpc_error* unused_error) {
233
+ GrpcPolledFdWindows* grpc_polled_fd =
234
+ static_cast<GrpcPolledFdWindows*>(arg);
235
+ grpc_polled_fd->InnerContinueRegisterForOnWriteableLocked(GRPC_ERROR_NONE);
236
+ }
237
+
238
+ void InnerContinueRegisterForOnWriteableLocked(grpc_error* unused_error) {
239
+ GRPC_CARES_TRACE_LOG(
240
+ "fd:|%s| InnerContinueRegisterForOnWriteableLocked "
241
+ "wsa_connect_error_:%d",
242
+ GetName(), wsa_connect_error_);
243
+ GPR_ASSERT(connect_done_);
244
+ if (wsa_connect_error_ != 0) {
245
+ ScheduleAndNullWriteClosure(
246
+ GRPC_WSA_ERROR(wsa_connect_error_, "connect"));
247
+ return;
248
+ }
249
+ if (socket_type_ == SOCK_DGRAM) {
250
+ ScheduleAndNullWriteClosure(GRPC_ERROR_NONE);
251
+ } else {
252
+ GPR_ASSERT(socket_type_ == SOCK_STREAM);
253
+ int wsa_error_code = 0;
254
+ switch (tcp_write_state_) {
255
+ case WRITE_IDLE:
256
+ ScheduleAndNullWriteClosure(GRPC_ERROR_NONE);
257
+ break;
258
+ case WRITE_REQUESTED:
259
+ tcp_write_state_ = WRITE_PENDING;
260
+ if (SendWriteBuf(nullptr, &winsocket_->write_info.overlapped,
261
+ &wsa_error_code) != 0) {
262
+ ScheduleAndNullWriteClosure(
263
+ GRPC_WSA_ERROR(wsa_error_code, "WSASend (overlapped)"));
264
+ } else {
265
+ grpc_socket_notify_on_write(winsocket_, &outer_write_closure_);
266
+ }
267
+ break;
268
+ case WRITE_PENDING:
269
+ case WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY:
270
+ abort();
271
+ }
157
272
  }
158
273
  }
159
274
 
@@ -171,13 +286,15 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
171
286
 
172
287
  const char* GetName() override { return name_; }
173
288
 
174
- ares_ssize_t RecvFrom(void* data, ares_socket_t data_len, int flags,
289
+ ares_ssize_t RecvFrom(WSAErrorContext* wsa_error_ctx, void* data,
290
+ ares_socket_t data_len, int flags,
175
291
  struct sockaddr* from, ares_socklen_t* from_len) {
176
292
  GRPC_CARES_TRACE_LOG(
177
- "RecvFrom called on fd:|%s|. Current read buf length:|%d|", GetName(),
178
- GRPC_SLICE_LENGTH(read_buf_));
293
+ "fd:|%s| RecvFrom called read_buf_has_data:%d Current read buf "
294
+ "length:|%d|",
295
+ GetName(), read_buf_has_data_, GRPC_SLICE_LENGTH(read_buf_));
179
296
  if (!read_buf_has_data_) {
180
- WSASetLastError(WSAEWOULDBLOCK);
297
+ wsa_error_ctx->SetWSAError(WSAEWOULDBLOCK);
181
298
  return -1;
182
299
  }
183
300
  ares_ssize_t bytes_read = 0;
@@ -215,54 +332,99 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
215
332
  return out;
216
333
  }
217
334
 
218
- int SendWriteBuf(LPDWORD bytes_sent_ptr, LPWSAOVERLAPPED overlapped) {
335
+ int SendWriteBuf(LPDWORD bytes_sent_ptr, LPWSAOVERLAPPED overlapped,
336
+ int* wsa_error_code) {
219
337
  WSABUF buf;
220
338
  buf.len = GRPC_SLICE_LENGTH(write_buf_);
221
339
  buf.buf = (char*)GRPC_SLICE_START_PTR(write_buf_);
222
340
  DWORD flags = 0;
223
341
  int out = WSASend(grpc_winsocket_wrapped_socket(winsocket_), &buf, 1,
224
342
  bytes_sent_ptr, flags, overlapped, nullptr);
343
+ *wsa_error_code = WSAGetLastError();
225
344
  GRPC_CARES_TRACE_LOG(
226
- "WSASend: name:%s. buf len:%d. bytes sent: %d. overlapped %p. return "
227
- "val: %d",
228
- GetName(), buf.len, *bytes_sent_ptr, overlapped, out);
345
+ "fd:|%s| SendWriteBuf WSASend buf.len:%d *bytes_sent_ptr:%d "
346
+ "overlapped:%p "
347
+ "return:%d *wsa_error_code:%d",
348
+ GetName(), buf.len, bytes_sent_ptr != nullptr ? *bytes_sent_ptr : 0,
349
+ overlapped, out, *wsa_error_code);
229
350
  return out;
230
351
  }
231
352
 
232
- ares_ssize_t TrySendWriteBufSyncNonBlocking() {
233
- GPR_ASSERT(write_state_ == WRITE_IDLE);
353
+ ares_ssize_t SendV(WSAErrorContext* wsa_error_ctx, const struct iovec* iov,
354
+ int iov_count) {
355
+ GRPC_CARES_TRACE_LOG(
356
+ "fd:|%s| SendV called connect_done_:%d wsa_connect_error_:%d",
357
+ GetName(), connect_done_, wsa_connect_error_);
358
+ if (!connect_done_) {
359
+ wsa_error_ctx->SetWSAError(WSAEWOULDBLOCK);
360
+ return -1;
361
+ }
362
+ if (wsa_connect_error_ != 0) {
363
+ wsa_error_ctx->SetWSAError(wsa_connect_error_);
364
+ return -1;
365
+ }
366
+ switch (socket_type_) {
367
+ case SOCK_DGRAM:
368
+ return SendVUDP(wsa_error_ctx, iov, iov_count);
369
+ case SOCK_STREAM:
370
+ return SendVTCP(wsa_error_ctx, iov, iov_count);
371
+ default:
372
+ abort();
373
+ }
374
+ }
375
+
376
+ ares_ssize_t SendVUDP(WSAErrorContext* wsa_error_ctx, const struct iovec* iov,
377
+ int iov_count) {
378
+ // c-ares doesn't handle retryable errors on writes of UDP sockets.
379
+ // Therefore, the sendv handler for UDP sockets must only attempt
380
+ // to write everything inline.
381
+ GRPC_CARES_TRACE_LOG("fd:|%s| SendVUDP called", GetName());
382
+ GPR_ASSERT(GRPC_SLICE_LENGTH(write_buf_) == 0);
383
+ grpc_slice_unref_internal(write_buf_);
384
+ write_buf_ = FlattenIovec(iov, iov_count);
234
385
  DWORD bytes_sent = 0;
235
- if (SendWriteBuf(&bytes_sent, nullptr) != 0) {
236
- int wsa_last_error = WSAGetLastError();
237
- char* msg = gpr_format_message(wsa_last_error);
386
+ int wsa_error_code = 0;
387
+ if (SendWriteBuf(&bytes_sent, nullptr, &wsa_error_code) != 0) {
388
+ wsa_error_ctx->SetWSAError(wsa_error_code);
389
+ char* msg = gpr_format_message(wsa_error_code);
238
390
  GRPC_CARES_TRACE_LOG(
239
- "TrySendWriteBufSyncNonBlocking: SendWriteBuf error:|%s|. fd:|%s|",
240
- msg, GetName());
391
+ "fd:|%s| SendVUDP SendWriteBuf error code:%d msg:|%s|", GetName(),
392
+ wsa_error_code, msg);
241
393
  gpr_free(msg);
242
- if (wsa_last_error == WSA_IO_PENDING) {
243
- WSASetLastError(WSAEWOULDBLOCK);
244
- write_state_ = WRITE_REQUESTED;
245
- }
394
+ return -1;
246
395
  }
247
396
  write_buf_ = grpc_slice_sub_no_ref(write_buf_, bytes_sent,
248
397
  GRPC_SLICE_LENGTH(write_buf_));
249
398
  return bytes_sent;
250
399
  }
251
400
 
252
- ares_ssize_t SendV(const struct iovec* iov, int iov_count) {
253
- GRPC_CARES_TRACE_LOG("SendV called on fd:|%s|. Current write state: %d",
254
- GetName(), write_state_);
255
- switch (write_state_) {
401
+ ares_ssize_t SendVTCP(WSAErrorContext* wsa_error_ctx, const struct iovec* iov,
402
+ int iov_count) {
403
+ // The "sendv" handler on TCP sockets buffers up write
404
+ // requests and returns an artifical WSAEWOULDBLOCK. Writing that buffer out
405
+ // in the background, and making further send progress in general, will
406
+ // happen as long as c-ares continues to show interest in writeability on
407
+ // this fd.
408
+ GRPC_CARES_TRACE_LOG("fd:|%s| SendVTCP called tcp_write_state_:%d",
409
+ GetName(), tcp_write_state_);
410
+ switch (tcp_write_state_) {
256
411
  case WRITE_IDLE:
412
+ tcp_write_state_ = WRITE_REQUESTED;
257
413
  GPR_ASSERT(GRPC_SLICE_LENGTH(write_buf_) == 0);
258
414
  grpc_slice_unref_internal(write_buf_);
259
415
  write_buf_ = FlattenIovec(iov, iov_count);
260
- return TrySendWriteBufSyncNonBlocking();
416
+ wsa_error_ctx->SetWSAError(WSAEWOULDBLOCK);
417
+ return -1;
261
418
  case WRITE_REQUESTED:
262
419
  case WRITE_PENDING:
263
- WSASetLastError(WSAEWOULDBLOCK);
420
+ wsa_error_ctx->SetWSAError(WSAEWOULDBLOCK);
264
421
  return -1;
265
422
  case WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY:
423
+ // c-ares is retrying a send on data that we previously returned
424
+ // WSAEWOULDBLOCK for, but then subsequently wrote out in the
425
+ // background. Right now, we assume that c-ares is retrying the same
426
+ // send again. If c-ares still needs to send even more data, we'll get
427
+ // to it eventually.
266
428
  grpc_slice currently_attempted = FlattenIovec(iov, iov_count);
267
429
  GPR_ASSERT(GRPC_SLICE_LENGTH(currently_attempted) >=
268
430
  GRPC_SLICE_LENGTH(write_buf_));
@@ -272,31 +434,160 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
272
434
  GRPC_SLICE_START_PTR(write_buf_)[i]);
273
435
  total_sent++;
274
436
  }
275
- grpc_slice_unref_internal(write_buf_);
276
- write_buf_ =
277
- grpc_slice_sub_no_ref(currently_attempted, total_sent,
278
- GRPC_SLICE_LENGTH(currently_attempted));
279
- write_state_ = WRITE_IDLE;
280
- total_sent += TrySendWriteBufSyncNonBlocking();
437
+ grpc_slice_unref_internal(currently_attempted);
438
+ tcp_write_state_ = WRITE_IDLE;
281
439
  return total_sent;
282
440
  }
283
441
  abort();
284
442
  }
285
443
 
286
- int Connect(const struct sockaddr* target, ares_socklen_t target_len) {
444
+ static void OnTcpConnectLocked(void* arg, grpc_error* error) {
445
+ GrpcPolledFdWindows* grpc_polled_fd =
446
+ static_cast<GrpcPolledFdWindows*>(arg);
447
+ grpc_polled_fd->InnerOnTcpConnectLocked(error);
448
+ }
449
+
450
+ void InnerOnTcpConnectLocked(grpc_error* error) {
451
+ GRPC_CARES_TRACE_LOG(
452
+ "fd:%s InnerOnTcpConnectLocked error:|%s| "
453
+ "pending_register_for_readable:%" PRIdPTR
454
+ " pending_register_for_writeable:%" PRIdPTR,
455
+ GetName(), grpc_error_string(error),
456
+ pending_continue_register_for_on_readable_locked_,
457
+ pending_continue_register_for_on_writeable_locked_);
458
+ GPR_ASSERT(!connect_done_);
459
+ connect_done_ = true;
460
+ GPR_ASSERT(wsa_connect_error_ == 0);
461
+ if (error == GRPC_ERROR_NONE) {
462
+ DWORD transferred_bytes = 0;
463
+ DWORD flags;
464
+ BOOL wsa_success =
465
+ WSAGetOverlappedResult(grpc_winsocket_wrapped_socket(winsocket_),
466
+ &winsocket_->write_info.overlapped,
467
+ &transferred_bytes, FALSE, &flags);
468
+ GPR_ASSERT(transferred_bytes == 0);
469
+ if (!wsa_success) {
470
+ wsa_connect_error_ = WSAGetLastError();
471
+ char* msg = gpr_format_message(wsa_connect_error_);
472
+ GRPC_CARES_TRACE_LOG(
473
+ "fd:%s InnerOnTcpConnectLocked WSA overlapped result code:%d "
474
+ "msg:|%s|",
475
+ GetName(), wsa_connect_error_, msg);
476
+ gpr_free(msg);
477
+ }
478
+ } else {
479
+ // Spoof up an error code that will cause any future c-ares operations on
480
+ // this fd to abort.
481
+ wsa_connect_error_ = WSA_OPERATION_ABORTED;
482
+ }
483
+ if (pending_continue_register_for_on_readable_locked_ != nullptr) {
484
+ GRPC_CLOSURE_SCHED(pending_continue_register_for_on_readable_locked_,
485
+ GRPC_ERROR_NONE);
486
+ }
487
+ if (pending_continue_register_for_on_writeable_locked_ != nullptr) {
488
+ GRPC_CLOSURE_SCHED(pending_continue_register_for_on_writeable_locked_,
489
+ GRPC_ERROR_NONE);
490
+ }
491
+ }
492
+
493
+ int Connect(WSAErrorContext* wsa_error_ctx, const struct sockaddr* target,
494
+ ares_socklen_t target_len) {
495
+ switch (socket_type_) {
496
+ case SOCK_DGRAM:
497
+ return ConnectUDP(wsa_error_ctx, target, target_len);
498
+ case SOCK_STREAM:
499
+ return ConnectTCP(wsa_error_ctx, target, target_len);
500
+ default:
501
+ abort();
502
+ }
503
+ }
504
+
505
+ int ConnectUDP(WSAErrorContext* wsa_error_ctx, const struct sockaddr* target,
506
+ ares_socklen_t target_len) {
507
+ GRPC_CARES_TRACE_LOG("fd:%s ConnectUDP", GetName());
508
+ GPR_ASSERT(!connect_done_);
509
+ GPR_ASSERT(wsa_connect_error_ == 0);
287
510
  SOCKET s = grpc_winsocket_wrapped_socket(winsocket_);
288
- GRPC_CARES_TRACE_LOG("Connect: fd:|%s|", GetName());
289
511
  int out =
290
512
  WSAConnect(s, target, target_len, nullptr, nullptr, nullptr, nullptr);
291
- if (out != 0) {
513
+ wsa_connect_error_ = WSAGetLastError();
514
+ wsa_error_ctx->SetWSAError(wsa_connect_error_);
515
+ connect_done_ = true;
516
+ char* msg = gpr_format_message(wsa_connect_error_);
517
+ GRPC_CARES_TRACE_LOG("fd:%s WSAConnect error code:|%d| msg:|%s|", GetName(),
518
+ wsa_connect_error_, msg);
519
+ gpr_free(msg);
520
+ // c-ares expects a posix-style connect API
521
+ return out == 0 ? 0 : -1;
522
+ }
523
+
524
+ int ConnectTCP(WSAErrorContext* wsa_error_ctx, const struct sockaddr* target,
525
+ ares_socklen_t target_len) {
526
+ GRPC_CARES_TRACE_LOG("fd:%s ConnectTCP", GetName());
527
+ LPFN_CONNECTEX ConnectEx;
528
+ GUID guid = WSAID_CONNECTEX;
529
+ DWORD ioctl_num_bytes;
530
+ SOCKET s = grpc_winsocket_wrapped_socket(winsocket_);
531
+ if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
532
+ &ConnectEx, sizeof(ConnectEx), &ioctl_num_bytes, nullptr,
533
+ nullptr) != 0) {
534
+ int wsa_last_error = WSAGetLastError();
535
+ wsa_error_ctx->SetWSAError(wsa_last_error);
536
+ char* msg = gpr_format_message(wsa_last_error);
537
+ GRPC_CARES_TRACE_LOG(
538
+ "fd:%s WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER) error code:%d "
539
+ "msg:|%s|",
540
+ GetName(), wsa_last_error, msg);
541
+ gpr_free(msg);
542
+ connect_done_ = true;
543
+ wsa_connect_error_ = wsa_last_error;
544
+ return -1;
545
+ }
546
+ grpc_resolved_address wildcard4_addr;
547
+ grpc_resolved_address wildcard6_addr;
548
+ grpc_sockaddr_make_wildcards(0, &wildcard4_addr, &wildcard6_addr);
549
+ grpc_resolved_address* local_address = nullptr;
550
+ if (address_family_ == AF_INET) {
551
+ local_address = &wildcard4_addr;
552
+ } else {
553
+ local_address = &wildcard6_addr;
554
+ }
555
+ if (bind(s, (struct sockaddr*)local_address->addr,
556
+ (int)local_address->len) != 0) {
292
557
  int wsa_last_error = WSAGetLastError();
558
+ wsa_error_ctx->SetWSAError(wsa_last_error);
293
559
  char* msg = gpr_format_message(wsa_last_error);
294
- GRPC_CARES_TRACE_LOG("Connect error code:|%d|, msg:|%s|. fd:|%s|",
295
- wsa_last_error, msg, GetName());
560
+ GRPC_CARES_TRACE_LOG("fd:%s bind error code:%d msg:|%s|", GetName(),
561
+ wsa_last_error, msg);
296
562
  gpr_free(msg);
297
- // c-ares expects a posix-style connect API
563
+ connect_done_ = true;
564
+ wsa_connect_error_ = wsa_last_error;
565
+ return -1;
566
+ }
567
+ int out = 0;
568
+ if (ConnectEx(s, target, target_len, nullptr, 0, nullptr,
569
+ &winsocket_->write_info.overlapped) == 0) {
298
570
  out = -1;
571
+ int wsa_last_error = WSAGetLastError();
572
+ wsa_error_ctx->SetWSAError(wsa_last_error);
573
+ char* msg = gpr_format_message(wsa_last_error);
574
+ GRPC_CARES_TRACE_LOG("fd:%s ConnectEx error code:%d msg:|%s|", GetName(),
575
+ wsa_last_error, msg);
576
+ gpr_free(msg);
577
+ if (wsa_last_error == WSA_IO_PENDING) {
578
+ // c-ares only understands WSAEINPROGRESS and EWOULDBLOCK error codes on
579
+ // connect, but an async connect on IOCP socket will give
580
+ // WSA_IO_PENDING, so we need to convert.
581
+ wsa_error_ctx->SetWSAError(WSAEWOULDBLOCK);
582
+ } else {
583
+ // By returning a non-retryable error to c-ares at this point,
584
+ // we're aborting the possibility of any future operations on this fd.
585
+ connect_done_ = true;
586
+ wsa_connect_error_ = wsa_last_error;
587
+ return -1;
588
+ }
299
589
  }
590
+ grpc_socket_notify_on_write(winsocket_, &on_tcp_connect_locked_);
300
591
  return out;
301
592
  }
302
593
 
@@ -319,26 +610,27 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
319
610
  * in subsequent c-ares reads. */
320
611
  if (winsocket_->read_info.wsa_error != WSAEMSGSIZE) {
321
612
  GRPC_ERROR_UNREF(error);
322
- char* msg = gpr_format_message(winsocket_->read_info.wsa_error);
613
+ error = GRPC_WSA_ERROR(winsocket_->read_info.wsa_error,
614
+ "OnIocpReadableInner");
323
615
  GRPC_CARES_TRACE_LOG(
324
- "OnIocpReadableInner. winsocket error:|%s|. fd:|%s|", msg,
325
- GetName());
326
- error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
327
- gpr_free(msg);
616
+ "fd:|%s| OnIocpReadableInner winsocket_->read_info.wsa_error "
617
+ "code:|%d| msg:|%s|",
618
+ GetName(), winsocket_->read_info.wsa_error,
619
+ grpc_error_string(error));
328
620
  }
329
621
  }
330
622
  }
331
623
  if (error == GRPC_ERROR_NONE) {
332
- read_buf_ = grpc_slice_sub_no_ref(read_buf_, 0,
333
- winsocket_->read_info.bytes_transfered);
624
+ read_buf_ = grpc_slice_sub_no_ref(
625
+ read_buf_, 0, winsocket_->read_info.bytes_transferred);
334
626
  read_buf_has_data_ = true;
335
627
  } else {
336
628
  grpc_slice_unref_internal(read_buf_);
337
629
  read_buf_ = grpc_empty_slice();
338
630
  }
339
631
  GRPC_CARES_TRACE_LOG(
340
- "OnIocpReadable finishing. read buf length now:|%d|. :fd:|%s|",
341
- GRPC_SLICE_LENGTH(read_buf_), GetName());
632
+ "fd:|%s| OnIocpReadable finishing. read buf length now:|%d|", GetName(),
633
+ GRPC_SLICE_LENGTH(read_buf_));
342
634
  ScheduleAndNullReadClosure(error);
343
635
  }
344
636
 
@@ -349,22 +641,26 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
349
641
 
350
642
  void OnIocpWriteableInner(grpc_error* error) {
351
643
  GRPC_CARES_TRACE_LOG("OnIocpWriteableInner. fd:|%s|", GetName());
644
+ GPR_ASSERT(socket_type_ == SOCK_STREAM);
352
645
  if (error == GRPC_ERROR_NONE) {
353
646
  if (winsocket_->write_info.wsa_error != 0) {
354
- char* msg = gpr_format_message(winsocket_->write_info.wsa_error);
355
- GRPC_CARES_TRACE_LOG(
356
- "OnIocpWriteableInner. winsocket error:|%s|. fd:|%s|", msg,
357
- GetName());
358
647
  GRPC_ERROR_UNREF(error);
359
- error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
360
- gpr_free(msg);
648
+ error = GRPC_WSA_ERROR(winsocket_->write_info.wsa_error,
649
+ "OnIocpWriteableInner");
650
+ GRPC_CARES_TRACE_LOG(
651
+ "fd:|%s| OnIocpWriteableInner. winsocket_->write_info.wsa_error "
652
+ "code:|%d| msg:|%s|",
653
+ GetName(), winsocket_->write_info.wsa_error,
654
+ grpc_error_string(error));
361
655
  }
362
656
  }
363
- GPR_ASSERT(write_state_ == WRITE_PENDING);
657
+ GPR_ASSERT(tcp_write_state_ == WRITE_PENDING);
364
658
  if (error == GRPC_ERROR_NONE) {
365
- write_state_ = WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY;
659
+ tcp_write_state_ = WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY;
366
660
  write_buf_ = grpc_slice_sub_no_ref(
367
- write_buf_, 0, winsocket_->write_info.bytes_transfered);
661
+ write_buf_, 0, winsocket_->write_info.bytes_transferred);
662
+ GRPC_CARES_TRACE_LOG("fd:|%s| OnIocpWriteableInner. bytes transferred:%d",
663
+ GetName(), winsocket_->write_info.bytes_transferred);
368
664
  } else {
369
665
  grpc_slice_unref_internal(write_buf_);
370
666
  write_buf_ = grpc_empty_slice();
@@ -386,9 +682,22 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
386
682
  grpc_closure outer_read_closure_;
387
683
  grpc_closure outer_write_closure_;
388
684
  grpc_winsocket* winsocket_;
389
- WriteState write_state_;
685
+ // tcp_write_state_ is only used on TCP GrpcPolledFds
686
+ WriteState tcp_write_state_;
390
687
  char* name_ = nullptr;
391
688
  bool gotten_into_driver_list_;
689
+ int address_family_;
690
+ int socket_type_;
691
+ grpc_closure on_tcp_connect_locked_;
692
+ bool connect_done_ = false;
693
+ int wsa_connect_error_ = 0;
694
+ // We don't run register_for_{readable,writeable} logic until
695
+ // a socket is connected. In the interim, we queue readable/writeable
696
+ // registrations with the following state.
697
+ grpc_closure continue_register_for_on_readable_locked_;
698
+ grpc_closure continue_register_for_on_writeable_locked_;
699
+ grpc_closure* pending_continue_register_for_on_readable_locked_ = nullptr;
700
+ grpc_closure* pending_continue_register_for_on_writeable_locked_ = nullptr;
392
701
  };
393
702
 
394
703
  struct SockToPolledFdEntry {
@@ -454,39 +763,53 @@ class SockToPolledFdMap {
454
763
  * objects.
455
764
  */
456
765
  static ares_socket_t Socket(int af, int type, int protocol, void* user_data) {
766
+ if (type != SOCK_DGRAM && type != SOCK_STREAM) {
767
+ GRPC_CARES_TRACE_LOG("Socket called with invalid socket type:%d", type);
768
+ return INVALID_SOCKET;
769
+ }
457
770
  SockToPolledFdMap* map = static_cast<SockToPolledFdMap*>(user_data);
458
771
  SOCKET s = WSASocket(af, type, protocol, nullptr, 0,
459
772
  grpc_get_default_wsa_socket_flags());
460
773
  if (s == INVALID_SOCKET) {
774
+ GRPC_CARES_TRACE_LOG(
775
+ "WSASocket failed with params af:%d type:%d protocol:%d", af, type,
776
+ protocol);
461
777
  return s;
462
778
  }
463
779
  grpc_tcp_set_non_block(s);
464
780
  GrpcPolledFdWindows* polled_fd =
465
- New<GrpcPolledFdWindows>(s, map->combiner_);
781
+ New<GrpcPolledFdWindows>(s, map->combiner_, af, type);
782
+ GRPC_CARES_TRACE_LOG(
783
+ "fd:|%s| created with params af:%d type:%d protocol:%d",
784
+ polled_fd->GetName(), af, type, protocol);
466
785
  map->AddNewSocket(s, polled_fd);
467
786
  return s;
468
787
  }
469
788
 
470
789
  static int Connect(ares_socket_t as, const struct sockaddr* target,
471
790
  ares_socklen_t target_len, void* user_data) {
791
+ WSAErrorContext wsa_error_ctx;
472
792
  SockToPolledFdMap* map = static_cast<SockToPolledFdMap*>(user_data);
473
793
  GrpcPolledFdWindows* polled_fd = map->LookupPolledFd(as);
474
- return polled_fd->Connect(target, target_len);
794
+ return polled_fd->Connect(&wsa_error_ctx, target, target_len);
475
795
  }
476
796
 
477
797
  static ares_ssize_t SendV(ares_socket_t as, const struct iovec* iov,
478
798
  int iovec_count, void* user_data) {
799
+ WSAErrorContext wsa_error_ctx;
479
800
  SockToPolledFdMap* map = static_cast<SockToPolledFdMap*>(user_data);
480
801
  GrpcPolledFdWindows* polled_fd = map->LookupPolledFd(as);
481
- return polled_fd->SendV(iov, iovec_count);
802
+ return polled_fd->SendV(&wsa_error_ctx, iov, iovec_count);
482
803
  }
483
804
 
484
805
  static ares_ssize_t RecvFrom(ares_socket_t as, void* data, size_t data_len,
485
806
  int flags, struct sockaddr* from,
486
807
  ares_socklen_t* from_len, void* user_data) {
808
+ WSAErrorContext wsa_error_ctx;
487
809
  SockToPolledFdMap* map = static_cast<SockToPolledFdMap*>(user_data);
488
810
  GrpcPolledFdWindows* polled_fd = map->LookupPolledFd(as);
489
- return polled_fd->RecvFrom(data, data_len, flags, from, from_len);
811
+ return polled_fd->RecvFrom(&wsa_error_ctx, data, data_len, flags, from,
812
+ from_len);
490
813
  }
491
814
 
492
815
  static int CloseSocket(SOCKET s, void* user_data) {