Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 1 | /* |
| 2 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 3 | * Copyright 2015 gRPC authors. |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 4 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 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 |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 8 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 10 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 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. |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 16 | * |
| 17 | */ |
| 18 | |
Alexander Polcyn | db3e898 | 2018-02-21 16:59:24 -0800 | [diff] [blame] | 19 | #include <grpc/support/port_platform.h> |
| 20 | |
murgatroid99 | 5407089 | 2016-08-08 17:01:18 -0700 | [diff] [blame] | 21 | #include "src/core/lib/iomgr/port.h" |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 22 | |
murgatroid99 | 623dd4f | 2016-08-08 17:31:27 -0700 | [diff] [blame] | 23 | #ifdef GRPC_WINSOCK_SOCKET |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 24 | |
Nicolas "Pixel" Noble | c4b18a5 | 2016-04-15 04:53:54 +0200 | [diff] [blame] | 25 | #include <limits.h> |
| 26 | |
Makarand Dharmapurikar | 0579cfc | 2016-06-20 15:45:24 -0700 | [diff] [blame] | 27 | #include "src/core/lib/iomgr/network_status_tracker.h" |
Yuchen Zeng | 12dfdc3 | 2016-04-26 22:05:41 -0700 | [diff] [blame] | 28 | #include "src/core/lib/iomgr/sockaddr_windows.h" |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 29 | |
Craig Tiller | 28b7242 | 2016-10-26 21:15:29 -0700 | [diff] [blame] | 30 | #include <grpc/slice_buffer.h> |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 31 | #include <grpc/support/alloc.h> |
| 32 | #include <grpc/support/log.h> |
Yuchen Zeng | 12dfdc3 | 2016-04-26 22:05:41 -0700 | [diff] [blame] | 33 | #include <grpc/support/log_windows.h> |
Masood Malekghassemi | 701af60 | 2015-06-03 15:01:17 -0700 | [diff] [blame] | 34 | #include <grpc/support/string_util.h> |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 35 | |
Vijay Pai | d4d0a30 | 2018-01-25 13:24:03 -0800 | [diff] [blame] | 36 | #include "src/core/lib/gpr/useful.h" |
Craig Tiller | 9533d04 | 2016-03-25 17:11:06 -0700 | [diff] [blame] | 37 | #include "src/core/lib/iomgr/iocp_windows.h" |
| 38 | #include "src/core/lib/iomgr/sockaddr.h" |
| 39 | #include "src/core/lib/iomgr/sockaddr_utils.h" |
| 40 | #include "src/core/lib/iomgr/socket_windows.h" |
| 41 | #include "src/core/lib/iomgr/tcp_client.h" |
Yash Tibrewal | 547653e | 2017-09-25 21:20:19 -0700 | [diff] [blame] | 42 | #include "src/core/lib/iomgr/tcp_windows.h" |
Craig Tiller | 9533d04 | 2016-03-25 17:11:06 -0700 | [diff] [blame] | 43 | #include "src/core/lib/iomgr/timer.h" |
Craig Tiller | fede4d4 | 2016-12-06 20:20:10 -0800 | [diff] [blame] | 44 | #include "src/core/lib/slice/slice_internal.h" |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 45 | |
Nicolas "Pixel" Noble | c4b18a5 | 2016-04-15 04:53:54 +0200 | [diff] [blame] | 46 | #if defined(__MSYS__) && defined(GPR_ARCH_64) |
| 47 | /* Nasty workaround for nasty bug when using the 64 bits msys compiler |
| 48 | in conjunction with Microsoft Windows headers. */ |
| 49 | #define GRPC_FIONBIO _IOW('f', 126, uint32_t) |
| 50 | #else |
| 51 | #define GRPC_FIONBIO FIONBIO |
| 52 | #endif |
| 53 | |
kpayson64 | 539f506 | 2018-03-12 19:16:30 -0700 | [diff] [blame] | 54 | extern grpc_core::TraceFlag grpc_tcp_trace; |
ncteisen | 0e3aee3 | 2017-06-08 16:32:24 -0700 | [diff] [blame] | 55 | |
Alex Polcyn | 5cd8b1e | 2018-06-16 04:08:55 +0000 | [diff] [blame] | 56 | grpc_error* grpc_tcp_set_non_block(SOCKET sock) { |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 57 | int status; |
Nicolas "Pixel" Noble | c4b18a5 | 2016-04-15 04:53:54 +0200 | [diff] [blame] | 58 | uint32_t param = 1; |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 59 | DWORD ret; |
Nicolas "Pixel" Noble | 344f55b | 2016-04-15 07:52:25 +0200 | [diff] [blame] | 60 | status = WSAIoctl(sock, GRPC_FIONBIO, ¶m, sizeof(param), NULL, 0, &ret, |
| 61 | NULL, NULL); |
Craig Tiller | 3e149f3 | 2016-05-17 16:11:04 -0700 | [diff] [blame] | 62 | return status == 0 |
| 63 | ? GRPC_ERROR_NONE |
| 64 | : GRPC_WSA_ERROR(WSAGetLastError(), "WSAIoctl(GRPC_FIONBIO)"); |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 65 | } |
| 66 | |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 67 | static grpc_error* set_dualstack(SOCKET sock) { |
Nicolas "Pixel" Noble | ee0c96c | 2015-02-04 23:35:41 +0100 | [diff] [blame] | 68 | int status; |
| 69 | unsigned long param = 0; |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 70 | status = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)¶m, |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 71 | sizeof(param)); |
Craig Tiller | 3e149f3 | 2016-05-17 16:11:04 -0700 | [diff] [blame] | 72 | return status == 0 |
| 73 | ? GRPC_ERROR_NONE |
| 74 | : GRPC_WSA_ERROR(WSAGetLastError(), "setsockopt(IPV6_V6ONLY)"); |
Nicolas "Pixel" Noble | ee0c96c | 2015-02-04 23:35:41 +0100 | [diff] [blame] | 75 | } |
| 76 | |
Ara Ayvazyan | f5f5ee3 | 2018-04-26 16:23:06 -0700 | [diff] [blame] | 77 | static grpc_error* enable_loopback_fast_path(SOCKET sock) { |
| 78 | int status; |
| 79 | uint32_t param = 1; |
| 80 | DWORD ret; |
| 81 | status = WSAIoctl(sock, /*SIO_LOOPBACK_FAST_PATH==*/_WSAIOW(IOC_VENDOR, 16), |
| 82 | ¶m, sizeof(param), NULL, 0, &ret, 0, 0); |
| 83 | if (status == SOCKET_ERROR) { |
| 84 | status = WSAGetLastError(); |
| 85 | } |
| 86 | return status == 0 || status == WSAEOPNOTSUPP |
| 87 | ? GRPC_ERROR_NONE |
| 88 | : GRPC_WSA_ERROR(status, "WSAIoctl(SIO_LOOPBACK_FAST_PATH)"); |
| 89 | } |
| 90 | |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 91 | grpc_error* grpc_tcp_prepare_socket(SOCKET sock) { |
| 92 | grpc_error* err; |
Alex Polcyn | 5cd8b1e | 2018-06-16 04:08:55 +0000 | [diff] [blame] | 93 | err = grpc_tcp_set_non_block(sock); |
Craig Tiller | a41ac57 | 2016-05-17 16:08:17 -0700 | [diff] [blame] | 94 | if (err != GRPC_ERROR_NONE) return err; |
| 95 | err = set_dualstack(sock); |
| 96 | if (err != GRPC_ERROR_NONE) return err; |
Ara Ayvazyan | f5f5ee3 | 2018-04-26 16:23:06 -0700 | [diff] [blame] | 97 | err = enable_loopback_fast_path(sock); |
| 98 | if (err != GRPC_ERROR_NONE) return err; |
Craig Tiller | a41ac57 | 2016-05-17 16:08:17 -0700 | [diff] [blame] | 99 | return GRPC_ERROR_NONE; |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 100 | } |
| 101 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 102 | typedef struct grpc_tcp { |
Nicolas "Pixel" Noble | 0f981e9 | 2015-05-03 10:40:56 +0200 | [diff] [blame] | 103 | /* This is our C++ class derivation emulation. */ |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 104 | grpc_endpoint base; |
Nicolas "Pixel" Noble | 0f981e9 | 2015-05-03 10:40:56 +0200 | [diff] [blame] | 105 | /* The one socket this endpoint is using. */ |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 106 | grpc_winsocket* socket; |
Nicolas "Pixel" Noble | 0f981e9 | 2015-05-03 10:40:56 +0200 | [diff] [blame] | 107 | /* Refcounting how many operations are in progress. */ |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 108 | gpr_refcount refcount; |
| 109 | |
Craig Tiller | 82f9bd8 | 2015-09-23 09:31:51 -0700 | [diff] [blame] | 110 | grpc_closure on_read; |
| 111 | grpc_closure on_write; |
| 112 | |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 113 | grpc_closure* read_cb; |
| 114 | grpc_closure* write_cb; |
Craig Tiller | d41a4a7 | 2016-10-26 16:16:06 -0700 | [diff] [blame] | 115 | grpc_slice read_slice; |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 116 | grpc_slice_buffer* write_slices; |
| 117 | grpc_slice_buffer* read_slices; |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 118 | |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 119 | grpc_resource_user* resource_user; |
Craig Tiller | 290e9a7 | 2016-10-28 08:17:00 -0700 | [diff] [blame] | 120 | |
Nicolas "Pixel" Noble | 0f981e9 | 2015-05-03 10:40:56 +0200 | [diff] [blame] | 121 | /* The IO Completion Port runs from another thread. We need some mechanism |
| 122 | to protect ourselves when requesting a shutdown. */ |
| 123 | gpr_mu mu; |
| 124 | int shutting_down; |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 125 | grpc_error* shutdown_error; |
Craig Tiller | 81bcc4c | 2015-07-20 14:04:18 -0700 | [diff] [blame] | 126 | |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 127 | char* peer_string; |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 128 | } grpc_tcp; |
| 129 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 130 | static void tcp_free(grpc_tcp* tcp) { |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 131 | grpc_winsocket_destroy(tcp->socket); |
| 132 | gpr_mu_destroy(&tcp->mu); |
| 133 | gpr_free(tcp->peer_string); |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 134 | grpc_resource_user_unref(tcp->resource_user); |
Craig Tiller | 6ba80f9 | 2017-01-27 11:58:32 -0800 | [diff] [blame] | 135 | if (tcp->shutting_down) GRPC_ERROR_UNREF(tcp->shutdown_error); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 136 | gpr_free(tcp); |
Craig Tiller | b029859 | 2015-08-27 07:38:01 -0700 | [diff] [blame] | 137 | } |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 138 | |
ncteisen | 0e3aee3 | 2017-06-08 16:32:24 -0700 | [diff] [blame] | 139 | #ifndef NDEBUG |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 140 | #define TCP_UNREF(tcp, reason) tcp_unref((tcp), (reason), __FILE__, __LINE__) |
Craig Tiller | b029859 | 2015-08-27 07:38:01 -0700 | [diff] [blame] | 141 | #define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 142 | static void tcp_unref(grpc_tcp* tcp, const char* reason, const char* file, |
| 143 | int line) { |
ncteisen | 9ffb149 | 2017-11-10 14:00:49 -0800 | [diff] [blame] | 144 | if (grpc_tcp_trace.enabled()) { |
ncteisen | 0e3aee3 | 2017-06-08 16:32:24 -0700 | [diff] [blame] | 145 | gpr_atm val = gpr_atm_no_barrier_load(&tcp->refcount.count); |
ncteisen | d39010e | 2017-06-08 17:08:07 -0700 | [diff] [blame] | 146 | gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, |
| 147 | "TCP unref %p : %s %" PRIdPTR " -> %" PRIdPTR, tcp, reason, val, |
| 148 | val - 1); |
ncteisen | 0e3aee3 | 2017-06-08 16:32:24 -0700 | [diff] [blame] | 149 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 150 | if (gpr_unref(&tcp->refcount)) { |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 151 | tcp_free(tcp); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 152 | } |
Craig Tiller | 0882a35 | 2015-08-26 13:21:14 -0700 | [diff] [blame] | 153 | } |
| 154 | |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 155 | static void tcp_ref(grpc_tcp* tcp, const char* reason, const char* file, |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 156 | int line) { |
ncteisen | 9ffb149 | 2017-11-10 14:00:49 -0800 | [diff] [blame] | 157 | if (grpc_tcp_trace.enabled()) { |
ncteisen | 0e3aee3 | 2017-06-08 16:32:24 -0700 | [diff] [blame] | 158 | gpr_atm val = gpr_atm_no_barrier_load(&tcp->refcount.count); |
ncteisen | d39010e | 2017-06-08 17:08:07 -0700 | [diff] [blame] | 159 | gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, |
| 160 | "TCP ref %p : %s %" PRIdPTR " -> %" PRIdPTR, tcp, reason, val, |
| 161 | val + 1); |
ncteisen | 0e3aee3 | 2017-06-08 16:32:24 -0700 | [diff] [blame] | 162 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 163 | gpr_ref(&tcp->refcount); |
Craig Tiller | b029859 | 2015-08-27 07:38:01 -0700 | [diff] [blame] | 164 | } |
| 165 | #else |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 166 | #define TCP_UNREF(tcp, reason) tcp_unref((tcp)) |
Craig Tiller | b029859 | 2015-08-27 07:38:01 -0700 | [diff] [blame] | 167 | #define TCP_REF(tcp, reason) tcp_ref((tcp)) |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 168 | static void tcp_unref(grpc_tcp* tcp) { |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 169 | if (gpr_unref(&tcp->refcount)) { |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 170 | tcp_free(tcp); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 171 | } |
Craig Tiller | b029859 | 2015-08-27 07:38:01 -0700 | [diff] [blame] | 172 | } |
| 173 | |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 174 | static void tcp_ref(grpc_tcp* tcp) { gpr_ref(&tcp->refcount); } |
Craig Tiller | b029859 | 2015-08-27 07:38:01 -0700 | [diff] [blame] | 175 | #endif |
| 176 | |
Nicolas "Pixel" Noble | 0f981e9 | 2015-05-03 10:40:56 +0200 | [diff] [blame] | 177 | /* Asynchronous callback from the IOCP, or the background thread. */ |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 178 | static void on_read(void* tcpp, grpc_error* error) { |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 179 | grpc_tcp* tcp = (grpc_tcp*)tcpp; |
| 180 | grpc_closure* cb = tcp->read_cb; |
| 181 | grpc_winsocket* socket = tcp->socket; |
Craig Tiller | d41a4a7 | 2016-10-26 16:16:06 -0700 | [diff] [blame] | 182 | grpc_slice sub; |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 183 | grpc_winsocket_callback_info* info = &socket->read_info; |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 184 | |
Craig Tiller | a41ac57 | 2016-05-17 16:08:17 -0700 | [diff] [blame] | 185 | GRPC_ERROR_REF(error); |
| 186 | |
| 187 | if (error == GRPC_ERROR_NONE) { |
Jan Tattermusch | 6412479 | 2016-03-25 09:16:22 -0700 | [diff] [blame] | 188 | if (info->wsa_error != 0 && !tcp->shutting_down) { |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 189 | char* utf8_message = gpr_format_message(info->wsa_error); |
ncteisen | 4b36a3d | 2017-03-13 19:08:06 -0700 | [diff] [blame] | 190 | error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(utf8_message); |
Craig Tiller | a41ac57 | 2016-05-17 16:08:17 -0700 | [diff] [blame] | 191 | gpr_free(utf8_message); |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 192 | grpc_slice_unref_internal(tcp->read_slice); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 193 | } else { |
Nicolas "Pixel" Noble | 3a26c5b | 2015-09-22 00:07:14 +0200 | [diff] [blame] | 194 | if (info->bytes_transfered != 0 && !tcp->shutting_down) { |
Craig Tiller | d41a4a7 | 2016-10-26 16:16:06 -0700 | [diff] [blame] | 195 | sub = grpc_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered); |
| 196 | grpc_slice_buffer_add(tcp->read_slices, sub); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 197 | } else { |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 198 | grpc_slice_unref_internal(tcp->read_slice); |
Craig Tiller | 393a4d9 | 2017-01-27 12:01:44 -0800 | [diff] [blame] | 199 | error = tcp->shutting_down |
ncteisen | 4b36a3d | 2017-03-13 19:08:06 -0700 | [diff] [blame] | 200 | ? GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( |
| 201 | "TCP stream shutting down", &tcp->shutdown_error, 1) |
| 202 | : GRPC_ERROR_CREATE_FROM_STATIC_STRING("End of TCP stream"); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 203 | } |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 204 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 205 | } |
Nicolas "Pixel" Noble | 0f981e9 | 2015-05-03 10:40:56 +0200 | [diff] [blame] | 206 | |
Craig Tiller | b029859 | 2015-08-27 07:38:01 -0700 | [diff] [blame] | 207 | tcp->read_cb = NULL; |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 208 | TCP_UNREF(tcp, "read"); |
| 209 | GRPC_CLOSURE_SCHED(cb, error); |
Craig Tiller | b029859 | 2015-08-27 07:38:01 -0700 | [diff] [blame] | 210 | } |
| 211 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 212 | static void win_read(grpc_endpoint* ep, grpc_slice_buffer* read_slices, |
| 213 | grpc_closure* cb) { |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 214 | grpc_tcp* tcp = (grpc_tcp*)ep; |
| 215 | grpc_winsocket* handle = tcp->socket; |
| 216 | grpc_winsocket_callback_info* info = &handle->read_info; |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 217 | int status; |
| 218 | DWORD bytes_read = 0; |
| 219 | DWORD flags = 0; |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 220 | WSABUF buffer; |
| 221 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 222 | if (tcp->shutting_down) { |
ncteisen | 969b46e | 2017-06-08 14:57:11 -0700 | [diff] [blame] | 223 | GRPC_CLOSURE_SCHED( |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 224 | cb, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( |
| 225 | "TCP socket is shutting down", &tcp->shutdown_error, 1)); |
Craig Tiller | 82f9bd8 | 2015-09-23 09:31:51 -0700 | [diff] [blame] | 226 | return; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 227 | } |
Craig Tiller | b029859 | 2015-08-27 07:38:01 -0700 | [diff] [blame] | 228 | |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 229 | tcp->read_cb = cb; |
Craig Tiller | b029859 | 2015-08-27 07:38:01 -0700 | [diff] [blame] | 230 | tcp->read_slices = read_slices; |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 231 | grpc_slice_buffer_reset_and_unref_internal(read_slices); |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 232 | |
Craig Tiller | 423d6fd | 2017-04-12 13:15:45 -0700 | [diff] [blame] | 233 | tcp->read_slice = GRPC_SLICE_MALLOC(8192); |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 234 | |
Craig Tiller | 618e67d | 2016-10-26 21:08:10 -0700 | [diff] [blame] | 235 | buffer.len = (ULONG)GRPC_SLICE_LENGTH( |
Craig Tiller | 620e965 | 2015-12-14 12:02:50 -0800 | [diff] [blame] | 236 | tcp->read_slice); // we know slice size fits in 32bit. |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 237 | buffer.buf = (char*)GRPC_SLICE_START_PTR(tcp->read_slice); |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 238 | |
Craig Tiller | 82f9bd8 | 2015-09-23 09:31:51 -0700 | [diff] [blame] | 239 | TCP_REF(tcp, "read"); |
| 240 | |
Nicolas "Pixel" Noble | 0f981e9 | 2015-05-03 10:40:56 +0200 | [diff] [blame] | 241 | /* First let's try a synchronous, non-blocking read. */ |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 242 | status = |
| 243 | WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, NULL, NULL); |
| 244 | info->wsa_error = status == 0 ? 0 : WSAGetLastError(); |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 245 | |
Nicolas "Pixel" Noble | 0f981e9 | 2015-05-03 10:40:56 +0200 | [diff] [blame] | 246 | /* Did we get data immediately ? Yay. */ |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 247 | if (info->wsa_error != WSAEWOULDBLOCK) { |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 248 | info->bytes_transfered = bytes_read; |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 249 | GRPC_CLOSURE_SCHED(&tcp->on_read, GRPC_ERROR_NONE); |
Craig Tiller | 82f9bd8 | 2015-09-23 09:31:51 -0700 | [diff] [blame] | 250 | return; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 251 | } |
Nicolas "Pixel" Noble | 7f2e98c | 2015-05-08 01:41:21 +0200 | [diff] [blame] | 252 | |
Craig Tiller | 45724b3 | 2015-09-22 10:42:19 -0700 | [diff] [blame] | 253 | /* Otherwise, let's retry, by queuing a read. */ |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 254 | memset(&tcp->socket->read_info.overlapped, 0, sizeof(OVERLAPPED)); |
| 255 | status = WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, |
| 256 | &info->overlapped, NULL); |
Craig Tiller | 45724b3 | 2015-09-22 10:42:19 -0700 | [diff] [blame] | 257 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 258 | if (status != 0) { |
| 259 | int wsa_error = WSAGetLastError(); |
| 260 | if (wsa_error != WSA_IO_PENDING) { |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 261 | info->wsa_error = wsa_error; |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 262 | GRPC_CLOSURE_SCHED(&tcp->on_read, |
Craig Tiller | d465456 | 2017-01-03 08:45:56 -0800 | [diff] [blame] | 263 | GRPC_WSA_ERROR(info->wsa_error, "WSARecv")); |
Craig Tiller | 82f9bd8 | 2015-09-23 09:31:51 -0700 | [diff] [blame] | 264 | return; |
Craig Tiller | 45724b3 | 2015-09-22 10:42:19 -0700 | [diff] [blame] | 265 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 266 | } |
Craig Tiller | 45724b3 | 2015-09-22 10:42:19 -0700 | [diff] [blame] | 267 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 268 | grpc_socket_notify_on_read(tcp->socket, &tcp->on_read); |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 269 | } |
| 270 | |
Nicolas "Pixel" Noble | 0f981e9 | 2015-05-03 10:40:56 +0200 | [diff] [blame] | 271 | /* Asynchronous callback from the IOCP, or the background thread. */ |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 272 | static void on_write(void* tcpp, grpc_error* error) { |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 273 | grpc_tcp* tcp = (grpc_tcp*)tcpp; |
| 274 | grpc_winsocket* handle = tcp->socket; |
| 275 | grpc_winsocket_callback_info* info = &handle->write_info; |
| 276 | grpc_closure* cb; |
Nicolas "Pixel" Noble | 0f981e9 | 2015-05-03 10:40:56 +0200 | [diff] [blame] | 277 | |
Craig Tiller | a41ac57 | 2016-05-17 16:08:17 -0700 | [diff] [blame] | 278 | GRPC_ERROR_REF(error); |
| 279 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 280 | gpr_mu_lock(&tcp->mu); |
Nicolas Noble | e144536 | 2015-05-11 17:40:26 -0700 | [diff] [blame] | 281 | cb = tcp->write_cb; |
| 282 | tcp->write_cb = NULL; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 283 | gpr_mu_unlock(&tcp->mu); |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 284 | |
Craig Tiller | a41ac57 | 2016-05-17 16:08:17 -0700 | [diff] [blame] | 285 | if (error == GRPC_ERROR_NONE) { |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 286 | if (info->wsa_error != 0) { |
Craig Tiller | a41ac57 | 2016-05-17 16:08:17 -0700 | [diff] [blame] | 287 | error = GRPC_WSA_ERROR(info->wsa_error, "WSASend"); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 288 | } else { |
| 289 | GPR_ASSERT(info->bytes_transfered == tcp->write_slices->length); |
Nicolas Noble | e144536 | 2015-05-11 17:40:26 -0700 | [diff] [blame] | 290 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 291 | } |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 292 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 293 | TCP_UNREF(tcp, "write"); |
| 294 | GRPC_CLOSURE_SCHED(cb, error); |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 295 | } |
| 296 | |
Nicolas "Pixel" Noble | 0f981e9 | 2015-05-03 10:40:56 +0200 | [diff] [blame] | 297 | /* Initiates a write. */ |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 298 | static void win_write(grpc_endpoint* ep, grpc_slice_buffer* slices, |
Jan Tattermusch | 97ba943 | 2018-08-27 12:43:20 +0200 | [diff] [blame^] | 299 | grpc_closure* cb) { |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 300 | grpc_tcp* tcp = (grpc_tcp*)ep; |
| 301 | grpc_winsocket* socket = tcp->socket; |
| 302 | grpc_winsocket_callback_info* info = &socket->write_info; |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 303 | unsigned i; |
| 304 | DWORD bytes_sent; |
| 305 | int status; |
| 306 | WSABUF local_buffers[16]; |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 307 | WSABUF* allocated = NULL; |
| 308 | WSABUF* buffers = local_buffers; |
Jan Tattermusch | f67f071 | 2015-12-07 18:09:49 -0800 | [diff] [blame] | 309 | size_t len; |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 310 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 311 | if (tcp->shutting_down) { |
ncteisen | 969b46e | 2017-06-08 14:57:11 -0700 | [diff] [blame] | 312 | GRPC_CLOSURE_SCHED( |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 313 | cb, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( |
| 314 | "TCP socket is shutting down", &tcp->shutdown_error, 1)); |
Craig Tiller | 82f9bd8 | 2015-09-23 09:31:51 -0700 | [diff] [blame] | 315 | return; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 316 | } |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 317 | |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 318 | tcp->write_cb = cb; |
Craig Tiller | b029859 | 2015-08-27 07:38:01 -0700 | [diff] [blame] | 319 | tcp->write_slices = slices; |
Jan Tattermusch | f67f071 | 2015-12-07 18:09:49 -0800 | [diff] [blame] | 320 | GPR_ASSERT(tcp->write_slices->count <= UINT_MAX); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 321 | if (tcp->write_slices->count > GPR_ARRAY_SIZE(local_buffers)) { |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 322 | buffers = (WSABUF*)gpr_malloc(sizeof(WSABUF) * tcp->write_slices->count); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 323 | allocated = buffers; |
| 324 | } |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 325 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 326 | for (i = 0; i < tcp->write_slices->count; i++) { |
Craig Tiller | 618e67d | 2016-10-26 21:08:10 -0700 | [diff] [blame] | 327 | len = GRPC_SLICE_LENGTH(tcp->write_slices->slices[i]); |
Jan Tattermusch | f67f071 | 2015-12-07 18:09:49 -0800 | [diff] [blame] | 328 | GPR_ASSERT(len <= ULONG_MAX); |
Craig Tiller | 620e965 | 2015-12-14 12:02:50 -0800 | [diff] [blame] | 329 | buffers[i].len = (ULONG)len; |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 330 | buffers[i].buf = (char*)GRPC_SLICE_START_PTR(tcp->write_slices->slices[i]); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 331 | } |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 332 | |
Nicolas "Pixel" Noble | 0f981e9 | 2015-05-03 10:40:56 +0200 | [diff] [blame] | 333 | /* First, let's try a synchronous, non-blocking write. */ |
Jan Tattermusch | 4b3ecdf | 2015-12-04 09:33:05 -0800 | [diff] [blame] | 334 | status = WSASend(socket->socket, buffers, (DWORD)tcp->write_slices->count, |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 335 | &bytes_sent, 0, NULL, NULL); |
| 336 | info->wsa_error = status == 0 ? 0 : WSAGetLastError(); |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 337 | |
Nicolas "Pixel" Noble | 0f981e9 | 2015-05-03 10:40:56 +0200 | [diff] [blame] | 338 | /* We would kind of expect to get a WSAEWOULDBLOCK here, especially on a busy |
| 339 | connection that has its send queue filled up. But if we don't, then we can |
| 340 | avoid doing an async write operation at all. */ |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 341 | if (info->wsa_error != WSAEWOULDBLOCK) { |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 342 | grpc_error* error = status == 0 |
Craig Tiller | 3e149f3 | 2016-05-17 16:11:04 -0700 | [diff] [blame] | 343 | ? GRPC_ERROR_NONE |
| 344 | : GRPC_WSA_ERROR(info->wsa_error, "WSASend"); |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 345 | GRPC_CLOSURE_SCHED(cb, error); |
Nicolas "Pixel" Noble | fa242cb | 2016-09-29 00:54:02 +0200 | [diff] [blame] | 346 | if (allocated) gpr_free(allocated); |
Craig Tiller | 82f9bd8 | 2015-09-23 09:31:51 -0700 | [diff] [blame] | 347 | return; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 348 | } |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 349 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 350 | TCP_REF(tcp, "write"); |
Craig Tiller | 9f80fcf | 2015-08-28 08:22:48 -0700 | [diff] [blame] | 351 | |
Nicolas "Pixel" Noble | 0f981e9 | 2015-05-03 10:40:56 +0200 | [diff] [blame] | 352 | /* If we got a WSAEWOULDBLOCK earlier, then we need to re-do the same |
| 353 | operation, this time asynchronously. */ |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 354 | memset(&socket->write_info.overlapped, 0, sizeof(OVERLAPPED)); |
Jan Tattermusch | 4b3ecdf | 2015-12-04 09:33:05 -0800 | [diff] [blame] | 355 | status = WSASend(socket->socket, buffers, (DWORD)tcp->write_slices->count, |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 356 | &bytes_sent, 0, &socket->write_info.overlapped, NULL); |
| 357 | if (allocated) gpr_free(allocated); |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 358 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 359 | if (status != 0) { |
| 360 | int wsa_error = WSAGetLastError(); |
| 361 | if (wsa_error != WSA_IO_PENDING) { |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 362 | TCP_UNREF(tcp, "write"); |
| 363 | GRPC_CLOSURE_SCHED(cb, GRPC_WSA_ERROR(wsa_error, "WSASend")); |
Craig Tiller | 82f9bd8 | 2015-09-23 09:31:51 -0700 | [diff] [blame] | 364 | return; |
Nicolas "Pixel" Noble | 7f2e98c | 2015-05-08 01:41:21 +0200 | [diff] [blame] | 365 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 366 | } |
Nicolas "Pixel" Noble | 7f2e98c | 2015-05-08 01:41:21 +0200 | [diff] [blame] | 367 | |
Nicolas "Pixel" Noble | 0f981e9 | 2015-05-03 10:40:56 +0200 | [diff] [blame] | 368 | /* As all is now setup, we can now ask for the IOCP notification. It may |
| 369 | trigger the callback immediately however, but no matter. */ |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 370 | grpc_socket_notify_on_write(socket, &tcp->on_write); |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 371 | } |
| 372 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 373 | static void win_add_to_pollset(grpc_endpoint* ep, grpc_pollset* ps) { |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 374 | grpc_tcp* tcp; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 375 | (void)ps; |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 376 | tcp = (grpc_tcp*)ep; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 377 | grpc_iocp_add_socket(tcp->socket); |
Nicolas "Pixel" Noble | f29e9db | 2015-07-29 06:00:22 +0200 | [diff] [blame] | 378 | } |
| 379 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 380 | static void win_add_to_pollset_set(grpc_endpoint* ep, grpc_pollset_set* pss) { |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 381 | grpc_tcp* tcp; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 382 | (void)pss; |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 383 | tcp = (grpc_tcp*)ep; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 384 | grpc_iocp_add_socket(tcp->socket); |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 385 | } |
| 386 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 387 | static void win_delete_from_pollset_set(grpc_endpoint* ep, |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 388 | grpc_pollset_set* pss) {} |
Yuchen Zeng | 01432b7 | 2017-10-02 16:14:06 -0700 | [diff] [blame] | 389 | |
Nicolas "Pixel" Noble | 0f981e9 | 2015-05-03 10:40:56 +0200 | [diff] [blame] | 390 | /* Initiates a shutdown of the TCP endpoint. This will queue abort callbacks |
| 391 | for the potential read and write operations. It is up to the caller to |
| 392 | guarantee this isn't called in parallel to a read or write request, so |
| 393 | we're not going to protect against these. However the IO Completion Port |
| 394 | callback will happen from another thread, so we need to protect against |
| 395 | concurrent access of the data structure in that regard. */ |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 396 | static void win_shutdown(grpc_endpoint* ep, grpc_error* why) { |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 397 | grpc_tcp* tcp = (grpc_tcp*)ep; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 398 | gpr_mu_lock(&tcp->mu); |
Nicolas "Pixel" Noble | 0f981e9 | 2015-05-03 10:40:56 +0200 | [diff] [blame] | 399 | /* At that point, what may happen is that we're already inside the IOCP |
| 400 | callback. See the comments in on_read and on_write. */ |
Craig Tiller | 6ba80f9 | 2017-01-27 11:58:32 -0800 | [diff] [blame] | 401 | if (!tcp->shutting_down) { |
Craig Tiller | 393a4d9 | 2017-01-27 12:01:44 -0800 | [diff] [blame] | 402 | tcp->shutting_down = 1; |
| 403 | tcp->shutdown_error = why; |
| 404 | } else { |
| 405 | GRPC_ERROR_UNREF(why); |
Craig Tiller | 6ba80f9 | 2017-01-27 11:58:32 -0800 | [diff] [blame] | 406 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 407 | grpc_winsocket_shutdown(tcp->socket); |
| 408 | gpr_mu_unlock(&tcp->mu); |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 409 | grpc_resource_user_shutdown(tcp->resource_user); |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 410 | } |
| 411 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 412 | static void win_destroy(grpc_endpoint* ep) { |
Makarand Dharmapurikar | 6149443 | 2016-06-22 13:34:59 -0700 | [diff] [blame] | 413 | grpc_network_status_unregister_endpoint(ep); |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 414 | grpc_tcp* tcp = (grpc_tcp*)ep; |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 415 | TCP_UNREF(tcp, "destroy"); |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 416 | } |
| 417 | |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 418 | static char* win_get_peer(grpc_endpoint* ep) { |
| 419 | grpc_tcp* tcp = (grpc_tcp*)ep; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 420 | return gpr_strdup(tcp->peer_string); |
Craig Tiller | 81bcc4c | 2015-07-20 14:04:18 -0700 | [diff] [blame] | 421 | } |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 422 | |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 423 | static grpc_resource_user* win_get_resource_user(grpc_endpoint* ep) { |
| 424 | grpc_tcp* tcp = (grpc_tcp*)ep; |
Craig Tiller | c037fc1 | 2016-11-04 14:04:54 -0700 | [diff] [blame] | 425 | return tcp->resource_user; |
Craig Tiller | 290e9a7 | 2016-10-28 08:17:00 -0700 | [diff] [blame] | 426 | } |
| 427 | |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 428 | static int win_get_fd(grpc_endpoint* ep) { return -1; } |
murgatroid99 | 2e01234 | 2016-11-10 18:24:08 -0800 | [diff] [blame] | 429 | |
Yuchen Zeng | 01432b7 | 2017-10-02 16:14:06 -0700 | [diff] [blame] | 430 | static grpc_endpoint_vtable vtable = {win_read, |
| 431 | win_write, |
| 432 | win_add_to_pollset, |
| 433 | win_add_to_pollset_set, |
| 434 | win_delete_from_pollset_set, |
| 435 | win_shutdown, |
| 436 | win_destroy, |
| 437 | win_get_resource_user, |
| 438 | win_get_peer, |
| 439 | win_get_fd}; |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 440 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 441 | grpc_endpoint* grpc_tcp_create(grpc_winsocket* socket, |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 442 | grpc_channel_args* channel_args, |
| 443 | const char* peer_string) { |
| 444 | grpc_resource_quota* resource_quota = grpc_resource_quota_create(NULL); |
Craig Tiller | 4254d3b | 2017-04-05 14:03:49 -0700 | [diff] [blame] | 445 | if (channel_args != NULL) { |
| 446 | for (size_t i = 0; i < channel_args->num_args; i++) { |
| 447 | if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_RESOURCE_QUOTA)) { |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 448 | grpc_resource_quota_unref_internal(resource_quota); |
Craig Tiller | 4254d3b | 2017-04-05 14:03:49 -0700 | [diff] [blame] | 449 | resource_quota = grpc_resource_quota_ref_internal( |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 450 | (grpc_resource_quota*)channel_args->args[i].value.pointer.p); |
Craig Tiller | 4254d3b | 2017-04-05 14:03:49 -0700 | [diff] [blame] | 451 | } |
| 452 | } |
| 453 | } |
Craig Tiller | baa14a9 | 2017-11-03 09:09:36 -0700 | [diff] [blame] | 454 | grpc_tcp* tcp = (grpc_tcp*)gpr_malloc(sizeof(grpc_tcp)); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 455 | memset(tcp, 0, sizeof(grpc_tcp)); |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 456 | tcp->base.vtable = &vtable; |
| 457 | tcp->socket = socket; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 458 | gpr_mu_init(&tcp->mu); |
Jan Tattermusch | 6f8507f | 2016-11-22 15:13:34 +0100 | [diff] [blame] | 459 | gpr_ref_init(&tcp->refcount, 1); |
ncteisen | 969b46e | 2017-06-08 14:57:11 -0700 | [diff] [blame] | 460 | GRPC_CLOSURE_INIT(&tcp->on_read, on_read, tcp, grpc_schedule_on_exec_ctx); |
| 461 | GRPC_CLOSURE_INIT(&tcp->on_write, on_write, tcp, grpc_schedule_on_exec_ctx); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 462 | tcp->peer_string = gpr_strdup(peer_string); |
Craig Tiller | c037fc1 | 2016-11-04 14:04:54 -0700 | [diff] [blame] | 463 | tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string); |
Makarand Dharmapurikar | 0579cfc | 2016-06-20 15:45:24 -0700 | [diff] [blame] | 464 | /* Tell network status tracking code about the new endpoint */ |
| 465 | grpc_network_status_register_endpoint(&tcp->base); |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 466 | grpc_resource_quota_unref_internal(resource_quota); |
Makarand Dharmapurikar | 0579cfc | 2016-06-20 15:45:24 -0700 | [diff] [blame] | 467 | |
Nicolas "Pixel" Noble | 21f627a | 2015-02-04 01:31:14 +0100 | [diff] [blame] | 468 | return &tcp->base; |
| 469 | } |
| 470 | |
murgatroid99 | 623dd4f | 2016-08-08 17:31:27 -0700 | [diff] [blame] | 471 | #endif /* GRPC_WINSOCK_SOCKET */ |