xref: /aosp_15_r20/external/cronet/net/websockets/websocket_inflater.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2013 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef NET_WEBSOCKETS_WEBSOCKET_INFLATER_H_
6*6777b538SAndroid Build Coastguard Worker #define NET_WEBSOCKETS_WEBSOCKET_INFLATER_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include <memory>
11*6777b538SAndroid Build Coastguard Worker #include <utility>
12*6777b538SAndroid Build Coastguard Worker #include <vector>
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #include "base/containers/circular_deque.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/memory/scoped_refptr.h"
16*6777b538SAndroid Build Coastguard Worker #include "net/base/net_export.h"
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker extern "C" struct z_stream_s;
19*6777b538SAndroid Build Coastguard Worker 
20*6777b538SAndroid Build Coastguard Worker namespace net {
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker class IOBufferWithSize;
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker // WebSocketInflater uncompresses data compressed by DEFLATE algorithm.
25*6777b538SAndroid Build Coastguard Worker class NET_EXPORT_PRIVATE WebSocketInflater {
26*6777b538SAndroid Build Coastguard Worker  public:
27*6777b538SAndroid Build Coastguard Worker   WebSocketInflater();
28*6777b538SAndroid Build Coastguard Worker   // |input_queue_capacity| is a capacity for each contiguous block in the
29*6777b538SAndroid Build Coastguard Worker   // input queue. The input queue can grow without limit.
30*6777b538SAndroid Build Coastguard Worker   WebSocketInflater(size_t input_queue_capacity, size_t output_buffer_capacity);
31*6777b538SAndroid Build Coastguard Worker 
32*6777b538SAndroid Build Coastguard Worker   WebSocketInflater(const WebSocketInflater&) = delete;
33*6777b538SAndroid Build Coastguard Worker   WebSocketInflater& operator=(const WebSocketInflater&) = delete;
34*6777b538SAndroid Build Coastguard Worker 
35*6777b538SAndroid Build Coastguard Worker   ~WebSocketInflater();
36*6777b538SAndroid Build Coastguard Worker 
37*6777b538SAndroid Build Coastguard Worker   // Returns true if there is no error.
38*6777b538SAndroid Build Coastguard Worker   // |window_bits| must be between 8 and 15 (both inclusive).
39*6777b538SAndroid Build Coastguard Worker   // This function must be called exactly once before calling any of the
40*6777b538SAndroid Build Coastguard Worker   // following functions.
41*6777b538SAndroid Build Coastguard Worker   bool Initialize(int window_bits);
42*6777b538SAndroid Build Coastguard Worker 
43*6777b538SAndroid Build Coastguard Worker   // Adds bytes to |stream_|.
44*6777b538SAndroid Build Coastguard Worker   // Returns true if there is no error.
45*6777b538SAndroid Build Coastguard Worker   // If the size of the output data reaches the capacity of the output buffer,
46*6777b538SAndroid Build Coastguard Worker   // the following input data will be "choked", i.e. stored in the input queue,
47*6777b538SAndroid Build Coastguard Worker   // staying compressed.
48*6777b538SAndroid Build Coastguard Worker   bool AddBytes(const char* data, size_t size);
49*6777b538SAndroid Build Coastguard Worker 
50*6777b538SAndroid Build Coastguard Worker   // Flushes the input.
51*6777b538SAndroid Build Coastguard Worker   // Returns true if there is no error.
52*6777b538SAndroid Build Coastguard Worker   bool Finish();
53*6777b538SAndroid Build Coastguard Worker 
54*6777b538SAndroid Build Coastguard Worker   // Returns up to |size| bytes of the decompressed output.
55*6777b538SAndroid Build Coastguard Worker   // Returns null if there is an inflation error.
56*6777b538SAndroid Build Coastguard Worker   // The returned bytes will be dropped from the current output and never be
57*6777b538SAndroid Build Coastguard Worker   // returned again.
58*6777b538SAndroid Build Coastguard Worker   // If some input data is choked, calling this function may restart the
59*6777b538SAndroid Build Coastguard Worker   // inflation process.
60*6777b538SAndroid Build Coastguard Worker   // This means that even if you call |Finish()| and call |GetOutput()| with
61*6777b538SAndroid Build Coastguard Worker   // size = |CurrentOutputSize()|, the inflater may have some remaining data.
62*6777b538SAndroid Build Coastguard Worker   // To confirm the inflater emptiness, you should check whether
63*6777b538SAndroid Build Coastguard Worker   // |CurrentOutputSize()| is zero.
64*6777b538SAndroid Build Coastguard Worker   scoped_refptr<IOBufferWithSize> GetOutput(size_t size);
65*6777b538SAndroid Build Coastguard Worker 
66*6777b538SAndroid Build Coastguard Worker   // Returns the size of the current inflated output.
CurrentOutputSize()67*6777b538SAndroid Build Coastguard Worker   size_t CurrentOutputSize() const { return output_buffer_.Size(); }
68*6777b538SAndroid Build Coastguard Worker 
69*6777b538SAndroid Build Coastguard Worker   static constexpr size_t kDefaultBufferCapacity = 512;
70*6777b538SAndroid Build Coastguard Worker   static constexpr size_t kDefaultInputIOBufferCapacity = 512;
71*6777b538SAndroid Build Coastguard Worker 
72*6777b538SAndroid Build Coastguard Worker  private:
73*6777b538SAndroid Build Coastguard Worker   // Ring buffer with fixed capacity.
74*6777b538SAndroid Build Coastguard Worker   class NET_EXPORT_PRIVATE OutputBuffer {
75*6777b538SAndroid Build Coastguard Worker    public:
76*6777b538SAndroid Build Coastguard Worker     explicit OutputBuffer(size_t capacity);
77*6777b538SAndroid Build Coastguard Worker     ~OutputBuffer();
78*6777b538SAndroid Build Coastguard Worker 
79*6777b538SAndroid Build Coastguard Worker     size_t Size() const;
80*6777b538SAndroid Build Coastguard Worker     // Returns (tail pointer, availabe size).
81*6777b538SAndroid Build Coastguard Worker     // A user can push data to the queue by writing the data to
82*6777b538SAndroid Build Coastguard Worker     // the area returned by this function and calling AdvanceTail.
83*6777b538SAndroid Build Coastguard Worker     std::pair<char*, size_t> GetTail();
84*6777b538SAndroid Build Coastguard Worker     void Read(char* dest, size_t size);
85*6777b538SAndroid Build Coastguard Worker     void AdvanceTail(size_t advance);
86*6777b538SAndroid Build Coastguard Worker 
87*6777b538SAndroid Build Coastguard Worker    private:
88*6777b538SAndroid Build Coastguard Worker     void AdvanceHead(size_t advance);
89*6777b538SAndroid Build Coastguard Worker 
90*6777b538SAndroid Build Coastguard Worker     const size_t capacity_;
91*6777b538SAndroid Build Coastguard Worker     std::vector<char> buffer_;
92*6777b538SAndroid Build Coastguard Worker     size_t head_ = 0;
93*6777b538SAndroid Build Coastguard Worker     size_t tail_ = 0;
94*6777b538SAndroid Build Coastguard Worker   };
95*6777b538SAndroid Build Coastguard Worker 
96*6777b538SAndroid Build Coastguard Worker   class InputQueue {
97*6777b538SAndroid Build Coastguard Worker    public:
98*6777b538SAndroid Build Coastguard Worker     // |capacity| is used for the capacity of each IOBuffer in this queue.
99*6777b538SAndroid Build Coastguard Worker     // this queue itself can grow without limit.
100*6777b538SAndroid Build Coastguard Worker     explicit InputQueue(size_t capacity);
101*6777b538SAndroid Build Coastguard Worker     ~InputQueue();
102*6777b538SAndroid Build Coastguard Worker 
103*6777b538SAndroid Build Coastguard Worker     // Returns (data pointer, size), the first component of unconsumed data.
104*6777b538SAndroid Build Coastguard Worker     // The type of data pointer is non-const because |inflate| function
105*6777b538SAndroid Build Coastguard Worker     // requires so.
106*6777b538SAndroid Build Coastguard Worker     std::pair<char*, size_t> Top();
IsEmpty()107*6777b538SAndroid Build Coastguard Worker     bool IsEmpty() const { return buffers_.empty(); }
108*6777b538SAndroid Build Coastguard Worker     void Push(const char* data, size_t size);
109*6777b538SAndroid Build Coastguard Worker     // Consumes the topmost |size| bytes.
110*6777b538SAndroid Build Coastguard Worker     // |size| must be less than or equal to the first buffer size.
111*6777b538SAndroid Build Coastguard Worker     void Consume(size_t size);
112*6777b538SAndroid Build Coastguard Worker 
113*6777b538SAndroid Build Coastguard Worker    private:
114*6777b538SAndroid Build Coastguard Worker     size_t PushToLastBuffer(const char* data, size_t size);
115*6777b538SAndroid Build Coastguard Worker 
116*6777b538SAndroid Build Coastguard Worker     const size_t capacity_;
117*6777b538SAndroid Build Coastguard Worker     size_t head_of_first_buffer_ = 0;
118*6777b538SAndroid Build Coastguard Worker     size_t tail_of_last_buffer_ = 0;
119*6777b538SAndroid Build Coastguard Worker     base::circular_deque<scoped_refptr<IOBufferWithSize>> buffers_;
120*6777b538SAndroid Build Coastguard Worker   };
121*6777b538SAndroid Build Coastguard Worker 
122*6777b538SAndroid Build Coastguard Worker   int InflateWithFlush(const char* next_in, size_t avail_in);
123*6777b538SAndroid Build Coastguard Worker   int Inflate(const char* next_in, size_t avail_in, int flush);
124*6777b538SAndroid Build Coastguard Worker   int InflateChokedInput();
125*6777b538SAndroid Build Coastguard Worker 
126*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<z_stream_s> stream_;
127*6777b538SAndroid Build Coastguard Worker   InputQueue input_queue_;
128*6777b538SAndroid Build Coastguard Worker   OutputBuffer output_buffer_;
129*6777b538SAndroid Build Coastguard Worker };
130*6777b538SAndroid Build Coastguard Worker 
131*6777b538SAndroid Build Coastguard Worker }  // namespace net
132*6777b538SAndroid Build Coastguard Worker 
133*6777b538SAndroid Build Coastguard Worker #endif  // NET_WEBSOCKETS_WEBSOCKET_INFLATER_H_
134