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