Home | History | Annotate | Download | only in websockets
      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.
     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 NET_EXPORT_PRIVATE 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();
    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