Line data Source code
1 : /*
2 : *
3 : * Copyright 2015, Google Inc.
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions are
8 : * met:
9 : *
10 : * * Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * * Redistributions in binary form must reproduce the above
13 : * copyright notice, this list of conditions and the following disclaimer
14 : * in the documentation and/or other materials provided with the
15 : * distribution.
16 : * * Neither the name of Google Inc. nor the names of its
17 : * contributors may be used to endorse or promote products derived from
18 : * this software without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 : * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 : * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 : * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : *
32 : */
33 :
34 : #include <grpc++/server_context.h>
35 :
36 : #include <grpc/grpc.h>
37 : #include <grpc/support/alloc.h>
38 : #include <grpc/support/log.h>
39 : #include <grpc++/impl/call.h>
40 : #include <grpc++/impl/sync.h>
41 : #include <grpc++/support/time.h>
42 :
43 : #include "src/core/channel/compress_filter.h"
44 : #include "src/cpp/common/create_auth_context.h"
45 :
46 : namespace grpc {
47 :
48 : // CompletionOp
49 :
50 3293509 : class ServerContext::CompletionOp GRPC_FINAL : public CallOpSetInterface {
51 : public:
52 : // initial refs: one in the server context, one in the cq
53 1646702 : CompletionOp()
54 : : has_tag_(false),
55 : tag_(nullptr),
56 : refs_(2),
57 : finalized_(false),
58 1646702 : cancelled_(0) {}
59 :
60 : void FillOps(grpc_op* ops, size_t* nops) GRPC_OVERRIDE;
61 : bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE;
62 :
63 : bool CheckCancelled(CompletionQueue* cq);
64 :
65 4 : void set_tag(void* tag) {
66 4 : has_tag_ = true;
67 4 : tag_ = tag;
68 4 : }
69 :
70 : void Unref();
71 :
72 : private:
73 : bool has_tag_;
74 : void* tag_;
75 : grpc::mutex mu_;
76 : int refs_;
77 : bool finalized_;
78 : int cancelled_;
79 : };
80 :
81 1646770 : void ServerContext::CompletionOp::Unref() {
82 1646770 : grpc::unique_lock<grpc::mutex> lock(mu_);
83 1646770 : if (--refs_ == 0) {
84 209535 : lock.unlock();
85 209536 : delete this;
86 1646771 : }
87 1646781 : }
88 :
89 105617 : bool ServerContext::CompletionOp::CheckCancelled(CompletionQueue* cq) {
90 105617 : cq->TryPluck(this);
91 105621 : grpc::lock_guard<grpc::mutex> g(mu_);
92 105621 : return finalized_ ? cancelled_ != 0 : false;
93 : }
94 :
95 1646540 : void ServerContext::CompletionOp::FillOps(grpc_op* ops, size_t* nops) {
96 1646540 : ops->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
97 1646540 : ops->data.recv_close_on_server.cancelled = &cancelled_;
98 1646540 : ops->flags = 0;
99 1646540 : ops->reserved = NULL;
100 1646540 : *nops = 1;
101 1646540 : }
102 :
103 1646592 : bool ServerContext::CompletionOp::FinalizeResult(void** tag, bool* status) {
104 1646592 : grpc::unique_lock<grpc::mutex> lock(mu_);
105 1646756 : finalized_ = true;
106 1646756 : bool ret = false;
107 1646756 : if (has_tag_) {
108 4 : *tag = tag_;
109 4 : ret = true;
110 : }
111 1646756 : if (!*status) cancelled_ = 1;
112 1646756 : if (--refs_ == 0) {
113 1437220 : lock.unlock();
114 1437236 : delete this;
115 : }
116 1647200 : return ret;
117 : }
118 :
119 : // ServerContext body
120 :
121 1508065 : ServerContext::ServerContext()
122 : : completion_op_(nullptr),
123 : has_notify_when_done_tag_(false),
124 : async_notify_when_done_tag_(nullptr),
125 : call_(nullptr),
126 : cq_(nullptr),
127 1508065 : sent_initial_metadata_(false) {}
128 :
129 209493 : ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata* metadata,
130 : size_t metadata_count)
131 : : completion_op_(nullptr),
132 : has_notify_when_done_tag_(false),
133 : async_notify_when_done_tag_(nullptr),
134 : deadline_(deadline),
135 : call_(nullptr),
136 : cq_(nullptr),
137 209493 : sent_initial_metadata_(false) {
138 418994 : for (size_t i = 0; i < metadata_count; i++) {
139 : client_metadata_.insert(std::pair<grpc::string_ref, grpc::string_ref>(
140 209501 : metadata[i].key,
141 419002 : grpc::string_ref(metadata[i].value, metadata[i].value_length)));
142 : }
143 209493 : }
144 :
145 3436271 : ServerContext::~ServerContext() {
146 1717878 : if (call_) {
147 1646526 : grpc_call_destroy(call_);
148 : }
149 1718382 : if (completion_op_) {
150 1646773 : completion_op_->Unref();
151 : }
152 1718396 : }
153 :
154 1646363 : void ServerContext::BeginCompletionOp(Call* call) {
155 1646363 : GPR_ASSERT(!completion_op_);
156 1646363 : completion_op_ = new CompletionOp();
157 1646642 : if (has_notify_when_done_tag_) {
158 4 : completion_op_->set_tag(async_notify_when_done_tag_);
159 : }
160 1646642 : call->PerformOps(completion_op_);
161 1646063 : }
162 :
163 16 : void ServerContext::AddInitialMetadata(const grpc::string& key,
164 : const grpc::string& value) {
165 16 : initial_metadata_.insert(std::make_pair(key, value));
166 16 : }
167 :
168 18 : void ServerContext::AddTrailingMetadata(const grpc::string& key,
169 : const grpc::string& value) {
170 18 : trailing_metadata_.insert(std::make_pair(key, value));
171 18 : }
172 :
173 105621 : bool ServerContext::IsCancelled() const {
174 105621 : return completion_op_ && completion_op_->CheckCancelled(cq_);
175 : }
176 :
177 0 : void ServerContext::set_compression_level(grpc_compression_level level) {
178 : const grpc_compression_algorithm algorithm_for_level =
179 0 : grpc_compression_algorithm_for_level(level);
180 0 : set_compression_algorithm(algorithm_for_level);
181 0 : }
182 :
183 4 : void ServerContext::set_compression_algorithm(
184 : grpc_compression_algorithm algorithm) {
185 4 : char* algorithm_name = NULL;
186 4 : if (!grpc_compression_algorithm_name(algorithm, &algorithm_name)) {
187 : gpr_log(GPR_ERROR, "Name for compression algorithm '%d' unknown.",
188 0 : algorithm);
189 0 : abort();
190 : }
191 4 : GPR_ASSERT(algorithm_name != NULL);
192 4 : AddInitialMetadata(GRPC_COMPRESS_REQUEST_ALGORITHM_KEY, algorithm_name);
193 4 : }
194 :
195 1718194 : void ServerContext::set_call(grpc_call* call) {
196 1718194 : call_ = call;
197 1718194 : auth_context_ = CreateAuthContext(call);
198 1718202 : }
199 :
200 3 : std::shared_ptr<const AuthContext> ServerContext::auth_context() const {
201 3 : if (auth_context_.get() == nullptr) {
202 0 : auth_context_ = CreateAuthContext(call_);
203 : }
204 3 : return auth_context_;
205 : }
206 :
207 4 : grpc::string ServerContext::peer() const {
208 4 : grpc::string peer;
209 4 : if (call_) {
210 4 : char* c_peer = grpc_call_get_peer(call_);
211 4 : peer = c_peer;
212 4 : gpr_free(c_peer);
213 : }
214 4 : return peer;
215 : }
216 :
217 0 : const struct census_context* ServerContext::census_context() const {
218 0 : return grpc_census_call_get_context(call_);
219 : }
220 :
221 : } // namespace grpc
|