|
|
|
@ -375,8 +375,15 @@ static void tcp_ref(grpc_tcp* tcp) { gpr_ref(&tcp->refcount); } |
|
|
|
|
static void tcp_destroy(grpc_endpoint* ep) { |
|
|
|
|
grpc_network_status_unregister_endpoint(ep); |
|
|
|
|
grpc_tcp* tcp = reinterpret_cast<grpc_tcp*>(ep); |
|
|
|
|
gpr_log(GPR_INFO, "tcp destroy %p %p", ep, tcp->outgoing_buffer_arg); |
|
|
|
|
grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer); |
|
|
|
|
if (grpc_event_engine_can_track_errors()) { |
|
|
|
|
gpr_mu_lock(&tcp->tb_mu); |
|
|
|
|
grpc_core::TracedBuffer::Shutdown( |
|
|
|
|
&tcp->tb_head, tcp->outgoing_buffer_arg, |
|
|
|
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING("endpoint destroyed")); |
|
|
|
|
gpr_mu_unlock(&tcp->tb_mu); |
|
|
|
|
tcp->outgoing_buffer_arg = nullptr; |
|
|
|
|
gpr_atm_no_barrier_store(&tcp->stop_error_notification, true); |
|
|
|
|
grpc_fd_set_error(tcp->em_fd); |
|
|
|
|
} |
|
|
|
@ -578,6 +585,7 @@ static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg, |
|
|
|
|
ssize_t* sent_length, |
|
|
|
|
grpc_error** error) { |
|
|
|
|
if (!tcp->socket_ts_enabled) { |
|
|
|
|
gpr_log(GPR_INFO, "set timestamps"); |
|
|
|
|
uint32_t opt = grpc_core::kTimestampingSocketOptions; |
|
|
|
|
if (setsockopt(tcp->fd, SOL_SOCKET, SO_TIMESTAMPING, |
|
|
|
|
static_cast<void*>(&opt), sizeof(opt)) != 0) { |
|
|
|
@ -610,6 +618,7 @@ static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg, |
|
|
|
|
*sent_length = length; |
|
|
|
|
/* Only save timestamps if all the bytes were taken by sendmsg. */ |
|
|
|
|
if (sending_length == static_cast<size_t>(length)) { |
|
|
|
|
gpr_log(GPR_INFO, "tcp new entry %p %p", tcp, tcp->outgoing_buffer_arg); |
|
|
|
|
gpr_mu_lock(&tcp->tb_mu); |
|
|
|
|
grpc_core::TracedBuffer::AddNewEntry( |
|
|
|
|
&tcp->tb_head, static_cast<int>(tcp->bytes_counter + length), |
|
|
|
@ -668,6 +677,7 @@ struct cmsghdr* process_timestamp(grpc_tcp* tcp, msghdr* msg, |
|
|
|
|
* non-linux platforms, error processing is not used/enabled currently. |
|
|
|
|
*/ |
|
|
|
|
static bool process_errors(grpc_tcp* tcp) { |
|
|
|
|
gpr_log(GPR_INFO, "process errors"); |
|
|
|
|
while (true) { |
|
|
|
|
struct iovec iov; |
|
|
|
|
iov.iov_base = nullptr; |
|
|
|
@ -730,6 +740,8 @@ static bool process_errors(grpc_tcp* tcp) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error) { |
|
|
|
|
gpr_log(GPR_INFO, "handle error %p", arg); |
|
|
|
|
GRPC_LOG_IF_ERROR("handle error", GRPC_ERROR_REF(error)); |
|
|
|
|
grpc_tcp* tcp = static_cast<grpc_tcp*>(arg); |
|
|
|
|
if (grpc_tcp_trace.enabled()) { |
|
|
|
|
gpr_log(GPR_INFO, "TCP:%p got_error: %s", tcp, grpc_error_string(error)); |
|
|
|
@ -739,7 +751,8 @@ static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error) { |
|
|
|
|
static_cast<bool>(gpr_atm_acq_load(&tcp->stop_error_notification))) { |
|
|
|
|
/* We aren't going to register to hear on error anymore, so it is safe to
|
|
|
|
|
* unref. */ |
|
|
|
|
grpc_core::TracedBuffer::Shutdown(&tcp->tb_head, GRPC_ERROR_REF(error)); |
|
|
|
|
gpr_log(GPR_INFO, "%p %d early return", error, |
|
|
|
|
static_cast<bool>(gpr_atm_acq_load(&tcp->stop_error_notification))); |
|
|
|
|
TCP_UNREF(tcp, "error-tracking"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -774,6 +787,17 @@ static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error) { |
|
|
|
|
} |
|
|
|
|
#endif /* GRPC_LINUX_ERRQUEUE */ |
|
|
|
|
|
|
|
|
|
void tcp_shutdown_buffer_list(grpc_tcp* tcp) { |
|
|
|
|
if (tcp->outgoing_buffer_arg) { |
|
|
|
|
gpr_mu_lock(&tcp->tb_mu); |
|
|
|
|
grpc_core::TracedBuffer::Shutdown( |
|
|
|
|
&tcp->tb_head, tcp->outgoing_buffer_arg, |
|
|
|
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING("endpoint destroyed")); |
|
|
|
|
gpr_mu_unlock(&tcp->tb_mu); |
|
|
|
|
tcp->outgoing_buffer_arg = nullptr; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* returns true if done, false if pending; if returning true, *error is set */ |
|
|
|
|
#if defined(IOV_MAX) && IOV_MAX < 1000 |
|
|
|
|
#define MAX_WRITE_IOVEC IOV_MAX |
|
|
|
@ -821,8 +845,11 @@ static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) { |
|
|
|
|
msg.msg_flags = 0; |
|
|
|
|
if (tcp->outgoing_buffer_arg != nullptr) { |
|
|
|
|
if (!tcp_write_with_timestamps(tcp, &msg, sending_length, &sent_length, |
|
|
|
|
error)) |
|
|
|
|
error)) { |
|
|
|
|
gpr_log(GPR_INFO, "something went wrong"); |
|
|
|
|
tcp_shutdown_buffer_list(tcp); |
|
|
|
|
return true; /* something went wrong with timestamps */ |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
msg.msg_control = nullptr; |
|
|
|
|
msg.msg_controllen = 0; |
|
|
|
@ -844,12 +871,16 @@ static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) { |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} else if (errno == EPIPE) { |
|
|
|
|
gpr_log(GPR_INFO, "something went wrong"); |
|
|
|
|
*error = tcp_annotate_error(GRPC_OS_ERROR(errno, "sendmsg"), tcp); |
|
|
|
|
grpc_slice_buffer_reset_and_unref_internal(tcp->outgoing_buffer); |
|
|
|
|
tcp_shutdown_buffer_list(tcp); |
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
gpr_log(GPR_INFO, "something went wrong"); |
|
|
|
|
*error = tcp_annotate_error(GRPC_OS_ERROR(errno, "sendmsg"), tcp); |
|
|
|
|
grpc_slice_buffer_reset_and_unref_internal(tcp->outgoing_buffer); |
|
|
|
|
tcp_shutdown_buffer_list(tcp); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -910,6 +941,7 @@ static void tcp_handle_write(void* arg /* grpc_tcp */, grpc_error* error) { |
|
|
|
|
static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf, |
|
|
|
|
grpc_closure* cb, void* arg) { |
|
|
|
|
GPR_TIMER_SCOPE("tcp_write", 0); |
|
|
|
|
gpr_log(GPR_INFO, "tcp_write %p %p", ep, arg); |
|
|
|
|
grpc_tcp* tcp = reinterpret_cast<grpc_tcp*>(ep); |
|
|
|
|
grpc_error* error = GRPC_ERROR_NONE; |
|
|
|
|
|
|
|
|
@ -926,17 +958,18 @@ static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf, |
|
|
|
|
|
|
|
|
|
GPR_ASSERT(tcp->write_cb == nullptr); |
|
|
|
|
|
|
|
|
|
tcp->outgoing_buffer_arg = arg; |
|
|
|
|
if (buf->length == 0) { |
|
|
|
|
GRPC_CLOSURE_SCHED( |
|
|
|
|
cb, grpc_fd_is_shutdown(tcp->em_fd) |
|
|
|
|
? tcp_annotate_error( |
|
|
|
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING("EOF"), tcp) |
|
|
|
|
: GRPC_ERROR_NONE); |
|
|
|
|
tcp_shutdown_buffer_list(tcp); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
tcp->outgoing_buffer = buf; |
|
|
|
|
tcp->outgoing_byte_idx = 0; |
|
|
|
|
tcp->outgoing_buffer_arg = arg; |
|
|
|
|
if (arg) { |
|
|
|
|
GPR_ASSERT(grpc_event_engine_can_track_errors()); |
|
|
|
|
} |
|
|
|
@ -949,6 +982,7 @@ static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf, |
|
|
|
|
} |
|
|
|
|
notify_on_write(tcp); |
|
|
|
|
} else { |
|
|
|
|
gpr_log(GPR_INFO, "imm sched"); |
|
|
|
|
if (grpc_tcp_trace.enabled()) { |
|
|
|
|
const char* str = grpc_error_string(error); |
|
|
|
|
gpr_log(GPR_INFO, "write: %s", str); |
|
|
|
@ -989,6 +1023,23 @@ static grpc_resource_user* tcp_get_resource_user(grpc_endpoint* ep) { |
|
|
|
|
return tcp->resource_user; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static bool tcp_can_track_err(grpc_endpoint* ep) { |
|
|
|
|
grpc_tcp* tcp = reinterpret_cast<grpc_tcp*>(ep); |
|
|
|
|
if (!grpc_event_engine_can_track_errors()) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
struct sockaddr addr; |
|
|
|
|
socklen_t len = sizeof(addr); |
|
|
|
|
if (getsockname(tcp->fd, &addr, &len) < 0) { |
|
|
|
|
gpr_log(GPR_ERROR, "getsockname"); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
if (addr.sa_family == AF_INET || addr.sa_family == AF_INET6) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static const grpc_endpoint_vtable vtable = {tcp_read, |
|
|
|
|
tcp_write, |
|
|
|
|
tcp_add_to_pollset, |
|
|
|
@ -998,7 +1049,8 @@ static const grpc_endpoint_vtable vtable = {tcp_read, |
|
|
|
|
tcp_destroy, |
|
|
|
|
tcp_get_resource_user, |
|
|
|
|
tcp_get_peer, |
|
|
|
|
tcp_get_fd}; |
|
|
|
|
tcp_get_fd, |
|
|
|
|
tcp_can_track_err}; |
|
|
|
|
|
|
|
|
|
#define MAX_CHUNK_SIZE 32 * 1024 * 1024 |
|
|
|
|
|
|
|
|
@ -1059,6 +1111,7 @@ grpc_endpoint* grpc_tcp_create(grpc_fd* em_fd, |
|
|
|
|
tcp->is_first_read = true; |
|
|
|
|
tcp->bytes_counter = -1; |
|
|
|
|
tcp->socket_ts_enabled = false; |
|
|
|
|
tcp->outgoing_buffer_arg = nullptr; |
|
|
|
|
/* paired with unref in grpc_tcp_destroy */ |
|
|
|
|
gpr_ref_init(&tcp->refcount, 1); |
|
|
|
|
gpr_atm_no_barrier_store(&tcp->shutdown_count, 0); |
|
|
|
@ -1097,12 +1150,19 @@ void grpc_tcp_destroy_and_release_fd(grpc_endpoint* ep, int* fd, |
|
|
|
|
grpc_closure* done) { |
|
|
|
|
grpc_network_status_unregister_endpoint(ep); |
|
|
|
|
grpc_tcp* tcp = reinterpret_cast<grpc_tcp*>(ep); |
|
|
|
|
gpr_log(GPR_INFO, "destroy and release %p %p", ep, tcp->outgoing_buffer_arg); |
|
|
|
|
GPR_ASSERT(ep->vtable == &vtable); |
|
|
|
|
tcp->release_fd = fd; |
|
|
|
|
tcp->release_fd_cb = done; |
|
|
|
|
grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer); |
|
|
|
|
if (grpc_event_engine_can_track_errors()) { |
|
|
|
|
/* Stop errors notification. */ |
|
|
|
|
gpr_mu_lock(&tcp->tb_mu); |
|
|
|
|
grpc_core::TracedBuffer::Shutdown( |
|
|
|
|
&tcp->tb_head, tcp->outgoing_buffer_arg, |
|
|
|
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING("endpoint destroyed")); |
|
|
|
|
gpr_mu_unlock(&tcp->tb_mu); |
|
|
|
|
tcp->outgoing_buffer_arg = nullptr; |
|
|
|
|
gpr_atm_no_barrier_store(&tcp->stop_error_notification, true); |
|
|
|
|
grpc_fd_set_error(tcp->em_fd); |
|
|
|
|
} |
|
|
|
|