1 //
2 // Copyright 2015 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include <grpc/support/port_platform.h>
18
19 #include "src/core/lib/surface/channel.h"
20
21 #include <grpc/compression.h>
22 #include <grpc/grpc.h>
23 #include <grpc/impl/channel_arg_names.h>
24 #include <grpc/support/alloc.h>
25 #include <grpc/support/log.h>
26
27 #include "src/core/lib/channel/channel_args.h"
28 #include "src/core/lib/channel/channel_trace.h"
29 #include "src/core/lib/channel/channelz.h"
30 #include "src/core/lib/compression/compression_internal.h"
31 #include "src/core/lib/debug/stats.h"
32 #include "src/core/lib/debug/stats_data.h"
33 #include "src/core/lib/debug/trace.h"
34 #include "src/core/lib/iomgr/exec_ctx.h"
35 #include "src/core/lib/surface/api_trace.h"
36
37 namespace grpc_core {
38
39 //
40 // Channel::RegisteredCall
41 //
42
RegisteredCall(const char * method_arg,const char * host_arg)43 Channel::RegisteredCall::RegisteredCall(const char* method_arg,
44 const char* host_arg) {
45 path = Slice::FromCopiedString(method_arg);
46 if (host_arg != nullptr && host_arg[0] != 0) {
47 authority = Slice::FromCopiedString(host_arg);
48 }
49 }
50
RegisteredCall(const RegisteredCall & other)51 Channel::RegisteredCall::RegisteredCall(const RegisteredCall& other)
52 : path(other.path.Ref()) {
53 if (other.authority.has_value()) {
54 authority = other.authority->Ref();
55 }
56 }
57
~RegisteredCall()58 Channel::RegisteredCall::~RegisteredCall() {}
59
60 //
61 // Channel
62 //
63
Channel(std::string target,const ChannelArgs & channel_args)64 Channel::Channel(std::string target, const ChannelArgs& channel_args)
65 : target_(std::move(target)),
66 channelz_node_(channel_args.GetObjectRef<channelz::ChannelNode>()),
67 compression_options_(CompressionOptionsFromChannelArgs(channel_args)) {}
68
RegisterCall(const char * method,const char * host)69 Channel::RegisteredCall* Channel::RegisterCall(const char* method,
70 const char* host) {
71 MutexLock lock(&mu_);
72 auto key = std::make_pair(std::string(host != nullptr ? host : ""),
73 std::string(method != nullptr ? method : ""));
74 auto rc_posn = registration_table_.find(key);
75 if (rc_posn != registration_table_.end()) {
76 return &rc_posn->second;
77 }
78 auto insertion_result = registration_table_.insert(
79 {std::move(key), RegisteredCall(method, host)});
80 return &insertion_result.first->second;
81 }
82
83 } // namespace grpc_core
84
85 //
86 // C-core API
87 //
88
grpc_channel_destroy(grpc_channel * channel)89 void grpc_channel_destroy(grpc_channel* channel) {
90 grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
91 grpc_core::ExecCtx exec_ctx;
92 GRPC_API_TRACE("grpc_channel_destroy(channel=%p)", 1, (channel));
93 grpc_channel_destroy_internal(channel);
94 }
95
grpc_channel_create_call(grpc_channel * channel,grpc_call * parent_call,uint32_t propagation_mask,grpc_completion_queue * completion_queue,grpc_slice method,const grpc_slice * host,gpr_timespec deadline,void * reserved)96 grpc_call* grpc_channel_create_call(grpc_channel* channel,
97 grpc_call* parent_call,
98 uint32_t propagation_mask,
99 grpc_completion_queue* completion_queue,
100 grpc_slice method, const grpc_slice* host,
101 gpr_timespec deadline, void* reserved) {
102 GPR_ASSERT(!reserved);
103 grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
104 grpc_core::ExecCtx exec_ctx;
105 return grpc_core::Channel::FromC(channel)->CreateCall(
106 parent_call, propagation_mask, completion_queue, nullptr,
107 grpc_core::Slice(grpc_core::CSliceRef(method)),
108 host != nullptr
109 ? absl::optional<grpc_core::Slice>(grpc_core::CSliceRef(*host))
110 : absl::nullopt,
111 grpc_core::Timestamp::FromTimespecRoundUp(deadline),
112 /*registered_method=*/false);
113 }
114
grpc_channel_register_call(grpc_channel * channel,const char * method,const char * host,void * reserved)115 void* grpc_channel_register_call(grpc_channel* channel, const char* method,
116 const char* host, void* reserved) {
117 GRPC_API_TRACE(
118 "grpc_channel_register_call(channel=%p, method=%s, host=%s, reserved=%p)",
119 4, (channel, method, host, reserved));
120 GPR_ASSERT(!reserved);
121 grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
122 grpc_core::ExecCtx exec_ctx;
123 return grpc_core::Channel::FromC(channel)->RegisterCall(method, host);
124 }
125
grpc_channel_create_registered_call(grpc_channel * channel,grpc_call * parent_call,uint32_t propagation_mask,grpc_completion_queue * completion_queue,void * registered_call_handle,gpr_timespec deadline,void * reserved)126 grpc_call* grpc_channel_create_registered_call(
127 grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask,
128 grpc_completion_queue* completion_queue, void* registered_call_handle,
129 gpr_timespec deadline, void* reserved) {
130 auto* rc =
131 static_cast<grpc_core::Channel::RegisteredCall*>(registered_call_handle);
132 GRPC_API_TRACE(
133 "grpc_channel_create_registered_call("
134 "channel=%p, parent_call=%p, propagation_mask=%x, completion_queue=%p, "
135 "registered_call_handle=%p, "
136 "deadline=gpr_timespec { tv_sec: %" PRId64
137 ", tv_nsec: %d, clock_type: %d }, "
138 "reserved=%p)",
139 9,
140 (channel, parent_call, (unsigned)propagation_mask, completion_queue,
141 registered_call_handle, deadline.tv_sec, deadline.tv_nsec,
142 (int)deadline.clock_type, reserved));
143 GPR_ASSERT(!reserved);
144 grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
145 grpc_core::ExecCtx exec_ctx;
146 return grpc_core::Channel::FromC(channel)->CreateCall(
147 parent_call, propagation_mask, completion_queue, nullptr, rc->path.Ref(),
148 rc->authority.has_value()
149 ? absl::optional<grpc_core::Slice>(rc->authority->Ref())
150 : absl::nullopt,
151 grpc_core::Timestamp::FromTimespecRoundUp(deadline),
152 /*registered_method=*/true);
153 }
154
grpc_channel_get_target(grpc_channel * channel)155 char* grpc_channel_get_target(grpc_channel* channel) {
156 GRPC_API_TRACE("grpc_channel_get_target(channel=%p)", 1, (channel));
157 auto target = grpc_core::Channel::FromC(channel)->target();
158 char* buffer = static_cast<char*>(gpr_zalloc(target.size() + 1));
159 memcpy(buffer, target.data(), target.size());
160 return buffer;
161 }
162
grpc_channel_get_info(grpc_channel * channel,const grpc_channel_info * channel_info)163 void grpc_channel_get_info(grpc_channel* channel,
164 const grpc_channel_info* channel_info) {
165 grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
166 grpc_core::ExecCtx exec_ctx;
167 grpc_core::Channel::FromC(channel)->GetInfo(channel_info);
168 }
169
grpc_channel_reset_connect_backoff(grpc_channel * channel)170 void grpc_channel_reset_connect_backoff(grpc_channel* channel) {
171 grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
172 grpc_core::ExecCtx exec_ctx;
173 GRPC_API_TRACE("grpc_channel_reset_connect_backoff(channel=%p)", 1,
174 (channel));
175 grpc_core::Channel::FromC(channel)->ResetConnectionBackoff();
176 }
177
grpc_channel_support_connectivity_watcher(grpc_channel * channel)178 int grpc_channel_support_connectivity_watcher(grpc_channel* channel) {
179 return grpc_core::Channel::FromC(channel)->SupportsConnectivityWatcher();
180 }
181
grpc_channel_check_connectivity_state(grpc_channel * channel,int try_to_connect)182 grpc_connectivity_state grpc_channel_check_connectivity_state(
183 grpc_channel* channel, int try_to_connect) {
184 grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
185 grpc_core::ExecCtx exec_ctx;
186 GRPC_API_TRACE(
187 "grpc_channel_check_connectivity_state(channel=%p, try_to_connect=%d)", 2,
188 (channel, try_to_connect));
189 return grpc_core::Channel::FromC(channel)->CheckConnectivityState(
190 try_to_connect);
191 }
192
grpc_channel_watch_connectivity_state(grpc_channel * channel,grpc_connectivity_state last_observed_state,gpr_timespec deadline,grpc_completion_queue * cq,void * tag)193 void grpc_channel_watch_connectivity_state(
194 grpc_channel* channel, grpc_connectivity_state last_observed_state,
195 gpr_timespec deadline, grpc_completion_queue* cq, void* tag) {
196 grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
197 grpc_core::ExecCtx exec_ctx;
198 GRPC_API_TRACE(
199 "grpc_channel_watch_connectivity_state("
200 "channel=%p, last_observed_state=%d, "
201 "deadline=gpr_timespec { tv_sec: %" PRId64
202 ", tv_nsec: %d, clock_type: %d }, "
203 "cq=%p, tag=%p)",
204 7,
205 (channel, (int)last_observed_state, deadline.tv_sec, deadline.tv_nsec,
206 (int)deadline.clock_type, cq, tag));
207 return grpc_core::Channel::FromC(channel)->WatchConnectivityState(
208 last_observed_state, grpc_core::Timestamp::FromTimespecRoundUp(deadline),
209 cq, tag);
210 }
211
grpc_channel_ping(grpc_channel * channel,grpc_completion_queue * cq,void * tag,void * reserved)212 void grpc_channel_ping(grpc_channel* channel, grpc_completion_queue* cq,
213 void* tag, void* reserved) {
214 grpc_core::ExecCtx exec_ctx;
215 GRPC_API_TRACE("grpc_channel_ping(channel=%p, cq=%p, tag=%p, reserved=%p)", 4,
216 (channel, cq, tag, reserved));
217 GPR_ASSERT(reserved == nullptr);
218 grpc_core::Channel::FromC(channel)->Ping(cq, tag);
219 }
220