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