15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2012 Google Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met: 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Redistributions of source code must retain the above copyright 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Redistributions in binary form must reproduce the above 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution. 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Neither the name of Google Inc. nor the names of its 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission. 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/websockets/WebSocketDeflater.h" 3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 341e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/Logging.h" 3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/FastMalloc.h" 3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/HashMap.h" 3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/StdLibExtras.h" 3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/StringExtras.h" 3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/text/StringHash.h" 4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/text/WTFString.h" 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <zlib.h> 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const int defaultMemLevel = 1; 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const size_t bufferIncrementUnit = 4096; 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassOwnPtr<WebSocketDeflater> WebSocketDeflater::create(int windowBits, ContextTakeOverMode contextTakeOverMode) 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return adoptPtr(new WebSocketDeflater(windowBits, contextTakeOverMode)); 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebSocketDeflater::WebSocketDeflater(int windowBits, ContextTakeOverMode contextTakeOverMode) 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_windowBits(windowBits) 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_contextTakeOverMode(contextTakeOverMode) 565267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) , m_isBytesAdded(false) 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_windowBits >= 8); 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_windowBits <= 15); 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_stream = adoptPtr(new z_stream); 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memset(m_stream.get(), 0, sizeof(z_stream)); 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool WebSocketDeflater::initialize() 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return deflateInit2(m_stream.get(), Z_DEFAULT_COMPRESSION, Z_DEFLATED, -m_windowBits, defaultMemLevel, Z_DEFAULT_STRATEGY) == Z_OK; 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebSocketDeflater::~WebSocketDeflater() 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int result = deflateEnd(m_stream.get()); 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (result != Z_OK) 73a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "WebSocketDeflater %p Destructor deflateEnd() failed: %d is returned", this, result); 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void setStreamParameter(z_stream* stream, const char* inputData, size_t inputLength, char* outputData, size_t outputLength) 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stream->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(inputData)); 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stream->avail_in = inputLength; 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stream->next_out = reinterpret_cast<Bytef*>(outputData); 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stream->avail_out = outputLength; 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool WebSocketDeflater::addBytes(const char* data, size_t length) 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!length) 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) // The estimation by deflateBound is not accurate if the zlib has some remaining input of the last compression. 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t maxLength = deflateBound(m_stream.get(), length); 9153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) do { 9253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) size_t writePosition = m_buffer.size(); 9353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) m_buffer.grow(writePosition + maxLength); 9453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) setStreamParameter(m_stream.get(), data, length, m_buffer.data() + writePosition, maxLength); 9553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) int result = deflate(m_stream.get(), Z_NO_FLUSH); 9653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (result != Z_OK) 9753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return false; 9853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) m_buffer.shrink(writePosition + maxLength - m_stream->avail_out); 9953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) maxLength *= 2; 10053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } while (m_stream->avail_in > 0); 1015267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) m_isBytesAdded = true; 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool WebSocketDeflater::finish() 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1075267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (!m_isBytesAdded) { 1085267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) // Since consecutive calls of deflate with Z_SYNC_FLUSH and no input lead to an error, 1095267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) // we create and return the output for the empty input manually. 1105267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) ASSERT(!m_buffer.size()); 1115267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) m_buffer.append("\x02\x00", 2); 1125267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) return true; 1135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) } 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (true) { 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t writePosition = m_buffer.size(); 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_buffer.grow(writePosition + bufferIncrementUnit); 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t availableCapacity = m_buffer.size() - writePosition; 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setStreamParameter(m_stream.get(), 0, 0, m_buffer.data() + writePosition, availableCapacity); 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int result = deflate(m_stream.get(), Z_SYNC_FLUSH); 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_buffer.shrink(writePosition + availableCapacity - m_stream->avail_out); 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (result == Z_OK) 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (result != Z_BUF_ERROR) 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Remove 4 octets from the tail as the specification requires. 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_buffer.size() <= 4) 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_buffer.resize(m_buffer.size() - 4); 1305267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) m_isBytesAdded = false; 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void WebSocketDeflater::reset() 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_buffer.clear(); 1375267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) m_isBytesAdded = false; 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_contextTakeOverMode == DoNotTakeOverContext) 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) deflateReset(m_stream.get()); 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 14253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void WebSocketDeflater::softReset() 14353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){ 14453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) m_buffer.clear(); 14553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} 14653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassOwnPtr<WebSocketInflater> WebSocketInflater::create(int windowBits) 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return adoptPtr(new WebSocketInflater(windowBits)); 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebSocketInflater::WebSocketInflater(int windowBits) 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_windowBits(windowBits) 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_stream = adoptPtr(new z_stream); 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memset(m_stream.get(), 0, sizeof(z_stream)); 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool WebSocketInflater::initialize() 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return inflateInit2(m_stream.get(), -m_windowBits) == Z_OK; 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebSocketInflater::~WebSocketInflater() 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int result = inflateEnd(m_stream.get()); 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (result != Z_OK) 168a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "WebSocketInflater %p Destructor inflateEnd() failed: %d is returned", this, result); 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool WebSocketInflater::addBytes(const char* data, size_t length) 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!length) 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t consumedSoFar = 0; 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (consumedSoFar < length) { 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t writePosition = m_buffer.size(); 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_buffer.grow(writePosition + bufferIncrementUnit); 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t availableCapacity = m_buffer.size() - writePosition; 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t remainingLength = length - consumedSoFar; 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setStreamParameter(m_stream.get(), data + consumedSoFar, remainingLength, m_buffer.data() + writePosition, availableCapacity); 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int result = inflate(m_stream.get(), Z_NO_FLUSH); 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) consumedSoFar += remainingLength - m_stream->avail_in; 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_buffer.shrink(writePosition + availableCapacity - m_stream->avail_out); 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (result == Z_BUF_ERROR) 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (result == Z_STREAM_END) { 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Received a block with BFINAL set to 1. Reset decompression state. 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (inflateReset(m_stream.get()) != Z_OK) 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (result != Z_OK) 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(remainingLength > m_stream->avail_in); 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(consumedSoFar == length); 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool WebSocketInflater::finish() 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 204f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) static const char strippedFields[] = "\0\0\xff\xff"; 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static const size_t strippedLength = 4; 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Appends 4 octests of 0x00 0x00 0xff 0xff 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t consumedSoFar = 0; 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (consumedSoFar < strippedLength) { 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t writePosition = m_buffer.size(); 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_buffer.grow(writePosition + bufferIncrementUnit); 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t availableCapacity = m_buffer.size() - writePosition; 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t remainingLength = strippedLength - consumedSoFar; 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setStreamParameter(m_stream.get(), strippedFields + consumedSoFar, remainingLength, m_buffer.data() + writePosition, availableCapacity); 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int result = inflate(m_stream.get(), Z_FINISH); 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) consumedSoFar += remainingLength - m_stream->avail_in; 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_buffer.shrink(writePosition + availableCapacity - m_stream->avail_out); 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (result == Z_BUF_ERROR) 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (result != Z_OK && result != Z_STREAM_END) 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(remainingLength > m_stream->avail_in); 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(consumedSoFar == strippedLength); 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void WebSocketInflater::reset() 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_buffer.clear(); 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 236