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