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