1 //
2 //
3 // Copyright 2015 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 #include <grpc/support/port_platform.h>
20
21 #include <initializer_list>
22 #include <memory>
23 #include <string>
24
25 #include "absl/strings/str_cat.h"
26 #include "absl/strings/str_format.h"
27
28 #include <grpc/support/log.h>
29
30 #include "src/core/lib/channel/channel_fwd.h"
31 #include "src/core/lib/channel/channel_stack.h"
32 #include "src/core/lib/gprpp/orphanable.h"
33 #include "src/core/lib/gprpp/status_helper.h"
34 #include "src/core/lib/iomgr/error.h"
35 #include "src/core/lib/slice/slice_buffer.h"
36 #include "src/core/lib/transport/connectivity_state.h"
37 #include "src/core/lib/transport/metadata_batch.h"
38 #include "src/core/lib/transport/transport.h"
39
40 // These routines are here to facilitate debugging - they produce string
41 // representations of various transport data structures
42
grpc_transport_stream_op_batch_string(grpc_transport_stream_op_batch * op,bool truncate)43 std::string grpc_transport_stream_op_batch_string(
44 grpc_transport_stream_op_batch* op, bool truncate) {
45 std::string out;
46
47 if (op->send_initial_metadata) {
48 absl::StrAppend(&out, " SEND_INITIAL_METADATA{");
49 if (truncate) {
50 absl::StrAppend(&out, "Length=",
51 op->payload->send_initial_metadata.send_initial_metadata
52 ->TransportSize());
53 } else {
54 absl::StrAppend(&out, op->payload->send_initial_metadata
55 .send_initial_metadata->DebugString());
56 }
57 absl::StrAppend(&out, "}");
58 }
59
60 if (op->send_message) {
61 if (op->payload->send_message.send_message != nullptr) {
62 absl::StrAppendFormat(&out, " SEND_MESSAGE:flags=0x%08x:len=%d",
63 op->payload->send_message.flags,
64 op->payload->send_message.send_message->Length());
65 } else {
66 // This can happen when we check a batch after the transport has
67 // processed and cleared the send_message op.
68 absl::StrAppend(
69 &out, " SEND_MESSAGE(flag and length unknown, already orphaned)");
70 }
71 }
72
73 if (op->send_trailing_metadata) {
74 absl::StrAppend(&out, " SEND_TRAILING_METADATA{");
75 if (truncate) {
76 absl::StrAppend(&out, "Length=",
77 op->payload->send_trailing_metadata
78 .send_trailing_metadata->TransportSize());
79 } else {
80 absl::StrAppend(&out, op->payload->send_trailing_metadata
81 .send_trailing_metadata->DebugString());
82 }
83 absl::StrAppend(&out, "}");
84 }
85
86 if (op->recv_initial_metadata) {
87 absl::StrAppend(&out, " RECV_INITIAL_METADATA");
88 }
89
90 if (op->recv_message) {
91 absl::StrAppend(&out, " RECV_MESSAGE");
92 }
93
94 if (op->recv_trailing_metadata) {
95 absl::StrAppend(&out, " RECV_TRAILING_METADATA");
96 }
97
98 if (op->cancel_stream) {
99 absl::StrAppend(
100 &out, " CANCEL:",
101 grpc_core::StatusToString(op->payload->cancel_stream.cancel_error));
102 }
103
104 return out;
105 }
106
grpc_transport_op_string(grpc_transport_op * op)107 std::string grpc_transport_op_string(grpc_transport_op* op) {
108 std::string out;
109
110 if (op->start_connectivity_watch != nullptr) {
111 absl::StrAppendFormat(
112 &out, " START_CONNECTIVITY_WATCH:watcher=%p:from=%s",
113 op->start_connectivity_watch.get(),
114 grpc_core::ConnectivityStateName(op->start_connectivity_watch_state));
115 }
116
117 if (op->stop_connectivity_watch != nullptr) {
118 absl::StrAppendFormat(&out, " STOP_CONNECTIVITY_WATCH:watcher=%p",
119 op->stop_connectivity_watch);
120 }
121
122 if (!op->disconnect_with_error.ok()) {
123 absl::StrAppend(&out, " DISCONNECT:",
124 grpc_core::StatusToString(op->disconnect_with_error));
125 }
126
127 if (!op->goaway_error.ok()) {
128 absl::StrAppend(
129 &out, " SEND_GOAWAY:", grpc_core::StatusToString(op->goaway_error));
130 }
131
132 if (op->set_accept_stream) {
133 absl::StrAppendFormat(&out, " SET_ACCEPT_STREAM:%p(%p,...)",
134 op->set_accept_stream_fn,
135 op->set_accept_stream_user_data);
136 }
137
138 if (op->bind_pollset != nullptr) {
139 absl::StrAppend(&out, " BIND_POLLSET");
140 }
141
142 if (op->bind_pollset_set != nullptr) {
143 absl::StrAppend(&out, " BIND_POLLSET_SET");
144 }
145
146 if (op->send_ping.on_initiate != nullptr || op->send_ping.on_ack != nullptr) {
147 absl::StrAppend(&out, " SEND_PING");
148 }
149
150 return out;
151 }
152
grpc_call_log_op(const char * file,int line,gpr_log_severity severity,grpc_call_element * elem,grpc_transport_stream_op_batch * op)153 void grpc_call_log_op(const char* file, int line, gpr_log_severity severity,
154 grpc_call_element* elem,
155 grpc_transport_stream_op_batch* op) {
156 gpr_log(file, line, severity, "OP[%s:%p]: %s", elem->filter->name, elem,
157 grpc_transport_stream_op_batch_string(op, false).c_str());
158 }
159