Remove "virtual" from all lines that have both "virtual" and "override".
[WebKit-https.git] / Source / WebCore / Modules / websockets / WebSocketDeflateFramer.cpp
1 /*
2  * Copyright (C) 2012 Google Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32
33 #if ENABLE(WEB_SOCKETS)
34
35 #include "WebSocketDeflateFramer.h"
36
37 #include <wtf/HashMap.h>
38 #include <wtf/text/StringHash.h>
39 #include <wtf/text/WTFString.h>
40
41 namespace WebCore {
42
43 class WebSocketExtensionDeflateFrame : public WebSocketExtensionProcessor {
44     WTF_MAKE_FAST_ALLOCATED;
45 public:
46     explicit WebSocketExtensionDeflateFrame(WebSocketDeflateFramer*);
47     virtual ~WebSocketExtensionDeflateFrame() { }
48
49     String handshakeString() override;
50     bool processResponse(const HashMap<String, String>&) override;
51     String failureReason() override { return m_failureReason; }
52
53 private:
54     WebSocketDeflateFramer* m_framer;
55     bool m_responseProcessed;
56     String m_failureReason;
57 };
58
59 // FXIME: Remove vendor prefix after the specification matured.
60 WebSocketExtensionDeflateFrame::WebSocketExtensionDeflateFrame(WebSocketDeflateFramer* framer)
61     : WebSocketExtensionProcessor("x-webkit-deflate-frame")
62     , m_framer(framer)
63     , m_responseProcessed(false)
64 {
65     ASSERT(m_framer);
66 }
67
68 String WebSocketExtensionDeflateFrame::handshakeString()
69 {
70     return extensionToken(); // No parameter
71 }
72
73 bool WebSocketExtensionDeflateFrame::processResponse(const HashMap<String, String>& serverParameters)
74 {
75 #if USE(ZLIB)
76     if (m_responseProcessed) {
77         m_failureReason = "Received duplicate deflate-frame response";
78         return false;
79     }
80     m_responseProcessed = true;
81
82     unsigned expectedNumParameters = 0;
83     int windowBits = 15;
84     HashMap<String, String>::const_iterator parameter = serverParameters.find("max_window_bits");
85     if (parameter != serverParameters.end()) {
86         windowBits = parameter->value.toInt();
87         if (windowBits < 8 || windowBits > 15) {
88             m_failureReason = "Received invalid max_window_bits parameter";
89             return false;
90         }
91         expectedNumParameters++;
92     }
93
94     WebSocketDeflater::ContextTakeOverMode mode = WebSocketDeflater::TakeOverContext;
95     parameter = serverParameters.find("no_context_takeover");
96     if (parameter != serverParameters.end()) {
97         if (!parameter->value.isNull()) {
98             m_failureReason = "Received invalid no_context_takeover parameter";
99             return false;
100         }
101         mode = WebSocketDeflater::DoNotTakeOverContext;
102         expectedNumParameters++;
103     }
104
105     if (expectedNumParameters != serverParameters.size()) {
106         m_failureReason = "Received unexpected deflate-frame parameter";
107         return false;
108     }
109
110     m_framer->enableDeflate(windowBits, mode);
111     return true;
112 #else
113     ASSERT_NOT_REACHED();
114     return false;
115 #endif
116 }
117
118 DeflateResultHolder::DeflateResultHolder(WebSocketDeflateFramer* framer)
119     : m_framer(framer)
120     , m_succeeded(true)
121 {
122     ASSERT(m_framer);
123 }
124
125 DeflateResultHolder::~DeflateResultHolder()
126 {
127     m_framer->resetDeflateContext();
128 }
129
130 void DeflateResultHolder::fail(const String& failureReason)
131 {
132     m_succeeded = false;
133     m_failureReason = failureReason;
134 }
135
136 InflateResultHolder::InflateResultHolder(WebSocketDeflateFramer* framer)
137     : m_framer(framer)
138     , m_succeeded(true)
139 {
140     ASSERT(m_framer);
141 }
142
143 InflateResultHolder::~InflateResultHolder()
144 {
145     m_framer->resetInflateContext();
146 }
147
148 void InflateResultHolder::fail(const String& failureReason)
149 {
150     m_succeeded = false;
151     m_failureReason = failureReason;
152 }
153
154 WebSocketDeflateFramer::WebSocketDeflateFramer()
155     : m_enabled(false)
156 {
157 }
158
159 std::unique_ptr<WebSocketExtensionProcessor> WebSocketDeflateFramer::createExtensionProcessor()
160 {
161     return std::make_unique<WebSocketExtensionDeflateFrame>(this);
162 }
163
164 bool WebSocketDeflateFramer::canDeflate() const
165 {
166 #if USE(ZLIB)
167     return true;
168 #else
169     return false;
170 #endif
171 }
172
173 #if USE(ZLIB)
174 void WebSocketDeflateFramer::enableDeflate(int windowBits, WebSocketDeflater::ContextTakeOverMode mode)
175 {
176     m_deflater = std::make_unique<WebSocketDeflater>(windowBits, mode);
177     m_inflater = std::make_unique<WebSocketInflater>();
178     if (!m_deflater->initialize() || !m_inflater->initialize()) {
179         m_deflater = nullptr;
180         m_inflater = nullptr;
181         return;
182     }
183     m_enabled = true;
184 }
185 #endif
186
187 std::unique_ptr<DeflateResultHolder> WebSocketDeflateFramer::deflate(WebSocketFrame& frame)
188 {
189 #if USE(ZLIB)
190     auto result = std::make_unique<DeflateResultHolder>(this);
191     if (!enabled() || !WebSocketFrame::isNonControlOpCode(frame.opCode) || !frame.payloadLength)
192         return result;
193     if (!m_deflater->addBytes(frame.payload, frame.payloadLength) || !m_deflater->finish()) {
194         result->fail("Failed to compress frame");
195         return result;
196     }
197     frame.compress = true;
198     frame.payload = m_deflater->data();
199     frame.payloadLength = m_deflater->size();
200     return result;
201 #else
202     return std::make_unique<DeflateResultHolder>(this);
203 #endif
204 }
205
206 void WebSocketDeflateFramer::resetDeflateContext()
207 {
208 #if USE(ZLIB)
209     if (m_deflater)
210         m_deflater->reset();
211 #endif
212 }
213
214 std::unique_ptr<InflateResultHolder> WebSocketDeflateFramer::inflate(WebSocketFrame& frame)
215 {
216     auto result = std::make_unique<InflateResultHolder>(this);
217     if (!enabled() && frame.compress) {
218         result->fail("Compressed bit must be 0 if no negotiated deflate-frame extension");
219         return result;
220     }
221 #if USE(ZLIB)
222     if (!frame.compress)
223         return result;
224     if (!WebSocketFrame::isNonControlOpCode(frame.opCode)) {
225         result->fail("Received unexpected compressed frame");
226         return result;
227     }
228     if (!m_inflater->addBytes(frame.payload, frame.payloadLength) || !m_inflater->finish()) {
229         result->fail("Failed to decompress frame");
230         return result;
231     }
232     frame.compress = false;
233     frame.payload = m_inflater->data();
234     frame.payloadLength = m_inflater->size();
235     return result;
236 #else
237     return result;
238 #endif
239 }
240
241 void WebSocketDeflateFramer::resetInflateContext()
242 {
243 #if USE(ZLIB)
244     if (m_inflater)
245         m_inflater->reset();
246 #endif
247 }
248
249 void WebSocketDeflateFramer::didFail()
250 {
251     resetDeflateContext();
252     resetInflateContext();
253 }
254
255 } // namespace WebCore
256
257 #endif // ENABLE(WEB_SOCKETS)