1/* 2 * Copyright (C) 2009, 2011, 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#include "SocketStreamHandleBase.h" 33 34#include "SocketStreamHandle.h" 35#include "SocketStreamHandleClient.h" 36 37namespace WebCore { 38 39const unsigned int bufferSize = 100 * 1024 * 1024; 40 41SocketStreamHandleBase::SocketStreamHandleBase(const KURL& url, SocketStreamHandleClient* client) 42 : m_url(url) 43 , m_client(client) 44 , m_state(Connecting) 45{ 46} 47 48SocketStreamHandleBase::SocketStreamState SocketStreamHandleBase::state() const 49{ 50 return m_state; 51} 52 53bool SocketStreamHandleBase::send(const char* data, int length) 54{ 55 if (m_state == Connecting || m_state == Closing) 56 return false; 57 if (!m_buffer.isEmpty()) { 58 if (m_buffer.size() + length > bufferSize) { 59 // FIXME: report error to indicate that buffer has no more space. 60 return false; 61 } 62 m_buffer.append(data, length); 63 if (m_client) 64 m_client->didUpdateBufferedAmount(static_cast<SocketStreamHandle*>(this), bufferedAmount()); 65 return true; 66 } 67 int bytesWritten = 0; 68 if (m_state == Open) 69 bytesWritten = platformSend(data, length); 70 if (bytesWritten < 0) 71 return false; 72 if (m_buffer.size() + length - bytesWritten > bufferSize) { 73 // FIXME: report error to indicate that buffer has no more space. 74 return false; 75 } 76 if (bytesWritten < length) { 77 m_buffer.append(data + bytesWritten, length - bytesWritten); 78 if (m_client) 79 m_client->didUpdateBufferedAmount(static_cast<SocketStreamHandle*>(this), bufferedAmount()); 80 } 81 return true; 82} 83 84void SocketStreamHandleBase::close() 85{ 86 if (m_state == Closed) 87 return; 88 m_state = Closing; 89 if (!m_buffer.isEmpty()) 90 return; 91 disconnect(); 92} 93 94void SocketStreamHandleBase::disconnect() 95{ 96 RefPtr<SocketStreamHandle> protect(static_cast<SocketStreamHandle*>(this)); // platformClose calls the client, which may make the handle get deallocated immediately. 97 98 platformClose(); 99 m_state = Closed; 100} 101 102void SocketStreamHandleBase::setClient(SocketStreamHandleClient* client) 103{ 104 ASSERT(!client || (!m_client && m_state == Connecting)); 105 m_client = client; 106} 107 108bool SocketStreamHandleBase::sendPendingData() 109{ 110 if (m_state != Open && m_state != Closing) 111 return false; 112 if (m_buffer.isEmpty()) { 113 if (m_state == Open) 114 return false; 115 if (m_state == Closing) { 116 disconnect(); 117 return false; 118 } 119 } 120 bool pending; 121 do { 122 int bytesWritten = platformSend(m_buffer.firstBlockData(), m_buffer.firstBlockSize()); 123 pending = bytesWritten != static_cast<int>(m_buffer.firstBlockSize()); 124 if (bytesWritten <= 0) 125 return false; 126 ASSERT(m_buffer.size() - bytesWritten <= bufferSize); 127 m_buffer.consume(bytesWritten); 128 } while (!pending && !m_buffer.isEmpty()); 129 if (m_client) 130 m_client->didUpdateBufferedAmount(static_cast<SocketStreamHandle*>(this), bufferedAmount()); 131 return true; 132} 133 134} // namespace WebCore 135