1 //
2 //
3 // Copyright 2020 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 #ifndef GRPCPP_XDS_SERVER_BUILDER_H
20 #define GRPCPP_XDS_SERVER_BUILDER_H
21 
22 #include <grpc/support/port_platform.h>
23 
24 #include <grpcpp/server_builder.h>
25 
26 namespace grpc {
27 
28 class XdsServerServingStatusNotifierInterface {
29  public:
30   struct ServingStatusUpdate {
31     grpc::Status status;
32   };
33 
34   virtual ~XdsServerServingStatusNotifierInterface() = default;
35 
36   // \a uri contains the listening target associated with the notification. Note
37   // that a single target provided to XdsServerBuilder can get resolved to
38   // multiple listening addresses.
39   // The callback is invoked each time there is an update to the serving status.
40   // The API does not provide any guarantees around duplicate updates.
41   // Status::OK signifies that the server is serving, while a non-OK status
42   // signifies that the server is not serving.
43   virtual void OnServingStatusUpdate(std::string uri,
44                                      ServingStatusUpdate update) = 0;
45 };
46 
47 class XdsServerBuilder : public grpc::ServerBuilder {
48  public:
49   // NOTE: class experimental_type is not part of the public API of this class
50   // TODO(yashykt): Integrate into public API when this is no longer
51   // experimental.
52   class experimental_type : public grpc::ServerBuilder::experimental_type {
53    public:
experimental_type(XdsServerBuilder * builder)54     explicit experimental_type(XdsServerBuilder* builder)
55         : ServerBuilder::experimental_type(builder), builder_(builder) {}
56 
57     // EXPERIMENTAL: Sets the drain grace period in ms for older connections
58     // when updates to a Listener is received.
set_drain_grace_time(int drain_grace_time_ms)59     void set_drain_grace_time(int drain_grace_time_ms) {
60       builder_->drain_grace_time_ms_ = drain_grace_time_ms;
61     }
62 
63    private:
64     XdsServerBuilder* builder_;
65   };
66 
67   // It is the responsibility of the application to make sure that \a notifier
68   // outlasts the life of the server. Notifications will start being made
69   // asynchronously once `BuildAndStart()` has been called. Note that it is
70   // possible for notifications to be made before `BuildAndStart()` returns.
set_status_notifier(XdsServerServingStatusNotifierInterface * notifier)71   void set_status_notifier(XdsServerServingStatusNotifierInterface* notifier) {
72     notifier_ = notifier;
73   }
74 
75   /// NOTE: The function experimental() is not stable public API. It is a view
76   /// to the experimental components of this class. It may be changed or removed
77   /// at any time.
experimental()78   experimental_type experimental() { return experimental_type(this); }
79 
80  private:
81   // Called at the beginning of BuildAndStart().
BuildChannelArgs()82   ChannelArguments BuildChannelArgs() override {
83     ChannelArguments args = ServerBuilder::BuildChannelArgs();
84     if (drain_grace_time_ms_ >= 0) {
85       args.SetInt(GRPC_ARG_SERVER_CONFIG_CHANGE_DRAIN_GRACE_TIME_MS,
86                   drain_grace_time_ms_);
87     }
88     grpc_channel_args c_channel_args = args.c_channel_args();
89     grpc_server_config_fetcher* fetcher = grpc_server_config_fetcher_xds_create(
90         {OnServingStatusUpdate, notifier_}, &c_channel_args);
91     if (fetcher != nullptr) set_fetcher(fetcher);
92     return args;
93   }
94 
OnServingStatusUpdate(void * user_data,const char * uri,grpc_serving_status_update update)95   static void OnServingStatusUpdate(void* user_data, const char* uri,
96                                     grpc_serving_status_update update) {
97     if (user_data == nullptr) return;
98     XdsServerServingStatusNotifierInterface* notifier =
99         static_cast<XdsServerServingStatusNotifierInterface*>(user_data);
100     notifier->OnServingStatusUpdate(
101         uri, {grpc::Status(static_cast<StatusCode>(update.code),
102                            update.error_message)});
103   }
104 
105   XdsServerServingStatusNotifierInterface* notifier_ = nullptr;
106   int drain_grace_time_ms_ = -1;
107 };
108 
109 }  // namespace grpc
110 
111 #endif  // GRPCPP_XDS_SERVER_BUILDER_H
112