• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 GRPC_SRC_CORE_EXT_FILTERS_HTTP_MESSAGE_COMPRESS_COMPRESSION_FILTER_H
20 #define GRPC_SRC_CORE_EXT_FILTERS_HTTP_MESSAGE_COMPRESS_COMPRESSION_FILTER_H
21 
22 #include <grpc/impl/compression_types.h>
23 #include <grpc/support/port_platform.h>
24 #include <stddef.h>
25 #include <stdint.h>
26 
27 #include "absl/status/statusor.h"
28 #include "absl/strings/string_view.h"
29 #include "absl/types/optional.h"
30 #include "src/core/lib/channel/channel_args.h"
31 #include "src/core/lib/channel/channel_fwd.h"
32 #include "src/core/lib/channel/promise_based_filter.h"
33 #include "src/core/lib/compression/compression_internal.h"
34 #include "src/core/lib/promise/arena_promise.h"
35 #include "src/core/lib/transport/metadata_batch.h"
36 #include "src/core/lib/transport/transport.h"
37 
38 namespace grpc_core {
39 
40 /// Compression filter for messages.
41 ///
42 /// See <grpc/compression.h> for the available compression settings.
43 ///
44 /// Compression settings may come from:
45 /// - Channel configuration, as established at channel creation time.
46 /// - The metadata accompanying the outgoing data to be compressed. This is
47 ///   taken as a request only. We may choose not to honor it. The metadata key
48 ///   is given by \a GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY.
49 ///
50 /// Compression can be disabled for concrete messages (for instance in order to
51 /// prevent CRIME/BEAST type attacks) by having the GRPC_WRITE_NO_COMPRESS set
52 /// in the MessageHandle flags.
53 ///
54 /// The attempted compression mechanism is added to the resulting initial
55 /// metadata under the 'grpc-encoding' key.
56 ///
57 /// If compression is actually performed, the MessageHandle's flag is modified
58 /// to incorporate GRPC_WRITE_INTERNAL_COMPRESS. Otherwise, and regardless of
59 /// the aforementioned 'grpc-encoding' metadata value, data will pass through
60 /// uncompressed.
61 
62 class ChannelCompression {
63  public:
64   explicit ChannelCompression(const ChannelArgs& args);
65 
66   struct DecompressArgs {
67     grpc_compression_algorithm algorithm;
68     absl::optional<uint32_t> max_recv_message_length;
69   };
70 
default_compression_algorithm()71   grpc_compression_algorithm default_compression_algorithm() const {
72     return default_compression_algorithm_;
73   }
74 
enabled_compression_algorithms()75   CompressionAlgorithmSet enabled_compression_algorithms() const {
76     return enabled_compression_algorithms_;
77   }
78 
79   grpc_compression_algorithm HandleOutgoingMetadata(
80       grpc_metadata_batch& outgoing_metadata);
81   DecompressArgs HandleIncomingMetadata(
82       const grpc_metadata_batch& incoming_metadata);
83 
84   // Compress one message synchronously.
85   MessageHandle CompressMessage(MessageHandle message,
86                                 grpc_compression_algorithm algorithm) const;
87   // Decompress one message synchronously.
88   absl::StatusOr<MessageHandle> DecompressMessage(bool is_client,
89                                                   MessageHandle message,
90                                                   DecompressArgs args) const;
91 
92  private:
93   // Max receive message length, if set.
94   absl::optional<uint32_t> max_recv_size_;
95   size_t message_size_service_config_parser_index_;
96   // The default, channel-level, compression algorithm.
97   grpc_compression_algorithm default_compression_algorithm_;
98   // Enabled compression algorithms.
99   CompressionAlgorithmSet enabled_compression_algorithms_;
100   // Is compression enabled?
101   bool enable_compression_;
102   // Is decompression enabled?
103   bool enable_decompression_;
104 };
105 
106 class ClientCompressionFilter final
107     : public ImplementChannelFilter<ClientCompressionFilter> {
108  public:
109   static const grpc_channel_filter kFilter;
110 
TypeName()111   static absl::string_view TypeName() { return "compression"; }
112 
113   static absl::StatusOr<std::unique_ptr<ClientCompressionFilter>> Create(
114       const ChannelArgs& args, ChannelFilter::Args filter_args);
115 
ClientCompressionFilter(const ChannelArgs & args)116   explicit ClientCompressionFilter(const ChannelArgs& args)
117       : compression_engine_(args) {}
118 
119   // Construct a promise for one call.
120   class Call {
121    public:
122     void OnClientInitialMetadata(ClientMetadata& md,
123                                  ClientCompressionFilter* filter);
124     MessageHandle OnClientToServerMessage(MessageHandle message,
125                                           ClientCompressionFilter* filter);
126 
127     void OnServerInitialMetadata(ServerMetadata& md,
128                                  ClientCompressionFilter* filter);
129     absl::StatusOr<MessageHandle> OnServerToClientMessage(
130         MessageHandle message, ClientCompressionFilter* filter);
131 
132     static const NoInterceptor OnClientToServerHalfClose;
133     static const NoInterceptor OnServerTrailingMetadata;
134     static const NoInterceptor OnFinalize;
135 
136    private:
137     grpc_compression_algorithm compression_algorithm_;
138     ChannelCompression::DecompressArgs decompress_args_;
139   };
140 
141  private:
142   ChannelCompression compression_engine_;
143 };
144 
145 class ServerCompressionFilter final
146     : public ImplementChannelFilter<ServerCompressionFilter> {
147  public:
148   static const grpc_channel_filter kFilter;
149 
TypeName()150   static absl::string_view TypeName() { return "compression"; }
151 
152   static absl::StatusOr<std::unique_ptr<ServerCompressionFilter>> Create(
153       const ChannelArgs& args, ChannelFilter::Args filter_args);
154 
ServerCompressionFilter(const ChannelArgs & args)155   explicit ServerCompressionFilter(const ChannelArgs& args)
156       : compression_engine_(args) {}
157 
158   // Construct a promise for one call.
159   class Call {
160    public:
161     void OnClientInitialMetadata(ClientMetadata& md,
162                                  ServerCompressionFilter* filter);
163     absl::StatusOr<MessageHandle> OnClientToServerMessage(
164         MessageHandle message, ServerCompressionFilter* filter);
165 
166     void OnServerInitialMetadata(ServerMetadata& md,
167                                  ServerCompressionFilter* filter);
168     MessageHandle OnServerToClientMessage(MessageHandle message,
169                                           ServerCompressionFilter* filter);
170 
171     static const NoInterceptor OnClientToServerHalfClose;
172     static const NoInterceptor OnServerTrailingMetadata;
173     static const NoInterceptor OnFinalize;
174 
175    private:
176     ChannelCompression::DecompressArgs decompress_args_;
177     grpc_compression_algorithm compression_algorithm_;
178   };
179 
180  private:
181   ChannelCompression compression_engine_;
182 };
183 
184 }  // namespace grpc_core
185 
186 #endif  // GRPC_SRC_CORE_EXT_FILTERS_HTTP_MESSAGE_COMPRESS_COMPRESSION_FILTER_H
187