websocket_inflater.h 4.3 KB

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