grpc 1.15.0 → 1.16.0.pre1
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.
- checksums.yaml +4 -4
- data/Makefile +158 -80
- data/etc/roots.pem +23 -0
- data/include/grpc/grpc.h +13 -1
- data/include/grpc/grpc_security.h +2 -2
- data/include/grpc/grpc_security_constants.h +24 -19
- data/include/grpc/impl/codegen/grpc_types.h +23 -5
- data/include/grpc/impl/codegen/port_platform.h +1 -0
- data/src/core/ext/filters/client_channel/client_channel.cc +95 -10
- data/src/core/ext/filters/client_channel/client_channel_channelz.cc +71 -0
- data/src/core/ext/filters/client_channel/client_channel_channelz.h +45 -11
- data/src/core/ext/filters/client_channel/connector.h +3 -0
- data/src/core/ext/filters/client_channel/http_connect_handshaker.cc +1 -1
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +5 -3
- data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +12 -32
- data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +6 -5
- data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +20 -15
- data/src/core/ext/filters/client_channel/lb_policy_factory.h +2 -4
- data/src/core/ext/filters/client_channel/parse_address.cc +27 -4
- data/src/core/ext/filters/client_channel/parse_address.h +3 -0
- data/src/core/ext/filters/client_channel/resolver.h +1 -12
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +1 -11
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +80 -19
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +9 -3
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc +5 -0
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +70 -0
- data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +1 -11
- data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +2 -16
- data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h +2 -1
- data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +0 -7
- data/src/core/ext/filters/client_channel/subchannel.cc +45 -7
- data/src/core/ext/filters/client_channel/subchannel.h +16 -1
- data/src/core/ext/filters/client_channel/subchannel_index.cc +2 -1
- data/src/core/ext/filters/client_channel/subchannel_index.h +1 -4
- data/src/core/ext/filters/http/client/http_client_filter.cc +32 -3
- data/src/core/ext/filters/http/server/http_server_filter.cc +59 -1
- data/src/core/ext/filters/max_age/max_age_filter.cc +1 -2
- data/src/core/ext/filters/message_size/message_size_filter.cc +59 -3
- data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +2 -0
- data/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc +1 -1
- data/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc +1 -1
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +286 -228
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +2 -0
- data/src/core/ext/transport/chttp2/transport/frame_data.cc +4 -0
- data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +14 -3
- data/src/core/ext/transport/chttp2/transport/hpack_table.cc +29 -0
- data/src/core/ext/transport/chttp2/transport/hpack_table.h +9 -0
- data/src/core/ext/transport/chttp2/transport/internal.h +10 -0
- data/src/core/ext/transport/chttp2/transport/parsing.cc +85 -54
- data/src/core/ext/transport/chttp2/transport/writing.cc +6 -0
- data/src/core/lib/channel/channel_trace.cc +51 -56
- data/src/core/lib/channel/channel_trace.h +30 -25
- data/src/core/lib/channel/channelz.cc +235 -61
- data/src/core/lib/channel/channelz.h +179 -48
- data/src/core/lib/channel/channelz_registry.cc +95 -23
- data/src/core/lib/channel/channelz_registry.h +15 -42
- data/src/core/lib/gpr/sync_posix.cc +42 -0
- data/src/core/lib/http/httpcli.cc +1 -1
- data/src/core/lib/iomgr/buffer_list.cc +134 -0
- data/src/core/lib/iomgr/buffer_list.h +96 -0
- data/src/core/lib/iomgr/endpoint.cc +2 -2
- data/src/core/lib/iomgr/endpoint.h +6 -2
- data/src/core/lib/iomgr/endpoint_pair_posix.cc +2 -2
- data/src/core/lib/iomgr/error.cc +29 -18
- data/src/core/lib/iomgr/error.h +8 -0
- data/src/core/lib/iomgr/ev_epoll1_linux.cc +4 -0
- data/src/core/lib/iomgr/ev_epollex_linux.cc +4 -0
- data/src/core/lib/iomgr/ev_posix.cc +16 -10
- data/src/core/lib/iomgr/exec_ctx.h +0 -7
- data/src/core/lib/iomgr/{ev_epollsig_linux.h → internal_errqueue.cc} +13 -12
- data/src/core/lib/iomgr/internal_errqueue.h +83 -0
- data/src/core/lib/iomgr/port.h +11 -2
- data/src/core/lib/iomgr/socket_utils_common_posix.cc +90 -0
- data/src/core/lib/iomgr/socket_utils_posix.h +7 -0
- data/src/core/lib/iomgr/tcp_client_posix.cc +4 -1
- data/src/core/lib/iomgr/tcp_custom.cc +1 -1
- data/src/core/lib/iomgr/tcp_posix.cc +306 -13
- data/src/core/lib/iomgr/tcp_posix.h +3 -0
- data/src/core/lib/iomgr/tcp_server_posix.cc +2 -2
- data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +4 -1
- data/src/core/lib/iomgr/tcp_windows.cc +1 -1
- data/src/core/lib/iomgr/timer_generic.cc +13 -12
- data/src/core/lib/iomgr/timer_heap.cc +2 -2
- data/src/core/lib/iomgr/timer_heap.h +3 -3
- data/src/core/lib/iomgr/timer_manager.cc +28 -3
- data/src/core/lib/iomgr/timer_manager.h +2 -2
- data/src/core/lib/iomgr/udp_server.cc +1 -1
- data/src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc +2 -1
- data/src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc +2 -1
- data/src/core/lib/security/security_connector/security_connector.cc +7 -7
- data/src/core/lib/security/transport/secure_endpoint.cc +2 -2
- data/src/core/lib/security/transport/security_handshaker.cc +1 -1
- data/src/core/lib/security/transport/server_auth_filter.cc +53 -4
- data/src/core/lib/slice/slice.cc +8 -0
- data/src/core/lib/slice/slice_internal.h +5 -0
- data/src/core/lib/surface/call.cc +149 -253
- data/src/core/lib/surface/call.h +1 -0
- data/src/core/lib/surface/channel.cc +17 -13
- data/src/core/lib/surface/completion_queue.cc +21 -17
- data/src/core/lib/surface/completion_queue.h +1 -18
- data/src/core/lib/surface/completion_queue_factory.cc +3 -3
- data/src/core/lib/surface/init_secure.cc +1 -1
- data/src/core/lib/surface/server.cc +77 -4
- data/src/core/lib/surface/server.h +4 -0
- data/src/core/lib/surface/version.cc +2 -2
- data/src/core/lib/transport/metadata.cc +0 -18
- data/src/core/lib/transport/metadata.h +0 -3
- data/src/core/lib/transport/metadata_batch.cc +2 -2
- data/src/core/lib/transport/metadata_batch.h +2 -0
- data/src/core/lib/transport/static_metadata.cc +220 -249
- data/src/core/lib/transport/static_metadata.h +189 -191
- data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +5 -4
- data/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc +3 -1
- data/src/core/tsi/alts/handshaker/alts_tsi_event.cc +4 -2
- data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +6 -5
- data/src/core/tsi/alts/handshaker/alts_tsi_utils.cc +3 -1
- data/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc +2 -2
- data/src/core/tsi/alts_transport_security.cc +3 -1
- data/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +2 -1
- data/src/ruby/ext/grpc/rb_call.c +1 -0
- data/src/ruby/ext/grpc/rb_channel.c +3 -0
- data/src/ruby/ext/grpc/rb_grpc.c +31 -1
- data/src/ruby/ext/grpc/rb_grpc.h +2 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +6 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +12 -3
- data/src/ruby/ext/grpc/rb_server.c +2 -0
- data/src/ruby/lib/grpc/errors.rb +0 -1
- data/src/ruby/lib/grpc/generic/rpc_desc.rb +3 -3
- data/src/ruby/lib/grpc/generic/rpc_server.rb +1 -1
- data/src/ruby/lib/grpc/version.rb +1 -1
- data/src/ruby/spec/channel_spec.rb +44 -0
- data/src/ruby/spec/client_auth_spec.rb +5 -5
- data/src/ruby/spec/generic/client_stub_spec.rb +13 -9
- data/src/ruby/spec/generic/rpc_server_spec.rb +3 -3
- data/src/ruby/spec/pb/codegen/package_option_spec.rb +53 -0
- data/src/ruby/spec/support/services.rb +28 -22
- metadata +35 -31
- data/src/core/lib/iomgr/ev_epollsig_linux.cc +0 -1743
@@ -273,6 +273,10 @@ static gpr_mu fork_fd_list_mu;
|
|
273
273
|
static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); }
|
274
274
|
|
275
275
|
static void fd_global_shutdown(void) {
|
276
|
+
// TODO(guantaol): We don't have a reasonable explanation about this
|
277
|
+
// lock()/unlock() pattern. It can be a valid barrier if there is at most one
|
278
|
+
// pending lock() at this point. Otherwise, there is still a possibility of
|
279
|
+
// use-after-free race. Need to reason about the code and/or clean it up.
|
276
280
|
gpr_mu_lock(&fd_freelist_mu);
|
277
281
|
gpr_mu_unlock(&fd_freelist_mu);
|
278
282
|
while (fd_freelist != nullptr) {
|
@@ -403,6 +403,10 @@ static void unref_by(grpc_fd* fd, int n) {
|
|
403
403
|
static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); }
|
404
404
|
|
405
405
|
static void fd_global_shutdown(void) {
|
406
|
+
// TODO(guantaol): We don't have a reasonable explanation about this
|
407
|
+
// lock()/unlock() pattern. It can be a valid barrier if there is at most one
|
408
|
+
// pending lock() at this point. Otherwise, there is still a possibility of
|
409
|
+
// use-after-free race. Need to reason about the code and/or clean it up.
|
406
410
|
gpr_mu_lock(&fd_freelist_mu);
|
407
411
|
gpr_mu_unlock(&fd_freelist_mu);
|
408
412
|
while (fd_freelist != nullptr) {
|
@@ -35,7 +35,6 @@
|
|
35
35
|
#include "src/core/lib/gpr/useful.h"
|
36
36
|
#include "src/core/lib/iomgr/ev_epoll1_linux.h"
|
37
37
|
#include "src/core/lib/iomgr/ev_epollex_linux.h"
|
38
|
-
#include "src/core/lib/iomgr/ev_epollsig_linux.h"
|
39
38
|
#include "src/core/lib/iomgr/ev_poll_posix.h"
|
40
39
|
|
41
40
|
grpc_core::TraceFlag grpc_polling_trace(false,
|
@@ -123,13 +122,13 @@ const grpc_event_engine_vtable* init_non_polling(bool explicit_request) {
|
|
123
122
|
// environment variable if that variable is set (which should be a
|
124
123
|
// comma-separated list of one or more event engine names)
|
125
124
|
static event_engine_factory g_factories[] = {
|
126
|
-
{ENGINE_HEAD_CUSTOM, nullptr},
|
127
|
-
{ENGINE_HEAD_CUSTOM, nullptr},
|
128
|
-
{"epollex", grpc_init_epollex_linux},
|
129
|
-
{"
|
130
|
-
{"
|
131
|
-
{ENGINE_TAIL_CUSTOM, nullptr},
|
132
|
-
{ENGINE_TAIL_CUSTOM, nullptr},
|
125
|
+
{ENGINE_HEAD_CUSTOM, nullptr}, {ENGINE_HEAD_CUSTOM, nullptr},
|
126
|
+
{ENGINE_HEAD_CUSTOM, nullptr}, {ENGINE_HEAD_CUSTOM, nullptr},
|
127
|
+
{"epollex", grpc_init_epollex_linux}, {"epoll1", grpc_init_epoll1_linux},
|
128
|
+
{"poll", grpc_init_poll_posix}, {"poll-cv", grpc_init_poll_cv_posix},
|
129
|
+
{"none", init_non_polling}, {ENGINE_TAIL_CUSTOM, nullptr},
|
130
|
+
{ENGINE_TAIL_CUSTOM, nullptr}, {ENGINE_TAIL_CUSTOM, nullptr},
|
131
|
+
{ENGINE_TAIL_CUSTOM, nullptr},
|
133
132
|
};
|
134
133
|
|
135
134
|
static void add(const char* beg, const char* end, char*** ss, size_t* ns) {
|
@@ -237,14 +236,19 @@ void grpc_event_engine_shutdown(void) {
|
|
237
236
|
}
|
238
237
|
|
239
238
|
bool grpc_event_engine_can_track_errors(void) {
|
239
|
+
/* Only track errors if platform supports errqueue. */
|
240
|
+
#ifdef GRPC_LINUX_ERRQUEUE
|
240
241
|
return g_event_engine->can_track_err;
|
242
|
+
#else
|
243
|
+
return false;
|
244
|
+
#endif /* GRPC_LINUX_ERRQUEUE */
|
241
245
|
}
|
242
246
|
|
243
247
|
grpc_fd* grpc_fd_create(int fd, const char* name, bool track_err) {
|
244
248
|
GRPC_POLLING_API_TRACE("fd_create(%d, %s, %d)", fd, name, track_err);
|
245
249
|
GRPC_FD_TRACE("fd_create(%d, %s, %d)", fd, name, track_err);
|
246
|
-
|
247
|
-
|
250
|
+
return g_event_engine->fd_create(fd, name,
|
251
|
+
track_err && g_event_engine->can_track_err);
|
248
252
|
}
|
249
253
|
|
250
254
|
int grpc_fd_wrapped_fd(grpc_fd* fd) {
|
@@ -391,4 +395,6 @@ void grpc_pollset_set_del_fd(grpc_pollset_set* pollset_set, grpc_fd* fd) {
|
|
391
395
|
g_event_engine->pollset_set_del_fd(pollset_set, fd);
|
392
396
|
}
|
393
397
|
|
398
|
+
void grpc_use_signal(int signum) {}
|
399
|
+
|
394
400
|
#endif // GRPC_POSIX_SOCKET_EV
|
@@ -116,12 +116,7 @@ class ExecCtx {
|
|
116
116
|
ExecCtx(const ExecCtx&) = delete;
|
117
117
|
ExecCtx& operator=(const ExecCtx&) = delete;
|
118
118
|
|
119
|
-
/** Return starting_cpu. This is only required for stats collection and is
|
120
|
-
* hence only defined if GRPC_COLLECT_STATS is enabled.
|
121
|
-
*/
|
122
|
-
#if defined(GRPC_COLLECT_STATS) || !defined(NDEBUG)
|
123
119
|
unsigned starting_cpu() const { return starting_cpu_; }
|
124
|
-
#endif /* defined(GRPC_COLLECT_STATS) || !defined(NDEBUG) */
|
125
120
|
|
126
121
|
struct CombinerData {
|
127
122
|
/* currently active combiner: updated only via combiner.c */
|
@@ -223,9 +218,7 @@ class ExecCtx {
|
|
223
218
|
CombinerData combiner_data_ = {nullptr, nullptr};
|
224
219
|
uintptr_t flags_;
|
225
220
|
|
226
|
-
#if defined(GRPC_COLLECT_STATS) || !defined(NDEBUG)
|
227
221
|
unsigned starting_cpu_ = gpr_cpu_current_cpu();
|
228
|
-
#endif /* defined(GRPC_COLLECT_STATS) || !defined(NDEBUG) */
|
229
222
|
|
230
223
|
bool now_is_valid_ = false;
|
231
224
|
grpc_millis now_ = 0;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
*
|
3
|
-
* Copyright
|
3
|
+
* Copyright 2018 gRPC authors.
|
4
4
|
*
|
5
5
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
* you may not use this file except in compliance with the License.
|
@@ -16,20 +16,21 @@
|
|
16
16
|
*
|
17
17
|
*/
|
18
18
|
|
19
|
-
#ifndef GRPC_CORE_LIB_IOMGR_EV_EPOLLSIG_LINUX_H
|
20
|
-
#define GRPC_CORE_LIB_IOMGR_EV_EPOLLSIG_LINUX_H
|
21
|
-
|
22
19
|
#include <grpc/support/port_platform.h>
|
23
20
|
|
24
|
-
#include "src/core/lib/iomgr/ev_posix.h"
|
25
21
|
#include "src/core/lib/iomgr/port.h"
|
26
22
|
|
27
|
-
|
23
|
+
#include "src/core/lib/iomgr/internal_errqueue.h"
|
24
|
+
|
25
|
+
#ifdef GRPC_POSIX_SOCKET_TCP
|
28
26
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
#endif /*
|
27
|
+
bool kernel_supports_errqueue() {
|
28
|
+
#ifdef LINUX_VERSION_CODE
|
29
|
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
|
30
|
+
return true;
|
31
|
+
#endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(4, 0, 0) */
|
32
|
+
#endif /* LINUX_VERSION_CODE */
|
33
|
+
return false;
|
34
|
+
}
|
34
35
|
|
35
|
-
#endif /*
|
36
|
+
#endif /* GRPC_POSIX_SOCKET_TCP */
|
@@ -0,0 +1,83 @@
|
|
1
|
+
/*
|
2
|
+
*
|
3
|
+
* Copyright 2018 gRPC authors.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*
|
17
|
+
*/
|
18
|
+
|
19
|
+
/* This file contains constants defined in <linux/errqueue.h> and
|
20
|
+
* <linux/net_tstamp.h> so as to allow collecting network timestamps in the
|
21
|
+
* kernel. This file allows tcp_posix.cc to compile on platforms that do not
|
22
|
+
* have <linux/errqueue.h> and <linux/net_tstamp.h>.
|
23
|
+
*/
|
24
|
+
|
25
|
+
#ifndef GRPC_CORE_LIB_IOMGR_INTERNAL_ERRQUEUE_H
|
26
|
+
#define GRPC_CORE_LIB_IOMGR_INTERNAL_ERRQUEUE_H
|
27
|
+
|
28
|
+
#include <grpc/support/port_platform.h>
|
29
|
+
|
30
|
+
#include "src/core/lib/iomgr/port.h"
|
31
|
+
|
32
|
+
#ifdef GRPC_POSIX_SOCKET_TCP
|
33
|
+
|
34
|
+
#include <sys/types.h>
|
35
|
+
#include <time.h>
|
36
|
+
|
37
|
+
#ifdef GRPC_LINUX_ERRQUEUE
|
38
|
+
#include <linux/errqueue.h>
|
39
|
+
#include <linux/net_tstamp.h>
|
40
|
+
#include <sys/socket.h>
|
41
|
+
#endif /* GRPC_LINUX_ERRQUEUE */
|
42
|
+
|
43
|
+
namespace grpc_core {
|
44
|
+
|
45
|
+
#ifdef GRPC_LINUX_ERRQUEUE
|
46
|
+
|
47
|
+
/* Redefining scm_timestamping in the same way that <linux/errqueue.h> defines
|
48
|
+
* it, so that code compiles on systems that don't have it. */
|
49
|
+
struct scm_timestamping {
|
50
|
+
struct timespec ts[3];
|
51
|
+
};
|
52
|
+
/* Also redefine timestamp types */
|
53
|
+
/* The timestamp type for when the driver passed skb to NIC, or HW. */
|
54
|
+
constexpr int SCM_TSTAMP_SND = 0;
|
55
|
+
/* The timestamp type for when data entered the packet scheduler. */
|
56
|
+
constexpr int SCM_TSTAMP_SCHED = 1;
|
57
|
+
/* The timestamp type for when data acknowledged by peer. */
|
58
|
+
constexpr int SCM_TSTAMP_ACK = 2;
|
59
|
+
/* Redefine required constants from <linux/net_tstamp.h> */
|
60
|
+
constexpr uint32_t SOF_TIMESTAMPING_TX_SOFTWARE = 1u << 1;
|
61
|
+
constexpr uint32_t SOF_TIMESTAMPING_SOFTWARE = 1u << 4;
|
62
|
+
constexpr uint32_t SOF_TIMESTAMPING_OPT_ID = 1u << 7;
|
63
|
+
constexpr uint32_t SOF_TIMESTAMPING_TX_SCHED = 1u << 8;
|
64
|
+
constexpr uint32_t SOF_TIMESTAMPING_TX_ACK = 1u << 9;
|
65
|
+
constexpr uint32_t SOF_TIMESTAMPING_OPT_TSONLY = 1u << 11;
|
66
|
+
|
67
|
+
constexpr uint32_t kTimestampingSocketOptions = SOF_TIMESTAMPING_SOFTWARE |
|
68
|
+
SOF_TIMESTAMPING_OPT_ID |
|
69
|
+
SOF_TIMESTAMPING_OPT_TSONLY;
|
70
|
+
constexpr uint32_t kTimestampingRecordingOptions =
|
71
|
+
SOF_TIMESTAMPING_TX_SCHED | SOF_TIMESTAMPING_TX_SOFTWARE |
|
72
|
+
SOF_TIMESTAMPING_TX_ACK;
|
73
|
+
#endif /* GRPC_LINUX_ERRQUEUE */
|
74
|
+
|
75
|
+
/* Returns true if kernel is capable of supporting errqueue and timestamping.
|
76
|
+
* Currently allowing only linux kernels above 4.0.0
|
77
|
+
*/
|
78
|
+
bool kernel_supports_errqueue();
|
79
|
+
} // namespace grpc_core
|
80
|
+
|
81
|
+
#endif /* GRPC_POSIX_SOCKET_TCP */
|
82
|
+
|
83
|
+
#endif /* GRPC_CORE_LIB_IOMGR_INTERNAL_ERRQUEUE_H */
|
data/src/core/lib/iomgr/port.h
CHANGED
@@ -60,6 +60,12 @@
|
|
60
60
|
#define GRPC_HAVE_IP_PKTINFO 1
|
61
61
|
#define GRPC_HAVE_MSG_NOSIGNAL 1
|
62
62
|
#define GRPC_HAVE_UNIX_SOCKET 1
|
63
|
+
#ifdef LINUX_VERSION_CODE
|
64
|
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
|
65
|
+
/* TODO(yashykt): Re-enable once Fathom changes are commited.
|
66
|
+
#define GRPC_LINUX_ERRQUEUE 1 */
|
67
|
+
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) */
|
68
|
+
#endif /* LINUX_VERSION_CODE */
|
63
69
|
#define GRPC_LINUX_MULTIPOLL_WITH_EPOLL 1
|
64
70
|
#define GRPC_POSIX_FORK 1
|
65
71
|
#define GRPC_POSIX_HOST_NAME_MAX 1
|
@@ -77,6 +83,11 @@
|
|
77
83
|
#define GRPC_LINUX_SOCKETUTILS 1
|
78
84
|
#endif
|
79
85
|
#endif
|
86
|
+
#ifdef LINUX_VERSION_CODE
|
87
|
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
|
88
|
+
#define GRPC_HAVE_TCP_USER_TIMEOUT
|
89
|
+
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) */
|
90
|
+
#endif /* LINUX_VERSION_CODE */
|
80
91
|
#ifndef __GLIBC__
|
81
92
|
#define GRPC_LINUX_EPOLL 1
|
82
93
|
#define GRPC_LINUX_EPOLL_CREATE1 1
|
@@ -105,7 +116,6 @@
|
|
105
116
|
#define GRPC_POSIX_SOCKET_EV 1
|
106
117
|
#define GRPC_POSIX_SOCKET_EV_EPOLL1 1
|
107
118
|
#define GRPC_POSIX_SOCKET_EV_EPOLLEX 1
|
108
|
-
#define GRPC_POSIX_SOCKET_EV_EPOLLSIG 1
|
109
119
|
#define GRPC_POSIX_SOCKET_EV_POLL 1
|
110
120
|
#define GRPC_POSIX_SOCKET_RESOLVE_ADDRESS 1
|
111
121
|
#define GRPC_POSIX_SOCKET_SOCKADDR 1
|
@@ -173,7 +183,6 @@
|
|
173
183
|
#define GRPC_POSIX_SOCKET_ARES_EV_DRIVER 1
|
174
184
|
#define GRPC_POSIX_SOCKET_EV 1
|
175
185
|
#define GRPC_POSIX_SOCKET_EV_EPOLLEX 1
|
176
|
-
#define GRPC_POSIX_SOCKET_EV_EPOLLSIG 1
|
177
186
|
#define GRPC_POSIX_SOCKET_EV_POLL 1
|
178
187
|
#define GRPC_POSIX_SOCKET_EV_EPOLL1 1
|
179
188
|
#define GRPC_POSIX_SOCKET_IOMGR 1
|
@@ -41,6 +41,7 @@
|
|
41
41
|
#include <grpc/support/log.h>
|
42
42
|
#include <grpc/support/sync.h>
|
43
43
|
|
44
|
+
#include "src/core/lib/channel/channel_args.h"
|
44
45
|
#include "src/core/lib/gpr/host_port.h"
|
45
46
|
#include "src/core/lib/gpr/string.h"
|
46
47
|
#include "src/core/lib/iomgr/sockaddr.h"
|
@@ -222,6 +223,95 @@ grpc_error* grpc_set_socket_low_latency(int fd, int low_latency) {
|
|
222
223
|
return GRPC_ERROR_NONE;
|
223
224
|
}
|
224
225
|
|
226
|
+
/* The default values for TCP_USER_TIMEOUT are currently configured to be in
|
227
|
+
* line with the default values of KEEPALIVE_TIMEOUT as proposed in
|
228
|
+
* https://github.com/grpc/proposal/blob/master/A18-tcp-user-timeout.md */
|
229
|
+
#define DEFAULT_CLIENT_TCP_USER_TIMEOUT_MS 20000 /* 20 seconds */
|
230
|
+
#define DEFAULT_SERVER_TCP_USER_TIMEOUT_MS 20000 /* 20 seconds */
|
231
|
+
|
232
|
+
static int g_default_client_tcp_user_timeout_ms =
|
233
|
+
DEFAULT_CLIENT_TCP_USER_TIMEOUT_MS;
|
234
|
+
static int g_default_server_tcp_user_timeout_ms =
|
235
|
+
DEFAULT_SERVER_TCP_USER_TIMEOUT_MS;
|
236
|
+
static bool g_default_client_tcp_user_timeout_enabled = false;
|
237
|
+
static bool g_default_server_tcp_user_timeout_enabled = true;
|
238
|
+
|
239
|
+
void config_default_tcp_user_timeout(bool enable, int timeout, bool is_client) {
|
240
|
+
if (is_client) {
|
241
|
+
g_default_client_tcp_user_timeout_enabled = enable;
|
242
|
+
if (timeout > 0) {
|
243
|
+
g_default_client_tcp_user_timeout_ms = timeout;
|
244
|
+
}
|
245
|
+
} else {
|
246
|
+
g_default_server_tcp_user_timeout_enabled = enable;
|
247
|
+
if (timeout > 0) {
|
248
|
+
g_default_server_tcp_user_timeout_ms = timeout;
|
249
|
+
}
|
250
|
+
}
|
251
|
+
}
|
252
|
+
|
253
|
+
/* Set TCP_USER_TIMEOUT */
|
254
|
+
grpc_error* grpc_set_socket_tcp_user_timeout(
|
255
|
+
int fd, const grpc_channel_args* channel_args, bool is_client) {
|
256
|
+
#ifdef GRPC_HAVE_TCP_USER_TIMEOUT
|
257
|
+
bool enable;
|
258
|
+
int timeout;
|
259
|
+
if (is_client) {
|
260
|
+
enable = g_default_client_tcp_user_timeout_enabled;
|
261
|
+
timeout = g_default_client_tcp_user_timeout_ms;
|
262
|
+
} else {
|
263
|
+
enable = g_default_server_tcp_user_timeout_enabled;
|
264
|
+
timeout = g_default_server_tcp_user_timeout_ms;
|
265
|
+
}
|
266
|
+
if (channel_args) {
|
267
|
+
for (unsigned int i = 0; i < channel_args->num_args; i++) {
|
268
|
+
if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_KEEPALIVE_TIME_MS)) {
|
269
|
+
const int value = grpc_channel_arg_get_integer(
|
270
|
+
&channel_args->args[i], grpc_integer_options{0, 1, INT_MAX});
|
271
|
+
/* Continue using default if value is 0 */
|
272
|
+
if (value == 0) {
|
273
|
+
continue;
|
274
|
+
}
|
275
|
+
/* Disable if value is INT_MAX */
|
276
|
+
enable = value != INT_MAX;
|
277
|
+
} else if (0 == strcmp(channel_args->args[i].key,
|
278
|
+
GRPC_ARG_KEEPALIVE_TIMEOUT_MS)) {
|
279
|
+
const int value = grpc_channel_arg_get_integer(
|
280
|
+
&channel_args->args[i], grpc_integer_options{0, 1, INT_MAX});
|
281
|
+
/* Continue using default if value is 0 */
|
282
|
+
if (value == 0) {
|
283
|
+
continue;
|
284
|
+
}
|
285
|
+
timeout = value;
|
286
|
+
}
|
287
|
+
}
|
288
|
+
}
|
289
|
+
if (enable) {
|
290
|
+
extern grpc_core::TraceFlag grpc_tcp_trace;
|
291
|
+
if (grpc_tcp_trace.enabled()) {
|
292
|
+
gpr_log(GPR_INFO, "Enabling TCP_USER_TIMEOUT with a timeout of %d ms",
|
293
|
+
timeout);
|
294
|
+
}
|
295
|
+
int newval;
|
296
|
+
socklen_t len = sizeof(newval);
|
297
|
+
if (0 != setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout,
|
298
|
+
sizeof(timeout))) {
|
299
|
+
return GRPC_OS_ERROR(errno, "setsockopt(TCP_USER_TIMEOUT)");
|
300
|
+
}
|
301
|
+
if (0 != getsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &newval, &len)) {
|
302
|
+
return GRPC_OS_ERROR(errno, "getsockopt(TCP_USER_TIMEOUT)");
|
303
|
+
}
|
304
|
+
if (newval != timeout) {
|
305
|
+
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
|
306
|
+
"Failed to set TCP_USER_TIMEOUT");
|
307
|
+
}
|
308
|
+
}
|
309
|
+
#else
|
310
|
+
gpr_log(GPR_INFO, "TCP_USER_TIMEOUT not supported for this platform");
|
311
|
+
#endif /* GRPC_HAVE_TCP_USER_TIMEOUT */
|
312
|
+
return GRPC_ERROR_NONE;
|
313
|
+
}
|
314
|
+
|
225
315
|
/* set a socket using a grpc_socket_mutator */
|
226
316
|
grpc_error* grpc_set_socket_with_mutator(int fd, grpc_socket_mutator* mutator) {
|
227
317
|
GPR_ASSERT(mutator);
|
@@ -53,6 +53,13 @@ grpc_error* grpc_set_socket_low_latency(int fd, int low_latency);
|
|
53
53
|
/* set SO_REUSEPORT */
|
54
54
|
grpc_error* grpc_set_socket_reuse_port(int fd, int reuse);
|
55
55
|
|
56
|
+
/* Configure the default values for TCP_USER_TIMEOUT */
|
57
|
+
void config_default_tcp_user_timeout(bool enable, int timeout, bool is_client);
|
58
|
+
|
59
|
+
/* Set TCP_USER_TIMEOUT */
|
60
|
+
grpc_error* grpc_set_socket_tcp_user_timeout(
|
61
|
+
int fd, const grpc_channel_args* channel_args, bool is_client);
|
62
|
+
|
56
63
|
/* Returns true if this system can create AF_INET6 sockets bound to ::1.
|
57
64
|
The value is probed once, and cached for the life of the process.
|
58
65
|
|
@@ -76,6 +76,9 @@ static grpc_error* prepare_socket(const grpc_resolved_address* addr, int fd,
|
|
76
76
|
if (!grpc_is_unix_socket(addr)) {
|
77
77
|
err = grpc_set_socket_low_latency(fd, 1);
|
78
78
|
if (err != GRPC_ERROR_NONE) goto error;
|
79
|
+
err = grpc_set_socket_tcp_user_timeout(fd, channel_args,
|
80
|
+
true /* is_client */);
|
81
|
+
if (err != GRPC_ERROR_NONE) goto error;
|
79
82
|
}
|
80
83
|
err = grpc_set_socket_no_sigpipe_if_possible(fd);
|
81
84
|
if (err != GRPC_ERROR_NONE) goto error;
|
@@ -279,7 +282,7 @@ grpc_error* grpc_tcp_client_prepare_fd(const grpc_channel_args* channel_args,
|
|
279
282
|
}
|
280
283
|
addr_str = grpc_sockaddr_to_uri(mapped_addr);
|
281
284
|
gpr_asprintf(&name, "tcp-client:%s", addr_str);
|
282
|
-
*fdobj = grpc_fd_create(fd, name,
|
285
|
+
*fdobj = grpc_fd_create(fd, name, true);
|
283
286
|
gpr_free(name);
|
284
287
|
gpr_free(addr_str);
|
285
288
|
return GRPC_ERROR_NONE;
|
@@ -221,7 +221,7 @@ static void custom_write_callback(grpc_custom_socket* socket,
|
|
221
221
|
}
|
222
222
|
|
223
223
|
static void endpoint_write(grpc_endpoint* ep, grpc_slice_buffer* write_slices,
|
224
|
-
grpc_closure* cb) {
|
224
|
+
grpc_closure* cb, void* arg) {
|
225
225
|
custom_tcp_endpoint* tcp = (custom_tcp_endpoint*)ep;
|
226
226
|
GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD();
|
227
227
|
|
@@ -27,7 +27,9 @@
|
|
27
27
|
|
28
28
|
#include <errno.h>
|
29
29
|
#include <limits.h>
|
30
|
+
#include <netinet/in.h>
|
30
31
|
#include <stdbool.h>
|
32
|
+
#include <stdio.h>
|
31
33
|
#include <stdlib.h>
|
32
34
|
#include <string.h>
|
33
35
|
#include <sys/socket.h>
|
@@ -46,6 +48,7 @@
|
|
46
48
|
#include "src/core/lib/debug/trace.h"
|
47
49
|
#include "src/core/lib/gpr/string.h"
|
48
50
|
#include "src/core/lib/gpr/useful.h"
|
51
|
+
#include "src/core/lib/iomgr/buffer_list.h"
|
49
52
|
#include "src/core/lib/iomgr/ev_posix.h"
|
50
53
|
#include "src/core/lib/iomgr/executor.h"
|
51
54
|
#include "src/core/lib/profiling/timers.h"
|
@@ -97,17 +100,42 @@ struct grpc_tcp {
|
|
97
100
|
|
98
101
|
grpc_closure read_done_closure;
|
99
102
|
grpc_closure write_done_closure;
|
103
|
+
grpc_closure error_closure;
|
100
104
|
|
101
105
|
char* peer_string;
|
102
106
|
|
103
107
|
grpc_resource_user* resource_user;
|
104
108
|
grpc_resource_user_slice_allocator slice_allocator;
|
109
|
+
|
110
|
+
grpc_core::TracedBuffer* tb_head; /* List of traced buffers */
|
111
|
+
gpr_mu tb_mu; /* Lock for access to list of traced buffers */
|
112
|
+
|
113
|
+
/* grpc_endpoint_write takes an argument which if non-null means that the
|
114
|
+
* transport layer wants the TCP layer to collect timestamps for this write.
|
115
|
+
* This arg is forwarded to the timestamps callback function when the ACK
|
116
|
+
* timestamp is received from the kernel. This arg is a (void *) which allows
|
117
|
+
* users of this API to pass in a pointer to any kind of structure. This
|
118
|
+
* structure could actually be a tag or any book-keeping object that the user
|
119
|
+
* can use to distinguish between different traced writes. The only
|
120
|
+
* requirement from the TCP endpoint layer is that this arg should be non-null
|
121
|
+
* if the user wants timestamps for the write. */
|
122
|
+
void* outgoing_buffer_arg;
|
123
|
+
/* A counter which starts at 0. It is initialized the first time the socket
|
124
|
+
* options for collecting timestamps are set, and is incremented with each
|
125
|
+
* byte sent. */
|
126
|
+
int bytes_counter;
|
127
|
+
bool socket_ts_enabled; /* True if timestamping options are set on the socket
|
128
|
+
*/
|
129
|
+
gpr_atm
|
130
|
+
stop_error_notification; /* Set to 1 if we do not want to be notified on
|
131
|
+
errors anymore */
|
105
132
|
};
|
106
133
|
|
107
134
|
struct backup_poller {
|
108
135
|
gpr_mu* pollset_mu;
|
109
136
|
grpc_closure run_poller;
|
110
137
|
};
|
138
|
+
|
111
139
|
} // namespace
|
112
140
|
|
113
141
|
#define BACKUP_POLLER_POLLSET(b) ((grpc_pollset*)((b) + 1))
|
@@ -176,6 +204,13 @@ static void drop_uncovered(grpc_tcp* tcp) {
|
|
176
204
|
GPR_ASSERT(old_count != 1);
|
177
205
|
}
|
178
206
|
|
207
|
+
// gRPC API considers a Write operation to be done the moment it clears ‘flow
|
208
|
+
// control’ i.e., not necessarily sent on the wire. This means that the
|
209
|
+
// application MIGHT not call `grpc_completion_queue_next/pluck` in a timely
|
210
|
+
// manner when its `Write()` API is acked.
|
211
|
+
//
|
212
|
+
// We need to ensure that the fd is 'covered' (i.e being monitored by some
|
213
|
+
// polling thread and progress is made) and hence add it to a backup poller here
|
179
214
|
static void cover_self(grpc_tcp* tcp) {
|
180
215
|
backup_poller* p;
|
181
216
|
gpr_atm old_count =
|
@@ -302,6 +337,7 @@ static void tcp_free(grpc_tcp* tcp) {
|
|
302
337
|
grpc_slice_buffer_destroy_internal(&tcp->last_read_buffer);
|
303
338
|
grpc_resource_user_unref(tcp->resource_user);
|
304
339
|
gpr_free(tcp->peer_string);
|
340
|
+
gpr_mu_destroy(&tcp->tb_mu);
|
305
341
|
gpr_free(tcp);
|
306
342
|
}
|
307
343
|
|
@@ -347,6 +383,10 @@ static void tcp_destroy(grpc_endpoint* ep) {
|
|
347
383
|
grpc_network_status_unregister_endpoint(ep);
|
348
384
|
grpc_tcp* tcp = reinterpret_cast<grpc_tcp*>(ep);
|
349
385
|
grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer);
|
386
|
+
if (grpc_event_engine_can_track_errors()) {
|
387
|
+
gpr_atm_no_barrier_store(&tcp->stop_error_notification, true);
|
388
|
+
grpc_fd_set_error(tcp->em_fd);
|
389
|
+
}
|
350
390
|
TCP_UNREF(tcp, "destroy");
|
351
391
|
}
|
352
392
|
|
@@ -513,6 +553,235 @@ static void tcp_read(grpc_endpoint* ep, grpc_slice_buffer* incoming_buffer,
|
|
513
553
|
}
|
514
554
|
}
|
515
555
|
|
556
|
+
/* A wrapper around sendmsg. It sends \a msg over \a fd and returns the number
|
557
|
+
* of bytes sent. */
|
558
|
+
ssize_t tcp_send(int fd, const struct msghdr* msg) {
|
559
|
+
GPR_TIMER_SCOPE("sendmsg", 1);
|
560
|
+
ssize_t sent_length;
|
561
|
+
do {
|
562
|
+
/* TODO(klempner): Cork if this is a partial write */
|
563
|
+
GRPC_STATS_INC_SYSCALL_WRITE();
|
564
|
+
sent_length = sendmsg(fd, msg, SENDMSG_FLAGS);
|
565
|
+
} while (sent_length < 0 && errno == EINTR);
|
566
|
+
return sent_length;
|
567
|
+
}
|
568
|
+
|
569
|
+
/** This is to be called if outgoing_buffer_arg is not null. On linux platforms,
|
570
|
+
* this will call sendmsg with socket options set to collect timestamps inside
|
571
|
+
* the kernel. On return, sent_length is set to the return value of the sendmsg
|
572
|
+
* call. Returns false if setting the socket options failed. This is not
|
573
|
+
* implemented for non-linux platforms currently, and crashes out.
|
574
|
+
*/
|
575
|
+
static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg,
|
576
|
+
size_t sending_length,
|
577
|
+
ssize_t* sent_length, grpc_error** error);
|
578
|
+
|
579
|
+
/** The callback function to be invoked when we get an error on the socket. */
|
580
|
+
static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error);
|
581
|
+
|
582
|
+
#ifdef GRPC_LINUX_ERRQUEUE
|
583
|
+
static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg,
|
584
|
+
size_t sending_length,
|
585
|
+
ssize_t* sent_length,
|
586
|
+
grpc_error** error) {
|
587
|
+
if (!tcp->socket_ts_enabled) {
|
588
|
+
uint32_t opt = grpc_core::kTimestampingSocketOptions;
|
589
|
+
if (setsockopt(tcp->fd, SOL_SOCKET, SO_TIMESTAMPING,
|
590
|
+
static_cast<void*>(&opt), sizeof(opt)) != 0) {
|
591
|
+
*error = tcp_annotate_error(GRPC_OS_ERROR(errno, "setsockopt"), tcp);
|
592
|
+
grpc_slice_buffer_reset_and_unref_internal(tcp->outgoing_buffer);
|
593
|
+
if (grpc_tcp_trace.enabled()) {
|
594
|
+
gpr_log(GPR_ERROR, "Failed to set timestamping options on the socket.");
|
595
|
+
}
|
596
|
+
return false;
|
597
|
+
}
|
598
|
+
tcp->bytes_counter = -1;
|
599
|
+
tcp->socket_ts_enabled = true;
|
600
|
+
}
|
601
|
+
/* Set control message to indicate that you want timestamps. */
|
602
|
+
union {
|
603
|
+
char cmsg_buf[CMSG_SPACE(sizeof(uint32_t))];
|
604
|
+
struct cmsghdr align;
|
605
|
+
} u;
|
606
|
+
cmsghdr* cmsg = reinterpret_cast<cmsghdr*>(u.cmsg_buf);
|
607
|
+
cmsg->cmsg_level = SOL_SOCKET;
|
608
|
+
cmsg->cmsg_type = SO_TIMESTAMPING;
|
609
|
+
cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t));
|
610
|
+
*reinterpret_cast<int*>(CMSG_DATA(cmsg)) =
|
611
|
+
grpc_core::kTimestampingRecordingOptions;
|
612
|
+
msg->msg_control = u.cmsg_buf;
|
613
|
+
msg->msg_controllen = CMSG_SPACE(sizeof(uint32_t));
|
614
|
+
|
615
|
+
/* If there was an error on sendmsg the logic in tcp_flush will handle it. */
|
616
|
+
ssize_t length = tcp_send(tcp->fd, msg);
|
617
|
+
*sent_length = length;
|
618
|
+
/* Only save timestamps if all the bytes were taken by sendmsg. */
|
619
|
+
if (sending_length == static_cast<size_t>(length)) {
|
620
|
+
gpr_mu_lock(&tcp->tb_mu);
|
621
|
+
grpc_core::TracedBuffer::AddNewEntry(
|
622
|
+
&tcp->tb_head, static_cast<int>(tcp->bytes_counter + length),
|
623
|
+
tcp->outgoing_buffer_arg);
|
624
|
+
gpr_mu_unlock(&tcp->tb_mu);
|
625
|
+
tcp->outgoing_buffer_arg = nullptr;
|
626
|
+
}
|
627
|
+
return true;
|
628
|
+
}
|
629
|
+
|
630
|
+
/** Reads \a cmsg to derive timestamps from the control messages. If a valid
|
631
|
+
* timestamp is found, the traced buffer list is updated with this timestamp.
|
632
|
+
* The caller of this function should be looping on the control messages found
|
633
|
+
* in \a msg. \a cmsg should point to the control message that the caller wants
|
634
|
+
* processed.
|
635
|
+
* On return, a pointer to a control message is returned. On the next iteration,
|
636
|
+
* CMSG_NXTHDR(msg, ret_val) should be passed as \a cmsg. */
|
637
|
+
struct cmsghdr* process_timestamp(grpc_tcp* tcp, msghdr* msg,
|
638
|
+
struct cmsghdr* cmsg) {
|
639
|
+
auto next_cmsg = CMSG_NXTHDR(msg, cmsg);
|
640
|
+
if (next_cmsg == nullptr) {
|
641
|
+
if (grpc_tcp_trace.enabled()) {
|
642
|
+
gpr_log(GPR_ERROR, "Received timestamp without extended error");
|
643
|
+
}
|
644
|
+
return cmsg;
|
645
|
+
}
|
646
|
+
|
647
|
+
if (!(next_cmsg->cmsg_level == SOL_IP || next_cmsg->cmsg_level == SOL_IPV6) ||
|
648
|
+
!(next_cmsg->cmsg_type == IP_RECVERR ||
|
649
|
+
next_cmsg->cmsg_type == IPV6_RECVERR)) {
|
650
|
+
if (grpc_tcp_trace.enabled()) {
|
651
|
+
gpr_log(GPR_ERROR, "Unexpected control message");
|
652
|
+
}
|
653
|
+
return cmsg;
|
654
|
+
}
|
655
|
+
|
656
|
+
auto tss =
|
657
|
+
reinterpret_cast<struct grpc_core::scm_timestamping*>(CMSG_DATA(cmsg));
|
658
|
+
auto serr = reinterpret_cast<struct sock_extended_err*>(CMSG_DATA(next_cmsg));
|
659
|
+
if (serr->ee_errno != ENOMSG ||
|
660
|
+
serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) {
|
661
|
+
gpr_log(GPR_ERROR, "Unexpected control message");
|
662
|
+
return cmsg;
|
663
|
+
}
|
664
|
+
/* The error handling can potentially be done on another thread so we need
|
665
|
+
* to protect the traced buffer list. A lock free list might be better. Using
|
666
|
+
* a simple mutex for now. */
|
667
|
+
gpr_mu_lock(&tcp->tb_mu);
|
668
|
+
grpc_core::TracedBuffer::ProcessTimestamp(&tcp->tb_head, serr, tss);
|
669
|
+
gpr_mu_unlock(&tcp->tb_mu);
|
670
|
+
return next_cmsg;
|
671
|
+
}
|
672
|
+
|
673
|
+
/** For linux platforms, reads the socket's error queue and processes error
|
674
|
+
* messages from the queue. Returns true if all the errors processed were
|
675
|
+
* timestamps. Returns false if any of the errors were not timestamps. For
|
676
|
+
* non-linux platforms, error processing is not used/enabled currently.
|
677
|
+
*/
|
678
|
+
static bool process_errors(grpc_tcp* tcp) {
|
679
|
+
while (true) {
|
680
|
+
struct iovec iov;
|
681
|
+
iov.iov_base = nullptr;
|
682
|
+
iov.iov_len = 0;
|
683
|
+
struct msghdr msg;
|
684
|
+
msg.msg_name = nullptr;
|
685
|
+
msg.msg_namelen = 0;
|
686
|
+
msg.msg_iov = &iov;
|
687
|
+
msg.msg_iovlen = 0;
|
688
|
+
msg.msg_flags = 0;
|
689
|
+
|
690
|
+
union {
|
691
|
+
char rbuf[1024 /*CMSG_SPACE(sizeof(scm_timestamping)) +
|
692
|
+
CMSG_SPACE(sizeof(sock_extended_err) + sizeof(sockaddr_in))*/];
|
693
|
+
struct cmsghdr align;
|
694
|
+
} aligned_buf;
|
695
|
+
memset(&aligned_buf, 0, sizeof(aligned_buf));
|
696
|
+
|
697
|
+
msg.msg_control = aligned_buf.rbuf;
|
698
|
+
msg.msg_controllen = sizeof(aligned_buf.rbuf);
|
699
|
+
|
700
|
+
int r, saved_errno;
|
701
|
+
do {
|
702
|
+
r = recvmsg(tcp->fd, &msg, MSG_ERRQUEUE);
|
703
|
+
saved_errno = errno;
|
704
|
+
} while (r < 0 && saved_errno == EINTR);
|
705
|
+
|
706
|
+
if (r == -1 && saved_errno == EAGAIN) {
|
707
|
+
return true; /* No more errors to process */
|
708
|
+
}
|
709
|
+
if (r == -1) {
|
710
|
+
return false;
|
711
|
+
}
|
712
|
+
if (grpc_tcp_trace.enabled()) {
|
713
|
+
if ((msg.msg_flags & MSG_CTRUNC) == 1) {
|
714
|
+
gpr_log(GPR_INFO, "Error message was truncated.");
|
715
|
+
}
|
716
|
+
}
|
717
|
+
|
718
|
+
if (msg.msg_controllen == 0) {
|
719
|
+
/* There was no control message found. It was probably spurious. */
|
720
|
+
return true;
|
721
|
+
}
|
722
|
+
for (auto cmsg = CMSG_FIRSTHDR(&msg); cmsg && cmsg->cmsg_len;
|
723
|
+
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
724
|
+
if (cmsg->cmsg_level != SOL_SOCKET ||
|
725
|
+
cmsg->cmsg_type != SCM_TIMESTAMPING) {
|
726
|
+
/* Got a control message that is not a timestamp. Don't know how to
|
727
|
+
* handle this. */
|
728
|
+
if (grpc_tcp_trace.enabled()) {
|
729
|
+
gpr_log(GPR_INFO,
|
730
|
+
"unknown control message cmsg_level:%d cmsg_type:%d",
|
731
|
+
cmsg->cmsg_level, cmsg->cmsg_type);
|
732
|
+
}
|
733
|
+
return false;
|
734
|
+
}
|
735
|
+
process_timestamp(tcp, &msg, cmsg);
|
736
|
+
}
|
737
|
+
}
|
738
|
+
}
|
739
|
+
|
740
|
+
static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error) {
|
741
|
+
grpc_tcp* tcp = static_cast<grpc_tcp*>(arg);
|
742
|
+
if (grpc_tcp_trace.enabled()) {
|
743
|
+
gpr_log(GPR_INFO, "TCP:%p got_error: %s", tcp, grpc_error_string(error));
|
744
|
+
}
|
745
|
+
|
746
|
+
if (error != GRPC_ERROR_NONE ||
|
747
|
+
static_cast<bool>(gpr_atm_acq_load(&tcp->stop_error_notification))) {
|
748
|
+
/* We aren't going to register to hear on error anymore, so it is safe to
|
749
|
+
* unref. */
|
750
|
+
grpc_core::TracedBuffer::Shutdown(&tcp->tb_head, GRPC_ERROR_REF(error));
|
751
|
+
TCP_UNREF(tcp, "error-tracking");
|
752
|
+
return;
|
753
|
+
}
|
754
|
+
|
755
|
+
/* We are still interested in collecting timestamps, so let's try reading
|
756
|
+
* them. */
|
757
|
+
if (!process_errors(tcp)) {
|
758
|
+
/* This was not a timestamps error. This was an actual error. Set the
|
759
|
+
* read and write closures to be ready.
|
760
|
+
*/
|
761
|
+
grpc_fd_set_readable(tcp->em_fd);
|
762
|
+
grpc_fd_set_writable(tcp->em_fd);
|
763
|
+
}
|
764
|
+
GRPC_CLOSURE_INIT(&tcp->error_closure, tcp_handle_error, tcp,
|
765
|
+
grpc_schedule_on_exec_ctx);
|
766
|
+
grpc_fd_notify_on_error(tcp->em_fd, &tcp->error_closure);
|
767
|
+
}
|
768
|
+
|
769
|
+
#else /* GRPC_LINUX_ERRQUEUE */
|
770
|
+
static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg,
|
771
|
+
size_t sending_length,
|
772
|
+
ssize_t* sent_length,
|
773
|
+
grpc_error** error) {
|
774
|
+
gpr_log(GPR_ERROR, "Write with timestamps not supported for this platform");
|
775
|
+
GPR_ASSERT(0);
|
776
|
+
return false;
|
777
|
+
}
|
778
|
+
|
779
|
+
static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error) {
|
780
|
+
gpr_log(GPR_ERROR, "Error handling is not supported for this platform");
|
781
|
+
GPR_ASSERT(0);
|
782
|
+
}
|
783
|
+
#endif /* GRPC_LINUX_ERRQUEUE */
|
784
|
+
|
516
785
|
/* returns true if done, false if pending; if returning true, *error is set */
|
517
786
|
#if defined(IOV_MAX) && IOV_MAX < 1000
|
518
787
|
#define MAX_WRITE_IOVEC IOV_MAX
|
@@ -557,19 +826,20 @@ static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) {
|
|
557
826
|
msg.msg_namelen = 0;
|
558
827
|
msg.msg_iov = iov;
|
559
828
|
msg.msg_iovlen = iov_size;
|
560
|
-
msg.msg_control = nullptr;
|
561
|
-
msg.msg_controllen = 0;
|
562
829
|
msg.msg_flags = 0;
|
830
|
+
if (tcp->outgoing_buffer_arg != nullptr) {
|
831
|
+
if (!tcp_write_with_timestamps(tcp, &msg, sending_length, &sent_length,
|
832
|
+
error))
|
833
|
+
return true; /* something went wrong with timestamps */
|
834
|
+
} else {
|
835
|
+
msg.msg_control = nullptr;
|
836
|
+
msg.msg_controllen = 0;
|
563
837
|
|
564
|
-
|
565
|
-
|
838
|
+
GRPC_STATS_INC_TCP_WRITE_SIZE(sending_length);
|
839
|
+
GRPC_STATS_INC_TCP_WRITE_IOV_SIZE(iov_size);
|
566
840
|
|
567
|
-
|
568
|
-
|
569
|
-
/* TODO(klempner): Cork if this is a partial write */
|
570
|
-
GRPC_STATS_INC_SYSCALL_WRITE();
|
571
|
-
sent_length = sendmsg(tcp->fd, &msg, SENDMSG_FLAGS);
|
572
|
-
} while (sent_length < 0 && errno == EINTR);
|
841
|
+
sent_length = tcp_send(tcp->fd, &msg);
|
842
|
+
}
|
573
843
|
|
574
844
|
if (sent_length < 0) {
|
575
845
|
if (errno == EAGAIN) {
|
@@ -593,6 +863,7 @@ static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) {
|
|
593
863
|
}
|
594
864
|
|
595
865
|
GPR_ASSERT(tcp->outgoing_byte_idx == 0);
|
866
|
+
tcp->bytes_counter += sent_length;
|
596
867
|
trailing = sending_length - static_cast<size_t>(sent_length);
|
597
868
|
while (trailing > 0) {
|
598
869
|
size_t slice_length;
|
@@ -607,7 +878,6 @@ static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) {
|
|
607
878
|
trailing -= slice_length;
|
608
879
|
}
|
609
880
|
}
|
610
|
-
|
611
881
|
if (outgoing_slice_idx == tcp->outgoing_buffer->count) {
|
612
882
|
*error = GRPC_ERROR_NONE;
|
613
883
|
grpc_slice_buffer_reset_and_unref_internal(tcp->outgoing_buffer);
|
@@ -640,14 +910,13 @@ static void tcp_handle_write(void* arg /* grpc_tcp */, grpc_error* error) {
|
|
640
910
|
const char* str = grpc_error_string(error);
|
641
911
|
gpr_log(GPR_INFO, "write: %s", str);
|
642
912
|
}
|
643
|
-
|
644
913
|
GRPC_CLOSURE_SCHED(cb, error);
|
645
914
|
TCP_UNREF(tcp, "write");
|
646
915
|
}
|
647
916
|
}
|
648
917
|
|
649
918
|
static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf,
|
650
|
-
grpc_closure* cb) {
|
919
|
+
grpc_closure* cb, void* arg) {
|
651
920
|
GPR_TIMER_SCOPE("tcp_write", 0);
|
652
921
|
grpc_tcp* tcp = reinterpret_cast<grpc_tcp*>(ep);
|
653
922
|
grpc_error* error = GRPC_ERROR_NONE;
|
@@ -675,6 +944,10 @@ static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf,
|
|
675
944
|
}
|
676
945
|
tcp->outgoing_buffer = buf;
|
677
946
|
tcp->outgoing_byte_idx = 0;
|
947
|
+
tcp->outgoing_buffer_arg = arg;
|
948
|
+
if (arg) {
|
949
|
+
GPR_ASSERT(grpc_event_engine_can_track_errors());
|
950
|
+
}
|
678
951
|
|
679
952
|
if (!tcp_flush(tcp, &error)) {
|
680
953
|
TCP_REF(tcp, "write");
|
@@ -792,6 +1065,8 @@ grpc_endpoint* grpc_tcp_create(grpc_fd* em_fd,
|
|
792
1065
|
tcp->bytes_read_this_round = 0;
|
793
1066
|
/* Will be set to false by the very first endpoint read function */
|
794
1067
|
tcp->is_first_read = true;
|
1068
|
+
tcp->bytes_counter = -1;
|
1069
|
+
tcp->socket_ts_enabled = false;
|
795
1070
|
/* paired with unref in grpc_tcp_destroy */
|
796
1071
|
gpr_ref_init(&tcp->refcount, 1);
|
797
1072
|
gpr_atm_no_barrier_store(&tcp->shutdown_count, 0);
|
@@ -803,6 +1078,19 @@ grpc_endpoint* grpc_tcp_create(grpc_fd* em_fd,
|
|
803
1078
|
/* Tell network status tracker about new endpoint */
|
804
1079
|
grpc_network_status_register_endpoint(&tcp->base);
|
805
1080
|
grpc_resource_quota_unref_internal(resource_quota);
|
1081
|
+
gpr_mu_init(&tcp->tb_mu);
|
1082
|
+
tcp->tb_head = nullptr;
|
1083
|
+
/* Start being notified on errors if event engine can track errors. */
|
1084
|
+
if (grpc_event_engine_can_track_errors()) {
|
1085
|
+
/* Grab a ref to tcp so that we can safely access the tcp struct when
|
1086
|
+
* processing errors. We unref when we no longer want to track errors
|
1087
|
+
* separately. */
|
1088
|
+
TCP_REF(tcp, "error-tracking");
|
1089
|
+
gpr_atm_rel_store(&tcp->stop_error_notification, 0);
|
1090
|
+
GRPC_CLOSURE_INIT(&tcp->error_closure, tcp_handle_error, tcp,
|
1091
|
+
grpc_schedule_on_exec_ctx);
|
1092
|
+
grpc_fd_notify_on_error(tcp->em_fd, &tcp->error_closure);
|
1093
|
+
}
|
806
1094
|
|
807
1095
|
return &tcp->base;
|
808
1096
|
}
|
@@ -821,6 +1109,11 @@ void grpc_tcp_destroy_and_release_fd(grpc_endpoint* ep, int* fd,
|
|
821
1109
|
tcp->release_fd = fd;
|
822
1110
|
tcp->release_fd_cb = done;
|
823
1111
|
grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer);
|
1112
|
+
if (grpc_event_engine_can_track_errors()) {
|
1113
|
+
/* Stop errors notification. */
|
1114
|
+
gpr_atm_no_barrier_store(&tcp->stop_error_notification, true);
|
1115
|
+
grpc_fd_set_error(tcp->em_fd);
|
1116
|
+
}
|
824
1117
|
TCP_UNREF(tcp, "destroy");
|
825
1118
|
}
|
826
1119
|
|