blob: 7c21b44e76ceaaceb3e3d831ffed76538fa030b2 [file] [log] [blame]
murgatroid999030c812016-09-16 13:25:08 -07001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2016 gRPC authors.
murgatroid999030c812016-09-16 13:25:08 -07004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * 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
murgatroid999030c812016-09-16 13:25:08 -07008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
murgatroid999030c812016-09-16 13:25:08 -070010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * 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.
murgatroid999030c812016-09-16 13:25:08 -070016 *
17 */
18
19#include "src/core/lib/iomgr/port.h"
20
21#ifdef GRPC_UV
22
23#include <limits.h>
24#include <string.h>
25
murgatroid99e2672c92016-11-09 15:12:22 -080026#include <grpc/slice_buffer.h>
27
murgatroid999030c812016-09-16 13:25:08 -070028#include <grpc/support/alloc.h>
29#include <grpc/support/log.h>
murgatroid999030c812016-09-16 13:25:08 -070030#include <grpc/support/string_util.h>
31
32#include "src/core/lib/iomgr/error.h"
33#include "src/core/lib/iomgr/network_status_tracker.h"
murgatroid99e2672c92016-11-09 15:12:22 -080034#include "src/core/lib/iomgr/resource_quota.h"
murgatroid999030c812016-09-16 13:25:08 -070035#include "src/core/lib/iomgr/tcp_uv.h"
Craig Tiller7c70b6c2017-01-23 07:48:42 -080036#include "src/core/lib/slice/slice_internal.h"
murgatroid99e2672c92016-11-09 15:12:22 -080037#include "src/core/lib/slice/slice_string_helpers.h"
murgatroid999030c812016-09-16 13:25:08 -070038#include "src/core/lib/support/string.h"
39
Craig Tiller020176d2017-05-09 08:36:44 -070040grpc_tracer_flag grpc_tcp_trace = GRPC_TRACER_INITIALIZER(false);
murgatroid999030c812016-09-16 13:25:08 -070041
42typedef struct {
43 grpc_endpoint base;
44 gpr_refcount refcount;
45
murgatroid9969259d42016-10-31 14:34:10 -070046 uv_write_t write_req;
47 uv_shutdown_t shutdown_req;
48
murgatroid999030c812016-09-16 13:25:08 -070049 uv_tcp_t *handle;
50
51 grpc_closure *read_cb;
52 grpc_closure *write_cb;
53
murgatroid99e2672c92016-11-09 15:12:22 -080054 grpc_slice read_slice;
55 grpc_slice_buffer *read_slices;
56 grpc_slice_buffer *write_slices;
murgatroid999030c812016-09-16 13:25:08 -070057 uv_buf_t *write_buffers;
58
murgatroid99e2672c92016-11-09 15:12:22 -080059 grpc_resource_user *resource_user;
murgatroid9969259d42016-10-31 14:34:10 -070060
murgatroid992c287ca2016-10-07 09:55:35 -070061 bool shutting_down;
murgatroid9969259d42016-10-31 14:34:10 -070062
murgatroid999030c812016-09-16 13:25:08 -070063 char *peer_string;
64 grpc_pollset *pollset;
65} grpc_tcp;
66
murgatroid99e2672c92016-11-09 15:12:22 -080067static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
68 grpc_resource_user_unref(exec_ctx, tcp->resource_user);
murgatroid9969259d42016-10-31 14:34:10 -070069 gpr_free(tcp);
murgatroid9969259d42016-10-31 14:34:10 -070070}
murgatroid999030c812016-09-16 13:25:08 -070071
ncteisen0e3aee32017-06-08 16:32:24 -070072#ifndef NDEBUG
murgatroid992e012342016-11-10 18:24:08 -080073#define TCP_UNREF(exec_ctx, tcp, reason) \
74 tcp_unref((exec_ctx), (tcp), (reason), __FILE__, __LINE__)
murgatroid99a1137ce2017-05-09 14:21:12 -070075#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__)
murgatroid992e012342016-11-10 18:24:08 -080076static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
77 const char *reason, const char *file, int line) {
ncteisen0e3aee32017-06-08 16:32:24 -070078 if (GRPC_TRACER_ON(grpc_tcp_trace)) {
79 gpr_atm val = gpr_atm_no_barrier_load(&tcp->refcount.count);
ncteisend39010e2017-06-08 17:08:07 -070080 gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
81 "TCP unref %p : %s %" PRIdPTR " -> %" PRIdPTR, tcp, reason, val,
82 val - 1);
ncteisen0e3aee32017-06-08 16:32:24 -070083 }
murgatroid999030c812016-09-16 13:25:08 -070084 if (gpr_unref(&tcp->refcount)) {
murgatroid99e2672c92016-11-09 15:12:22 -080085 tcp_free(exec_ctx, tcp);
murgatroid999030c812016-09-16 13:25:08 -070086 }
87}
88
89static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file,
90 int line) {
ncteisen0e3aee32017-06-08 16:32:24 -070091 if (GRPC_TRACER_ON(grpc_tcp_trace)) {
92 gpr_atm val = gpr_atm_no_barrier_load(&tcp->refcount.count);
ncteisend39010e2017-06-08 17:08:07 -070093 gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
94 "TCP ref %p : %s %" PRIdPTR " -> %" PRIdPTR, tcp, reason, val,
95 val + 1);
ncteisen0e3aee32017-06-08 16:32:24 -070096 }
murgatroid999030c812016-09-16 13:25:08 -070097 gpr_ref(&tcp->refcount);
98}
99#else
murgatroid99e2672c92016-11-09 15:12:22 -0800100#define TCP_UNREF(exec_ctx, tcp, reason) tcp_unref((exec_ctx), (tcp))
murgatroid999030c812016-09-16 13:25:08 -0700101#define TCP_REF(tcp, reason) tcp_ref((tcp))
murgatroid99e2672c92016-11-09 15:12:22 -0800102static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
murgatroid999030c812016-09-16 13:25:08 -0700103 if (gpr_unref(&tcp->refcount)) {
murgatroid99e2672c92016-11-09 15:12:22 -0800104 tcp_free(exec_ctx, tcp);
murgatroid999030c812016-09-16 13:25:08 -0700105 }
106}
107
108static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); }
109#endif
110
murgatroid991191b722017-02-08 11:56:52 -0800111static void uv_close_callback(uv_handle_t *handle) {
112 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
113 grpc_tcp *tcp = handle->data;
114 TCP_UNREF(&exec_ctx, tcp, "destroy");
115 grpc_exec_ctx_finish(&exec_ctx);
116}
117
murgatroid99dedb9232016-09-26 13:54:04 -0700118static void alloc_uv_buf(uv_handle_t *handle, size_t suggested_size,
119 uv_buf_t *buf) {
murgatroid9969259d42016-10-31 14:34:10 -0700120 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
murgatroid999030c812016-09-16 13:25:08 -0700121 grpc_tcp *tcp = handle->data;
122 (void)suggested_size;
murgatroid9969259d42016-10-31 14:34:10 -0700123 tcp->read_slice = grpc_resource_user_slice_malloc(
murgatroid99e2672c92016-11-09 15:12:22 -0800124 &exec_ctx, tcp->resource_user, GRPC_TCP_DEFAULT_READ_SLICE_SIZE);
Craig Tiller618e67d2016-10-26 21:08:10 -0700125 buf->base = (char *)GRPC_SLICE_START_PTR(tcp->read_slice);
126 buf->len = GRPC_SLICE_LENGTH(tcp->read_slice);
murgatroid9969259d42016-10-31 14:34:10 -0700127 grpc_exec_ctx_finish(&exec_ctx);
murgatroid999030c812016-09-16 13:25:08 -0700128}
129
murgatroid99dedb9232016-09-26 13:54:04 -0700130static void read_callback(uv_stream_t *stream, ssize_t nread,
131 const uv_buf_t *buf) {
murgatroid99e2672c92016-11-09 15:12:22 -0800132 grpc_slice sub;
murgatroid999030c812016-09-16 13:25:08 -0700133 grpc_error *error;
134 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
135 grpc_tcp *tcp = stream->data;
136 grpc_closure *cb = tcp->read_cb;
137 if (nread == 0) {
138 // Nothing happened. Wait for the next callback
139 return;
140 }
murgatroid99e2672c92016-11-09 15:12:22 -0800141 TCP_UNREF(&exec_ctx, tcp, "read");
murgatroid999030c812016-09-16 13:25:08 -0700142 tcp->read_cb = NULL;
143 // TODO(murgatroid99): figure out what the return value here means
144 uv_read_stop(stream);
145 if (nread == UV_EOF) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700146 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("EOF");
murgatroid999030c812016-09-16 13:25:08 -0700147 } else if (nread > 0) {
148 // Successful read
murgatroid99e2672c92016-11-09 15:12:22 -0800149 sub = grpc_slice_sub_no_ref(tcp->read_slice, 0, (size_t)nread);
150 grpc_slice_buffer_add(tcp->read_slices, sub);
murgatroid999030c812016-09-16 13:25:08 -0700151 error = GRPC_ERROR_NONE;
Craig Tiller341bcc52017-05-09 08:37:44 -0700152 if (GRPC_TRACER_ON(grpc_tcp_trace)) {
murgatroid999030c812016-09-16 13:25:08 -0700153 size_t i;
154 const char *str = grpc_error_string(error);
155 gpr_log(GPR_DEBUG, "read: error=%s", str);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800156
murgatroid999030c812016-09-16 13:25:08 -0700157 for (i = 0; i < tcp->read_slices->count; i++) {
murgatroid99e2672c92016-11-09 15:12:22 -0800158 char *dump = grpc_dump_slice(tcp->read_slices->slices[i],
murgatroid992e012342016-11-10 18:24:08 -0800159 GPR_DUMP_HEX | GPR_DUMP_ASCII);
murgatroid99dedb9232016-09-26 13:54:04 -0700160 gpr_log(GPR_DEBUG, "READ %p (peer=%s): %s", tcp, tcp->peer_string,
161 dump);
murgatroid999030c812016-09-16 13:25:08 -0700162 gpr_free(dump);
163 }
164 }
165 } else {
166 // nread < 0: Error
ncteisen4b36a3d2017-03-13 19:08:06 -0700167 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("TCP Read failed");
murgatroid999030c812016-09-16 13:25:08 -0700168 }
ncteisen969b46e2017-06-08 14:57:11 -0700169 GRPC_CLOSURE_SCHED(&exec_ctx, cb, error);
murgatroid999030c812016-09-16 13:25:08 -0700170 grpc_exec_ctx_finish(&exec_ctx);
171}
172
173static void uv_endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
murgatroid99e2672c92016-11-09 15:12:22 -0800174 grpc_slice_buffer *read_slices, grpc_closure *cb) {
murgatroid999030c812016-09-16 13:25:08 -0700175 grpc_tcp *tcp = (grpc_tcp *)ep;
176 int status;
177 grpc_error *error = GRPC_ERROR_NONE;
178 GPR_ASSERT(tcp->read_cb == NULL);
179 tcp->read_cb = cb;
180 tcp->read_slices = read_slices;
Craig Tillerab7b2d82016-12-07 07:26:34 -0800181 grpc_slice_buffer_reset_and_unref_internal(exec_ctx, read_slices);
murgatroid999030c812016-09-16 13:25:08 -0700182 TCP_REF(tcp, "read");
183 // TODO(murgatroid99): figure out what the return value here means
murgatroid99dedb9232016-09-26 13:54:04 -0700184 status =
185 uv_read_start((uv_stream_t *)tcp->handle, alloc_uv_buf, read_callback);
murgatroid999030c812016-09-16 13:25:08 -0700186 if (status != 0) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700187 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("TCP Read failed at start");
murgatroid99dedb9232016-09-26 13:54:04 -0700188 error =
ncteisen4b36a3d2017-03-13 19:08:06 -0700189 grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR,
190 grpc_slice_from_static_string(uv_strerror(status)));
ncteisen969b46e2017-06-08 14:57:11 -0700191 GRPC_CLOSURE_SCHED(exec_ctx, cb, error);
murgatroid999030c812016-09-16 13:25:08 -0700192 }
Craig Tiller341bcc52017-05-09 08:37:44 -0700193 if (GRPC_TRACER_ON(grpc_tcp_trace)) {
murgatroid999030c812016-09-16 13:25:08 -0700194 const char *str = grpc_error_string(error);
195 gpr_log(GPR_DEBUG, "Initiating read on %p: error=%s", tcp, str);
196 }
197}
198
199static void write_callback(uv_write_t *req, int status) {
200 grpc_tcp *tcp = req->data;
201 grpc_error *error;
202 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
203 grpc_closure *cb = tcp->write_cb;
204 tcp->write_cb = NULL;
murgatroid99e2672c92016-11-09 15:12:22 -0800205 TCP_UNREF(&exec_ctx, tcp, "write");
murgatroid999030c812016-09-16 13:25:08 -0700206 if (status == 0) {
207 error = GRPC_ERROR_NONE;
208 } else {
ncteisen4b36a3d2017-03-13 19:08:06 -0700209 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("TCP Write failed");
murgatroid999030c812016-09-16 13:25:08 -0700210 }
Craig Tiller341bcc52017-05-09 08:37:44 -0700211 if (GRPC_TRACER_ON(grpc_tcp_trace)) {
murgatroid999030c812016-09-16 13:25:08 -0700212 const char *str = grpc_error_string(error);
213 gpr_log(GPR_DEBUG, "write complete on %p: error=%s", tcp, str);
214 }
215 gpr_free(tcp->write_buffers);
murgatroid99e2672c92016-11-09 15:12:22 -0800216 grpc_resource_user_free(&exec_ctx, tcp->resource_user,
murgatroid9969259d42016-10-31 14:34:10 -0700217 sizeof(uv_buf_t) * tcp->write_slices->count);
ncteisen969b46e2017-06-08 14:57:11 -0700218 GRPC_CLOSURE_SCHED(&exec_ctx, cb, error);
murgatroid999030c812016-09-16 13:25:08 -0700219 grpc_exec_ctx_finish(&exec_ctx);
220}
221
222static void uv_endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
murgatroid99e2672c92016-11-09 15:12:22 -0800223 grpc_slice_buffer *write_slices,
murgatroid999030c812016-09-16 13:25:08 -0700224 grpc_closure *cb) {
225 grpc_tcp *tcp = (grpc_tcp *)ep;
226 uv_buf_t *buffers;
227 unsigned int buffer_count;
228 unsigned int i;
murgatroid99e2672c92016-11-09 15:12:22 -0800229 grpc_slice *slice;
murgatroid999030c812016-09-16 13:25:08 -0700230 uv_write_t *write_req;
231
Craig Tiller341bcc52017-05-09 08:37:44 -0700232 if (GRPC_TRACER_ON(grpc_tcp_trace)) {
murgatroid99c36f6ea2016-10-03 09:24:09 -0700233 size_t j;
murgatroid999030c812016-09-16 13:25:08 -0700234
murgatroid99c36f6ea2016-10-03 09:24:09 -0700235 for (j = 0; j < write_slices->count; j++) {
murgatroid99e2672c92016-11-09 15:12:22 -0800236 char *data = grpc_dump_slice(write_slices->slices[j],
murgatroid992e012342016-11-10 18:24:08 -0800237 GPR_DUMP_HEX | GPR_DUMP_ASCII);
murgatroid999030c812016-09-16 13:25:08 -0700238 gpr_log(GPR_DEBUG, "WRITE %p (peer=%s): %s", tcp, tcp->peer_string, data);
239 gpr_free(data);
240 }
241 }
242
243 if (tcp->shutting_down) {
ncteisen969b46e2017-06-08 14:57:11 -0700244 GRPC_CLOSURE_SCHED(exec_ctx, cb, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
ncteisen4b36a3d2017-03-13 19:08:06 -0700245 "TCP socket is shutting down"));
murgatroid999030c812016-09-16 13:25:08 -0700246 return;
247 }
248
249 GPR_ASSERT(tcp->write_cb == NULL);
250 tcp->write_slices = write_slices;
251 GPR_ASSERT(tcp->write_slices->count <= UINT_MAX);
252 if (tcp->write_slices->count == 0) {
253 // No slices means we don't have to do anything,
254 // and libuv doesn't like empty writes
ncteisen969b46e2017-06-08 14:57:11 -0700255 GRPC_CLOSURE_SCHED(exec_ctx, cb, GRPC_ERROR_NONE);
murgatroid999030c812016-09-16 13:25:08 -0700256 return;
257 }
258
259 tcp->write_cb = cb;
260 buffer_count = (unsigned int)tcp->write_slices->count;
261 buffers = gpr_malloc(sizeof(uv_buf_t) * buffer_count);
murgatroid99e2672c92016-11-09 15:12:22 -0800262 grpc_resource_user_alloc(exec_ctx, tcp->resource_user,
murgatroid9969259d42016-10-31 14:34:10 -0700263 sizeof(uv_buf_t) * buffer_count, NULL);
murgatroid999030c812016-09-16 13:25:08 -0700264 for (i = 0; i < buffer_count; i++) {
265 slice = &tcp->write_slices->slices[i];
Craig Tiller618e67d2016-10-26 21:08:10 -0700266 buffers[i].base = (char *)GRPC_SLICE_START_PTR(*slice);
267 buffers[i].len = GRPC_SLICE_LENGTH(*slice);
murgatroid999030c812016-09-16 13:25:08 -0700268 }
murgatroid9969259d42016-10-31 14:34:10 -0700269 tcp->write_buffers = buffers;
270 write_req = &tcp->write_req;
murgatroid999030c812016-09-16 13:25:08 -0700271 write_req->data = tcp;
272 TCP_REF(tcp, "write");
273 // TODO(murgatroid99): figure out what the return value here means
274 uv_write(write_req, (uv_stream_t *)tcp->handle, buffers, buffer_count,
275 write_callback);
276}
277
278static void uv_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
279 grpc_pollset *pollset) {
280 // No-op. We're ignoring pollsets currently
murgatroid99dedb9232016-09-26 13:54:04 -0700281 (void)exec_ctx;
282 (void)ep;
283 (void)pollset;
284 grpc_tcp *tcp = (grpc_tcp *)ep;
murgatroid999030c812016-09-16 13:25:08 -0700285 tcp->pollset = pollset;
286}
287
288static void uv_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
289 grpc_pollset_set *pollset) {
290 // No-op. We're ignoring pollsets currently
murgatroid99dedb9232016-09-26 13:54:04 -0700291 (void)exec_ctx;
292 (void)ep;
293 (void)pollset;
murgatroid999030c812016-09-16 13:25:08 -0700294}
295
murgatroid9969259d42016-10-31 14:34:10 -0700296static void shutdown_callback(uv_shutdown_t *req, int status) {}
297
Craig Tiller22f13fb2017-01-27 11:43:25 -0800298static void uv_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
299 grpc_error *why) {
murgatroid999030c812016-09-16 13:25:08 -0700300 grpc_tcp *tcp = (grpc_tcp *)ep;
murgatroid992c287ca2016-10-07 09:55:35 -0700301 if (!tcp->shutting_down) {
302 tcp->shutting_down = true;
murgatroid9969259d42016-10-31 14:34:10 -0700303 uv_shutdown_t *req = &tcp->shutdown_req;
murgatroid992c287ca2016-10-07 09:55:35 -0700304 uv_shutdown(req, (uv_stream_t *)tcp->handle, shutdown_callback);
murgatroid99a1137ce2017-05-09 14:21:12 -0700305 grpc_resource_user_shutdown(exec_ctx, tcp->resource_user);
murgatroid992c287ca2016-10-07 09:55:35 -0700306 }
Craig Tiller22f13fb2017-01-27 11:43:25 -0800307 GRPC_ERROR_UNREF(why);
murgatroid999030c812016-09-16 13:25:08 -0700308}
309
310static void uv_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
311 grpc_network_status_unregister_endpoint(ep);
312 grpc_tcp *tcp = (grpc_tcp *)ep;
murgatroid999030c812016-09-16 13:25:08 -0700313 uv_close((uv_handle_t *)tcp->handle, uv_close_callback);
murgatroid999030c812016-09-16 13:25:08 -0700314}
315
316static char *uv_get_peer(grpc_endpoint *ep) {
317 grpc_tcp *tcp = (grpc_tcp *)ep;
318 return gpr_strdup(tcp->peer_string);
319}
320
murgatroid9969259d42016-10-31 14:34:10 -0700321static grpc_resource_user *uv_get_resource_user(grpc_endpoint *ep) {
322 grpc_tcp *tcp = (grpc_tcp *)ep;
murgatroid99e2672c92016-11-09 15:12:22 -0800323 return tcp->resource_user;
murgatroid9969259d42016-10-31 14:34:10 -0700324}
325
murgatroid992e012342016-11-10 18:24:08 -0800326static int uv_get_fd(grpc_endpoint *ep) { return -1; }
327
murgatroid9969259d42016-10-31 14:34:10 -0700328static grpc_endpoint_vtable vtable = {
Craig Tiller00a8c0b2017-06-06 09:35:58 -0700329 uv_endpoint_read, uv_endpoint_write, uv_add_to_pollset,
330 uv_add_to_pollset_set, uv_endpoint_shutdown, uv_destroy,
331 uv_get_resource_user, uv_get_peer, uv_get_fd};
murgatroid999030c812016-09-16 13:25:08 -0700332
murgatroid9969259d42016-10-31 14:34:10 -0700333grpc_endpoint *grpc_tcp_create(uv_tcp_t *handle,
334 grpc_resource_quota *resource_quota,
335 char *peer_string) {
murgatroid999030c812016-09-16 13:25:08 -0700336 grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp));
337
Craig Tiller341bcc52017-05-09 08:37:44 -0700338 if (GRPC_TRACER_ON(grpc_tcp_trace)) {
murgatroid999030c812016-09-16 13:25:08 -0700339 gpr_log(GPR_DEBUG, "Creating TCP endpoint %p", tcp);
340 }
341
murgatroid9904d28292016-10-27 14:36:57 -0700342 /* Disable Nagle's Algorithm */
murgatroid9912e57752016-10-27 14:30:41 -0700343 uv_tcp_nodelay(handle, 1);
344
murgatroid999030c812016-09-16 13:25:08 -0700345 memset(tcp, 0, sizeof(grpc_tcp));
346 tcp->base.vtable = &vtable;
347 tcp->handle = handle;
348 handle->data = tcp;
349 gpr_ref_init(&tcp->refcount, 1);
350 tcp->peer_string = gpr_strdup(peer_string);
murgatroid992c287ca2016-10-07 09:55:35 -0700351 tcp->shutting_down = false;
murgatroid99e2672c92016-11-09 15:12:22 -0800352 tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string);
murgatroid999030c812016-09-16 13:25:08 -0700353 /* Tell network status tracking code about the new endpoint */
354 grpc_network_status_register_endpoint(&tcp->base);
355
356#ifndef GRPC_UV_TCP_HOLD_LOOP
357 uv_unref((uv_handle_t *)handle);
358#endif
359
360 return &tcp->base;
361}
362
363#endif /* GRPC_UV */