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
|
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_WEBSOCKETS_WEBSOCKET_INFLATER_H_
#define NET_WEBSOCKETS_WEBSOCKET_INFLATER_H_
#include <deque>
#include <utility>
#include <vector>
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/net_export.h"
extern "C" struct z_stream_s;
namespace net {
class IOBufferWithSize;
// WebSocketInflater uncompresses data compressed by DEFLATE algorithm.
class NET_EXPORT_PRIVATE WebSocketInflater {
public:
WebSocketInflater();
// |input_queue_capacity| is a capacity for each contiguous block in the
// input queue. The input queue can grow without limit.
WebSocketInflater(size_t input_queue_capacity, size_t output_buffer_capacity);
~WebSocketInflater();
// Returns true if there is no error.
// |window_bits| must be between 8 and 15 (both inclusive).
// This function must be called exactly once before calling any of the
// following functions.
bool Initialize(int window_bits);
// Adds bytes to |stream_|.
// Returns true if there is no error.
// If the size of the output data reaches the capacity of the output buffer,
// the following input data will be "choked", i.e. stored in the input queue,
// staying compressed.
bool AddBytes(const char* data, size_t size);
// Flushes the input.
// Returns true if there is no error.
bool Finish();
// Returns up to |size| bytes of the decompressed output.
// Returns null if there is an inflation error.
// The returned bytes will be dropped from the current output and never be
// returned again.
// If some input data is choked, calling this function may restart the
// inflation process.
// This means that even if you call |Finish()| and call |GetOutput()| with
// size = |CurrentOutputSize()|, the inflater may have some remaining data.
// To confirm the inflater emptiness, you should check whether
// |CurrentOutputSize()| is zero.
scoped_refptr<IOBufferWithSize> GetOutput(size_t size);
// Returns the size of the current inflated output.
size_t CurrentOutputSize() const { return output_buffer_.Size(); }
static const size_t kDefaultBufferCapacity = 512;
static const size_t kDefaultInputIOBufferCapacity = 512;
private:
// Ring buffer with fixed capacity.
class OutputBuffer {
public:
explicit OutputBuffer(size_t capacity);
~OutputBuffer();
size_t Size() const;
// Returns (tail pointer, availabe size).
// A user can push data to the queue by writing the data to
// the area returned by this function and calling AdvanceTail.
std::pair<char*, size_t> GetTail();
void Read(char* dest, size_t size);
void AdvanceTail(size_t advance);
private:
void AdvanceHead(size_t advance);
const size_t capacity_;
std::vector<char> buffer_;
size_t head_;
size_t tail_;
};
class InputQueue {
public:
// |capacity| is used for the capacity of each IOBuffer in this queue.
// this queue itself can grow without limit.
explicit InputQueue(size_t capacity);
~InputQueue();
// Returns (data pointer, size), the first component of unconsumed data.
// The type of data pointer is non-const because |inflate| function
// requires so.
std::pair<char*, size_t> Top();
bool IsEmpty() const { return buffers_.empty(); }
void Push(const char* data, size_t size);
// Consumes the topmost |size| bytes.
// |size| must be less than or equal to the first buffer size.
void Consume(size_t size);
private:
size_t PushToLastBuffer(const char* data, size_t size);
const size_t capacity_;
size_t head_of_first_buffer_;
size_t tail_of_last_buffer_;
std::deque<scoped_refptr<IOBufferWithSize> > buffers_;
};
int InflateWithFlush(const char* next_in, size_t avail_in);
int Inflate(const char* next_in, size_t avail_in, int flush);
int InflateChokedInput();
scoped_ptr<z_stream_s> stream_;
InputQueue input_queue_;
OutputBuffer output_buffer_;
DISALLOW_COPY_AND_ASSIGN(WebSocketInflater);
};
} // namespace net
#endif // NET_WEBSOCKETS_WEBSOCKET_INFLATER_H_
|