summaryrefslogtreecommitdiff
path: root/grpc/spm-cpp-include/grpcpp/impl/codegen/server_context.h
blob: cbbd22912d51b9d49469923d757a851831162fa5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
/*
 *
 * Copyright 2019 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#ifndef GRPCPP_IMPL_CODEGEN_SERVER_CONTEXT_H
#define GRPCPP_IMPL_CODEGEN_SERVER_CONTEXT_H

#include <atomic>
#include <cassert>
#include <map>
#include <memory>
#include <type_traits>
#include <vector>

#include <grpc/impl/codegen/port_platform.h>

#include <grpc/impl/codegen/compression_types.h>
#include <grpcpp/impl/codegen/call.h>
#include <grpcpp/impl/codegen/call_op_set.h>
#include <grpcpp/impl/codegen/callback_common.h>
#include <grpcpp/impl/codegen/completion_queue_tag.h>
#include <grpcpp/impl/codegen/config.h>
#include <grpcpp/impl/codegen/create_auth_context.h>
#include <grpcpp/impl/codegen/message_allocator.h>
#include <grpcpp/impl/codegen/metadata_map.h>
#include <grpcpp/impl/codegen/rpc_service_method.h>
#include <grpcpp/impl/codegen/security/auth_context.h>
#include <grpcpp/impl/codegen/server_callback.h>
#include <grpcpp/impl/codegen/server_interceptor.h>
#include <grpcpp/impl/codegen/status.h>
#include <grpcpp/impl/codegen/string_ref.h>
#include <grpcpp/impl/codegen/time.h>

struct grpc_metadata;
struct grpc_call;
struct census_context;

namespace grpc {
template <class W, class R>
class ServerAsyncReader;
template <class W>
class ServerAsyncWriter;
template <class W>
class ServerAsyncResponseWriter;
template <class W, class R>
class ServerAsyncReaderWriter;
template <class R>
class ServerReader;
template <class W>
class ServerWriter;

namespace internal {
template <class ServiceType, class RequestType, class ResponseType>
class BidiStreamingHandler;
template <class RequestType, class ResponseType>
class CallbackUnaryHandler;
template <class RequestType, class ResponseType>
class CallbackClientStreamingHandler;
template <class RequestType, class ResponseType>
class CallbackServerStreamingHandler;
template <class RequestType, class ResponseType>
class CallbackBidiHandler;
template <class ServiceType, class RequestType, class ResponseType>
class ClientStreamingHandler;
template <class ResponseType>
void UnaryRunHandlerHelper(const MethodHandler::HandlerParameter&,
                           ResponseType*, Status&);
template <class ServiceType, class RequestType, class ResponseType,
          class BaseRequestType, class BaseResponseType>
class RpcMethodHandler;
template <class Base>
class FinishOnlyReactor;
template <class W, class R>
class ServerReaderWriterBody;
template <class ServiceType, class RequestType, class ResponseType>
class ServerStreamingHandler;
class ServerReactor;
template <class Streamer, bool WriteNeeded>
class TemplatedBidiStreamingHandler;
template <::grpc::StatusCode code>
class ErrorMethodHandler;
}  // namespace internal

class ClientContext;
class CompletionQueue;
class GenericServerContext;
class Server;
class ServerInterface;
class ContextAllocator;

// TODO(vjpai): Remove namespace experimental when de-experimentalized fully.
namespace experimental {

typedef ::grpc::ServerContextBase ServerContextBase;
typedef ::grpc::CallbackServerContext CallbackServerContext;

}  // namespace experimental

#ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL
namespace experimental {
#endif
class GenericCallbackServerContext;
#ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL
}  // namespace experimental
#endif
namespace internal {
class Call;
}  // namespace internal

namespace testing {
class InteropServerContextInspector;
class ServerContextTestSpouse;
class DefaultReactorTestPeer;
}  // namespace testing

/// Base class of ServerContext. Experimental until callback API is final.
class ServerContextBase {
 public:
  virtual ~ServerContextBase();

  /// Return the deadline for the server call.
  std::chrono::system_clock::time_point deadline() const {
    return ::grpc::Timespec2Timepoint(deadline_);
  }

  /// Return a \a gpr_timespec representation of the server call's deadline.
  gpr_timespec raw_deadline() const { return deadline_; }

  /// Add the (\a key, \a value) pair to the initial metadata
  /// associated with a server call. These are made available at the client side
  /// by the \a grpc::ClientContext::GetServerInitialMetadata() method.
  ///
  /// \warning This method should only be called before sending initial metadata
  /// to the client (which can happen explicitly, or implicitly when sending a
  /// a response message or status to the client).
  ///
  /// \param key The metadata key. If \a value is binary data, it must
  /// end in "-bin".
  /// \param value The metadata value. If its value is binary, the key name
  /// must end in "-bin".
  ///
  /// Metadata must conform to the following format:
  /// Custom-Metadata -> Binary-Header / ASCII-Header
  /// Binary-Header -> {Header-Name "-bin" } {binary value}
  /// ASCII-Header -> Header-Name ASCII-Value
  /// Header-Name -> 1*( %x30-39 / %x61-7A / "_" / "-" / ".") ; 0-9 a-z _ - .
  /// ASCII-Value -> 1*( %x20-%x7E ) ; space and printable ASCII
  void AddInitialMetadata(const std::string& key, const std::string& value);

  /// Add the (\a key, \a value) pair to the initial metadata
  /// associated with a server call. These are made available at the client
  /// side by the \a grpc::ClientContext::GetServerTrailingMetadata() method.
  ///
  /// \warning This method should only be called before sending trailing
  /// metadata to the client (which happens when the call is finished and a
  /// status is sent to the client).
  ///
  /// \param key The metadata key. If \a value is binary data,
  /// it must end in "-bin".
  /// \param value The metadata value. If its value is binary, the key name
  /// must end in "-bin".
  ///
  /// Metadata must conform to the following format:
  /// Custom-Metadata -> Binary-Header / ASCII-Header
  /// Binary-Header -> {Header-Name "-bin" } {binary value}
  /// ASCII-Header -> Header-Name ASCII-Value
  /// Header-Name -> 1*( %x30-39 / %x61-7A / "_" / "-" / ".") ; 0-9 a-z _ - .
  /// ASCII-Value -> 1*( %x20-%x7E ) ; space and printable ASCII
  void AddTrailingMetadata(const std::string& key, const std::string& value);

  /// Return whether this RPC failed before the server could provide its status
  /// back to the client. This could be because of explicit API cancellation
  /// from the client-side or server-side, because of deadline exceeded, network
  /// connection reset, HTTP/2 parameter configuration (e.g., max message size,
  /// max connection age), etc. It does NOT include failure due to a non-OK
  /// status return from the server application's request handler, including
  /// Status::CANCELLED.
  ///
  /// IsCancelled is always safe to call when using sync or callback API.
  /// When using async API, it is only safe to call IsCancelled after
  /// the AsyncNotifyWhenDone tag has been delivered. Thread-safe.
  bool IsCancelled() const;

  /// Cancel the Call from the server. This is a best-effort API and
  /// depending on when it is called, the RPC may still appear successful to
  /// the client. For example, if TryCancel() is called on a separate thread, it
  /// might race with the server handler which might return success to the
  /// client before TryCancel() was even started by the thread.
  ///
  /// It is the caller's responsibility to prevent such races and ensure that if
  /// TryCancel() is called, the serverhandler must return Status::CANCELLED.
  /// The only exception is that if the serverhandler is already returning an
  /// error status code, it is ok to not return Status::CANCELLED even if
  /// TryCancel() was called.
  ///
  /// For reasons such as the above, it is generally preferred to explicitly
  /// finish an RPC by returning Status::CANCELLED rather than using TryCancel.
  ///
  /// Note that TryCancel() does not change any of the tags that are pending
  /// on the completion queue. All pending tags will still be delivered
  /// (though their ok result may reflect the effect of cancellation).
  void TryCancel() const;

  /// Return a collection of initial metadata key-value pairs sent from the
  /// client. Note that keys may happen more than
  /// once (ie, a \a std::multimap is returned).
  ///
  /// It is safe to use this method after initial metadata has been received,
  /// Calls always begin with the client sending initial metadata, so this is
  /// safe to access as soon as the call has begun on the server side.
  ///
  /// \return A multimap of initial metadata key-value pairs from the server.
  const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata()
      const {
    return *client_metadata_.map();
  }

  /// Return the compression algorithm to be used by the server call.
  grpc_compression_level compression_level() const {
    return compression_level_;
  }

  /// Set \a level to be the compression level used for the server call.
  ///
  /// \param level The compression level used for the server call.
  void set_compression_level(grpc_compression_level level) {
    compression_level_set_ = true;
    compression_level_ = level;
  }

  /// Return a bool indicating whether the compression level for this call
  /// has been set (either implicitly or through a previous call to
  /// \a set_compression_level.
  bool compression_level_set() const { return compression_level_set_; }

  /// Return the compression algorithm the server call will request be used.
  /// Note that the gRPC runtime may decide to ignore this request, for example,
  /// due to resource constraints, or if the server is aware the client doesn't
  /// support the requested algorithm.
  grpc_compression_algorithm compression_algorithm() const {
    return compression_algorithm_;
  }
  /// Set \a algorithm to be the compression algorithm used for the server call.
  ///
  /// \param algorithm The compression algorithm used for the server call.
  void set_compression_algorithm(grpc_compression_algorithm algorithm);

  /// Set the serialized load reporting costs in \a cost_data for the call.
  void SetLoadReportingCosts(const std::vector<std::string>& cost_data);

  /// Return the authentication context for this server call.
  ///
  /// \see grpc::AuthContext.
  std::shared_ptr<const ::grpc::AuthContext> auth_context() const {
    if (auth_context_ == nullptr) {
      auth_context_ = ::grpc::CreateAuthContext(call_.call);
    }
    return auth_context_;
  }

  /// Return the peer uri in a string.
  /// WARNING: this value is never authenticated or subject to any security
  /// related code. It must not be used for any authentication related
  /// functionality. Instead, use auth_context.
  std::string peer() const;

  /// Get the census context associated with this server call.
  const struct census_context* census_context() const;

  /// Should be used for framework-level extensions only.
  /// Applications never need to call this method.
  grpc_call* c_call() { return call_.call; }

 protected:
  /// Async only. Has to be called before the rpc starts.
  /// Returns the tag in completion queue when the rpc finishes.
  /// IsCancelled() can then be called to check whether the rpc was cancelled.
  /// TODO(vjpai): Fix this so that the tag is returned even if the call never
  /// starts (https://github.com/grpc/grpc/issues/10136).
  void AsyncNotifyWhenDone(void* tag) {
    has_notify_when_done_tag_ = true;
    async_notify_when_done_tag_ = tag;
  }

  /// NOTE: This is an API for advanced users who need custom allocators.
  /// Get and maybe mutate the allocator state associated with the current RPC.
  /// Currently only applicable for callback unary RPC methods.
  /// WARNING: This is experimental API and could be changed or removed.
  ::grpc::experimental::RpcAllocatorState* GetRpcAllocatorState() {
    return message_allocator_state_;
  }

  /// Get a library-owned default unary reactor for use in minimal reaction
  /// cases. This supports typical unary RPC usage of providing a response and
  /// status. It supports immediate Finish (finish from within the method
  /// handler) or delayed Finish (finish called after the method handler
  /// invocation). It does not support reacting to cancellation or completion,
  /// or early sending of initial metadata. Since this is a library-owned
  /// reactor, it should not be delete'd or freed in any way. This is more
  /// efficient than creating a user-owned reactor both because of avoiding an
  /// allocation and because its minimal reactions are optimized using a core
  /// surface flag that allows their reactions to run inline without any
  /// thread-hop.
  ///
  /// This method should not be called more than once or called after return
  /// from the method handler.
  ///
  /// WARNING: This is experimental API and could be changed or removed.
  ::grpc::ServerUnaryReactor* DefaultReactor() {
    // Short-circuit the case where a default reactor was already set up by
    // the TestPeer.
    if (test_unary_ != nullptr) {
      return reinterpret_cast<Reactor*>(&default_reactor_);
    }
    new (&default_reactor_) Reactor;
#ifndef NDEBUG
    bool old = false;
    assert(default_reactor_used_.compare_exchange_strong(
        old, true, std::memory_order_relaxed));
#else
    default_reactor_used_.store(true, std::memory_order_relaxed);
#endif
    return reinterpret_cast<Reactor*>(&default_reactor_);
  }

  /// Constructors for use by derived classes
  ServerContextBase();
  ServerContextBase(gpr_timespec deadline, grpc_metadata_array* arr);

  void set_context_allocator(ContextAllocator* context_allocator) {
    context_allocator_ = context_allocator;
  }

  ContextAllocator* context_allocator() const { return context_allocator_; }

 private:
  friend class ::grpc::testing::InteropServerContextInspector;
  friend class ::grpc::testing::ServerContextTestSpouse;
  friend class ::grpc::testing::DefaultReactorTestPeer;
  friend class ::grpc::ServerInterface;
  friend class ::grpc::Server;
  template <class W, class R>
  friend class ::grpc::ServerAsyncReader;
  template <class W>
  friend class ::grpc::ServerAsyncWriter;
  template <class W>
  friend class ::grpc::ServerAsyncResponseWriter;
  template <class W, class R>
  friend class ::grpc::ServerAsyncReaderWriter;
  template <class R>
  friend class ::grpc::ServerReader;
  template <class W>
  friend class ::grpc::ServerWriter;
  template <class W, class R>
  friend class ::grpc::internal::ServerReaderWriterBody;
  template <class ResponseType>
  friend void ::grpc::internal::UnaryRunHandlerHelper(
      const internal::MethodHandler::HandlerParameter& param, ResponseType* rsp,
      Status& status);
  template <class ServiceType, class RequestType, class ResponseType,
            class BaseRequestType, class BaseResponseType>
  friend class ::grpc::internal::RpcMethodHandler;
  template <class ServiceType, class RequestType, class ResponseType>
  friend class ::grpc::internal::ClientStreamingHandler;
  template <class ServiceType, class RequestType, class ResponseType>
  friend class ::grpc::internal::ServerStreamingHandler;
  template <class Streamer, bool WriteNeeded>
  friend class ::grpc::internal::TemplatedBidiStreamingHandler;
  template <class RequestType, class ResponseType>
  friend class ::grpc::internal::CallbackUnaryHandler;
  template <class RequestType, class ResponseType>
  friend class ::grpc::internal::CallbackClientStreamingHandler;
  template <class RequestType, class ResponseType>
  friend class ::grpc::internal::CallbackServerStreamingHandler;
  template <class RequestType, class ResponseType>
  friend class ::grpc::internal::CallbackBidiHandler;
  template <::grpc::StatusCode code>
  friend class ::grpc::internal::ErrorMethodHandler;
  template <class Base>
  friend class ::grpc::internal::FinishOnlyReactor;
  friend class ::grpc::ClientContext;
  friend class ::grpc::GenericServerContext;
#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
  friend class ::grpc::GenericCallbackServerContext;
#else
  friend class ::grpc::experimental::GenericCallbackServerContext;
#endif

  /// Prevent copying.
  ServerContextBase(const ServerContextBase&);
  ServerContextBase& operator=(const ServerContextBase&);

  class CompletionOp;

  void BeginCompletionOp(
      ::grpc::internal::Call* call, std::function<void(bool)> callback,
      ::grpc::internal::ServerCallbackCall* callback_controller);
  /// Return the tag queued by BeginCompletionOp()
  ::grpc::internal::CompletionQueueTag* GetCompletionOpTag();

  void set_call(grpc_call* call) { call_.call = call; }

  void BindDeadlineAndMetadata(gpr_timespec deadline, grpc_metadata_array* arr);

  uint32_t initial_metadata_flags() const { return 0; }

  ::grpc::experimental::ServerRpcInfo* set_server_rpc_info(
      const char* method, ::grpc::internal::RpcMethod::RpcType type,
      const std::vector<std::unique_ptr<
          ::grpc::experimental::ServerInterceptorFactoryInterface>>& creators) {
    if (!creators.empty()) {
      rpc_info_ = new ::grpc::experimental::ServerRpcInfo(this, method, type);
      rpc_info_->RegisterInterceptors(creators);
    }
    return rpc_info_;
  }

  void set_message_allocator_state(
      ::grpc::experimental::RpcAllocatorState* allocator_state) {
    message_allocator_state_ = allocator_state;
  }

  struct CallWrapper {
    ~CallWrapper();

    grpc_call* call = nullptr;
  };

  // NOTE: call_ must be the first data member of this object so that its
  //       destructor is the last to be called, since its destructor may unref
  //       the underlying core call which holds the arena that may be used to
  //       hold this object.
  CallWrapper call_;

  CompletionOp* completion_op_ = nullptr;
  bool has_notify_when_done_tag_ = false;
  void* async_notify_when_done_tag_ = nullptr;
  ::grpc::internal::CallbackWithSuccessTag completion_tag_;

  gpr_timespec deadline_;
  ::grpc::CompletionQueue* cq_ = nullptr;
  bool sent_initial_metadata_ = false;
  mutable std::shared_ptr<const ::grpc::AuthContext> auth_context_;
  mutable ::grpc::internal::MetadataMap client_metadata_;
  std::multimap<std::string, std::string> initial_metadata_;
  std::multimap<std::string, std::string> trailing_metadata_;

  bool compression_level_set_ = false;
  grpc_compression_level compression_level_;
  grpc_compression_algorithm compression_algorithm_;

  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
                              ::grpc::internal::CallOpSendMessage>
      pending_ops_;
  bool has_pending_ops_ = false;

  ::grpc::experimental::ServerRpcInfo* rpc_info_ = nullptr;
  ::grpc::experimental::RpcAllocatorState* message_allocator_state_ = nullptr;
  ContextAllocator* context_allocator_ = nullptr;

  class Reactor : public ::grpc::ServerUnaryReactor {
   public:
    void OnCancel() override {}
    void OnDone() override {}
    // Override InternalInlineable for this class since its reactions are
    // trivial and thus do not need to be run from the executor (triggering a
    // thread hop). This should only be used by internal reactors (thus the
    // name) and not by user application code.
    bool InternalInlineable() override { return true; }
  };

  void SetupTestDefaultReactor(std::function<void(::grpc::Status)> func) {
    // NOLINTNEXTLINE(modernize-make-unique)
    test_unary_.reset(new TestServerCallbackUnary(this, std::move(func)));
  }
  bool test_status_set() const {
    return (test_unary_ != nullptr) && test_unary_->status_set();
  }
  ::grpc::Status test_status() const { return test_unary_->status(); }

  class TestServerCallbackUnary : public ::grpc::ServerCallbackUnary {
   public:
    TestServerCallbackUnary(ServerContextBase* ctx,
                            std::function<void(::grpc::Status)> func)
        : reactor_(ctx->DefaultReactor()), func_(std::move(func)) {
      this->BindReactor(reactor_);
    }
    void Finish(::grpc::Status s) override {
      status_ = s;
      func_(std::move(s));
      status_set_.store(true, std::memory_order_release);
    }
    void SendInitialMetadata() override {}

    bool status_set() const {
      return status_set_.load(std::memory_order_acquire);
    }
    ::grpc::Status status() const { return status_; }

   private:
    void CallOnDone() override {}
    ::grpc::internal::ServerReactor* reactor() override { return reactor_; }

    ::grpc::ServerUnaryReactor* const reactor_;
    std::atomic_bool status_set_{false};
    ::grpc::Status status_;
    const std::function<void(::grpc::Status s)> func_;
  };

  typename std::aligned_storage<sizeof(Reactor), alignof(Reactor)>::type
      default_reactor_;
  std::atomic_bool default_reactor_used_{false};
  std::unique_ptr<TestServerCallbackUnary> test_unary_;
};

/// A ServerContext or CallbackServerContext allows the code implementing a
/// service handler to:
///
/// - Add custom initial and trailing metadata key-value pairs that will
///   propagated to the client side.
/// - Control call settings such as compression and authentication.
/// - Access metadata coming from the client.
/// - Get performance metrics (ie, census).
///
/// Context settings are only relevant to the call handler they are supplied to,
/// that is to say, they aren't sticky across multiple calls. Some of these
/// settings, such as the compression options, can be made persistent at server
/// construction time by specifying the appropriate \a ChannelArguments
/// to a \a grpc::ServerBuilder, via \a ServerBuilder::AddChannelArgument.
///
/// \warning ServerContext instances should \em not be reused across rpcs.
class ServerContext : public ServerContextBase {
 public:
  ServerContext() {}  // for async calls

  using ServerContextBase::AddInitialMetadata;
  using ServerContextBase::AddTrailingMetadata;
  using ServerContextBase::auth_context;
  using ServerContextBase::c_call;
  using ServerContextBase::census_context;
  using ServerContextBase::client_metadata;
  using ServerContextBase::compression_algorithm;
  using ServerContextBase::compression_level;
  using ServerContextBase::compression_level_set;
  using ServerContextBase::deadline;
  using ServerContextBase::IsCancelled;
  using ServerContextBase::peer;
  using ServerContextBase::raw_deadline;
  using ServerContextBase::set_compression_algorithm;
  using ServerContextBase::set_compression_level;
  using ServerContextBase::SetLoadReportingCosts;
  using ServerContextBase::TryCancel;

  // Sync/CQ-based Async ServerContext only
  using ServerContextBase::AsyncNotifyWhenDone;

 private:
  // Constructor for internal use by server only
  friend class ::grpc::Server;
  ServerContext(gpr_timespec deadline, grpc_metadata_array* arr)
      : ServerContextBase(deadline, arr) {}

  // CallbackServerContext only
  using ServerContextBase::DefaultReactor;
  using ServerContextBase::GetRpcAllocatorState;

  /// Prevent copying.
  ServerContext(const ServerContext&) = delete;
  ServerContext& operator=(const ServerContext&) = delete;
};

class CallbackServerContext : public ServerContextBase {
 public:
  /// Public constructors are for direct use only by mocking tests. In practice,
  /// these objects will be owned by the library.
  CallbackServerContext() {}

  using ServerContextBase::AddInitialMetadata;
  using ServerContextBase::AddTrailingMetadata;
  using ServerContextBase::auth_context;
  using ServerContextBase::c_call;
  using ServerContextBase::census_context;
  using ServerContextBase::client_metadata;
  using ServerContextBase::compression_algorithm;
  using ServerContextBase::compression_level;
  using ServerContextBase::compression_level_set;
  using ServerContextBase::context_allocator;
  using ServerContextBase::deadline;
  using ServerContextBase::IsCancelled;
  using ServerContextBase::peer;
  using ServerContextBase::raw_deadline;
  using ServerContextBase::set_compression_algorithm;
  using ServerContextBase::set_compression_level;
  using ServerContextBase::set_context_allocator;
  using ServerContextBase::SetLoadReportingCosts;
  using ServerContextBase::TryCancel;

  // CallbackServerContext only
  using ServerContextBase::DefaultReactor;
  using ServerContextBase::GetRpcAllocatorState;

 private:
  // Sync/CQ-based Async ServerContext only
  using ServerContextBase::AsyncNotifyWhenDone;

  /// Prevent copying.
  CallbackServerContext(const CallbackServerContext&) = delete;
  CallbackServerContext& operator=(const CallbackServerContext&) = delete;
};

/// A CallbackServerContext allows users to use the contents of the
/// CallbackServerContext or GenericCallbackServerContext structure for the
/// callback API.
/// The library will invoke the allocator any time a new call is initiated.
/// and call the Release method after the server OnDone.
class ContextAllocator {
 public:
  virtual ~ContextAllocator() {}

  virtual CallbackServerContext* NewCallbackServerContext() { return nullptr; }

#ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL
  virtual experimental::GenericCallbackServerContext*
  NewGenericCallbackServerContext() {
    return nullptr;
  }
#else
  virtual GenericCallbackServerContext* NewGenericCallbackServerContext() {
    return nullptr;
  }
#endif

  virtual void Release(CallbackServerContext*) {}

#ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL
  virtual void Release(experimental::GenericCallbackServerContext*) {}
#else
  virtual void Release(GenericCallbackServerContext*) {}
#endif
};

}  // namespace grpc

static_assert(
    std::is_base_of<::grpc::ServerContextBase, ::grpc::ServerContext>::value,
    "improper base class");
static_assert(std::is_base_of<::grpc::ServerContextBase,
                              ::grpc::CallbackServerContext>::value,
              "improper base class");
static_assert(sizeof(::grpc::ServerContextBase) ==
                  sizeof(::grpc::ServerContext),
              "wrong size");
static_assert(sizeof(::grpc::ServerContextBase) ==
                  sizeof(::grpc::CallbackServerContext),
              "wrong size");

#endif  // GRPCPP_IMPL_CODEGEN_SERVER_CONTEXT_H