summaryrefslogtreecommitdiffstats
path: root/netwerk/streamconv/converters/nsHTTPCompressConv.h
blob: 1ad34bbfabc93ba0038ae5f260bb37835b5e7ef2 (plain)
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
131
132
133
134
135
136
137
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#if !defined(__nsHTTPCompressConv__h__)
#  define __nsHTTPCompressConv__h__ 1

#  include "nsIStreamConverter.h"
#  include "nsICompressConvStats.h"
#  include "nsIThreadRetargetableStreamListener.h"
#  include "nsCOMPtr.h"
#  include "mozilla/Atomics.h"
#  include "mozilla/Mutex.h"

#  include "zlib.h"

// brotli includes
#  undef assert
#  include "assert.h"
#  include "state.h"

class nsIStringInputStream;

#  define NS_HTTPCOMPRESSCONVERTER_CID                 \
    {                                                  \
      /* 66230b2b-17fa-4bd3-abf4-07986151022d */       \
      0x66230b2b, 0x17fa, 0x4bd3, {                    \
        0xab, 0xf4, 0x07, 0x98, 0x61, 0x51, 0x02, 0x2d \
      }                                                \
    }

#  define HTTP_DEFLATE_TYPE "deflate"
#  define HTTP_GZIP_TYPE "gzip"
#  define HTTP_X_GZIP_TYPE "x-gzip"
#  define HTTP_COMPRESS_TYPE "compress"
#  define HTTP_X_COMPRESS_TYPE "x-compress"
#  define HTTP_BROTLI_TYPE "br"
#  define HTTP_IDENTITY_TYPE "identity"
#  define HTTP_UNCOMPRESSED_TYPE "uncompressed"

namespace mozilla {
namespace net {

typedef enum {
  HTTP_COMPRESS_GZIP,
  HTTP_COMPRESS_DEFLATE,
  HTTP_COMPRESS_COMPRESS,
  HTTP_COMPRESS_BROTLI,
  HTTP_COMPRESS_IDENTITY
} CompressMode;

class BrotliWrapper {
 public:
  BrotliWrapper()
      : mTotalOut(0),
        mStatus(NS_OK),
        mBrotliStateIsStreamEnd(false),
        mRequest(nullptr),
        mContext(nullptr),
        mSourceOffset(0) {
    BrotliDecoderStateInit(&mState, 0, 0, 0);
  }
  ~BrotliWrapper() { BrotliDecoderStateCleanup(&mState); }

  BrotliDecoderState mState;
  Atomic<size_t, Relaxed> mTotalOut;
  nsresult mStatus;
  Atomic<bool, Relaxed> mBrotliStateIsStreamEnd;

  nsIRequest* mRequest;
  nsISupports* mContext;
  uint64_t mSourceOffset;
};

class nsHTTPCompressConv : public nsIStreamConverter,
                           public nsICompressConvStats,
                           public nsIThreadRetargetableStreamListener {
 public:
  // nsISupports methods
  NS_DECL_THREADSAFE_ISUPPORTS
  NS_DECL_NSIREQUESTOBSERVER
  NS_DECL_NSISTREAMLISTENER
  NS_DECL_NSICOMPRESSCONVSTATS
  NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER

  // nsIStreamConverter methods
  NS_DECL_NSISTREAMCONVERTER

  nsHTTPCompressConv();

 private:
  virtual ~nsHTTPCompressConv();

  nsCOMPtr<nsIStreamListener>
      mListener;  // this guy gets the converted data via his OnDataAvailable ()
  Atomic<CompressMode, Relaxed> mMode;

  unsigned char* mOutBuffer;
  unsigned char* mInpBuffer;

  uint32_t mOutBufferLen;
  uint32_t mInpBufferLen;

  UniquePtr<BrotliWrapper> mBrotli;

  nsCOMPtr<nsIStringInputStream> mStream;

  static nsresult BrotliHandler(nsIInputStream* stream, void* closure,
                                const char* dataIn, uint32_t, uint32_t avail,
                                uint32_t* countRead);

  nsresult do_OnDataAvailable(nsIRequest* request, nsISupports* aContext,
                              uint64_t aSourceOffset, const char* buffer,
                              uint32_t aCount);

  bool mCheckHeaderDone;
  Atomic<bool> mStreamEnded;
  bool mStreamInitialized;
  bool mDummyStreamInitialised;
  bool mFailUncleanStops;

  z_stream d_stream;
  unsigned mLen, hMode, mSkipCount, mFlags;

  uint32_t check_header(nsIInputStream* iStr, uint32_t streamLen, nsresult* rv);

  Atomic<uint32_t, Relaxed> mDecodedDataLength;

  mutable mozilla::Mutex mMutex;
};

}  // namespace net
}  // namespace mozilla

#endif