Home | History | Annotate | Download | only in network
      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 "platform/network/SocketStreamHandle.h"
     33 
     34 #include "platform/Logging.h"
     35 #include "platform/network/SocketStreamError.h"
     36 #include "platform/network/SocketStreamHandleClient.h"
     37 #include "platform/network/SocketStreamHandleInternal.h"
     38 #include "public/platform/Platform.h"
     39 #include "public/platform/WebData.h"
     40 #include "public/platform/WebSocketStreamError.h"
     41 #include "public/platform/WebSocketStreamHandle.h"
     42 #include "wtf/PassOwnPtr.h"
     43 
     44 namespace WebCore {
     45 
     46 static const unsigned bufferSize = 100 * 1024 * 1024;
     47 
     48 SocketStreamHandleInternal::SocketStreamHandleInternal(SocketStreamHandle* handle)
     49     : m_handle(handle)
     50     , m_socket(adoptPtr(blink::Platform::current()->createSocketStreamHandle()))
     51     , m_maxPendingSendAllowed(0)
     52     , m_pendingAmountSent(0)
     53 {
     54 }
     55 
     56 SocketStreamHandleInternal::~SocketStreamHandleInternal()
     57 {
     58     m_handle = 0;
     59 }
     60 
     61 void SocketStreamHandleInternal::connect(const KURL& url)
     62 {
     63     WTF_LOG(Network, "SocketStreamHandleInternal %p connect()", this);
     64 
     65     ASSERT(m_socket);
     66     m_socket->connect(url, this);
     67 }
     68 
     69 int SocketStreamHandleInternal::send(const char* data, int len)
     70 {
     71     WTF_LOG(Network, "SocketStreamHandleInternal %p send() len=%d", this, len);
     72     // FIXME: |m_socket| should not be null here, but it seems that there is the
     73     // case. We should figure out such a path and fix it rather than checking
     74     // null here.
     75     if (!m_socket) {
     76         WTF_LOG(Network, "SocketStreamHandleInternal %p send() m_socket is NULL", this);
     77         return 0;
     78     }
     79     if (m_pendingAmountSent + len > m_maxPendingSendAllowed)
     80         len = m_maxPendingSendAllowed - m_pendingAmountSent;
     81 
     82     if (len <= 0)
     83         return len;
     84     blink::WebData webdata(data, len);
     85     if (m_socket->send(webdata)) {
     86         m_pendingAmountSent += len;
     87         WTF_LOG(Network, "SocketStreamHandleInternal %p send() Sent %d bytes", this, len);
     88         return len;
     89     }
     90     WTF_LOG(Network, "SocketStreamHandleInternal %p send() m_socket->send() failed", this);
     91     return 0;
     92 }
     93 
     94 void SocketStreamHandleInternal::close()
     95 {
     96     WTF_LOG(Network, "SocketStreamHandleInternal %p close()", this);
     97     if (m_socket)
     98         m_socket->close();
     99 }
    100 
    101 void SocketStreamHandleInternal::didOpenStream(blink::WebSocketStreamHandle* socketHandle, int maxPendingSendAllowed)
    102 {
    103     WTF_LOG(Network, "SocketStreamHandleInternal %p didOpenStream() maxPendingSendAllowed=%d", this, maxPendingSendAllowed);
    104     ASSERT(maxPendingSendAllowed > 0);
    105     if (m_handle && m_socket) {
    106         ASSERT(socketHandle == m_socket.get());
    107         m_maxPendingSendAllowed = maxPendingSendAllowed;
    108         m_handle->m_state = SocketStreamHandle::Open;
    109         if (m_handle->m_client) {
    110             m_handle->m_client->didOpenSocketStream(m_handle);
    111             return;
    112         }
    113     }
    114     WTF_LOG(Network, "SocketStreamHandleInternal %p didOpenStream() m_handle or m_socket is NULL", this);
    115 }
    116 
    117 void SocketStreamHandleInternal::didSendData(blink::WebSocketStreamHandle* socketHandle, int amountSent)
    118 {
    119     WTF_LOG(Network, "SocketStreamHandleInternal %p didSendData() amountSent=%d", this, amountSent);
    120     ASSERT(amountSent > 0);
    121     if (m_handle && m_socket) {
    122         ASSERT(socketHandle == m_socket.get());
    123         m_pendingAmountSent -= amountSent;
    124         ASSERT(m_pendingAmountSent >= 0);
    125         m_handle->sendPendingData();
    126     }
    127 }
    128 
    129 void SocketStreamHandleInternal::didReceiveData(blink::WebSocketStreamHandle* socketHandle, const blink::WebData& data)
    130 {
    131     WTF_LOG(Network, "SocketStreamHandleInternal %p didReceiveData() Received %lu bytes", this, static_cast<unsigned long>(data.size()));
    132     if (m_handle && m_socket) {
    133         ASSERT(socketHandle == m_socket.get());
    134         if (m_handle->m_client)
    135             m_handle->m_client->didReceiveSocketStreamData(m_handle, data.data(), data.size());
    136     }
    137 }
    138 
    139 void SocketStreamHandleInternal::didClose(blink::WebSocketStreamHandle* socketHandle)
    140 {
    141     WTF_LOG(Network, "SocketStreamHandleInternal %p didClose()", this);
    142     if (m_handle && m_socket) {
    143         ASSERT(socketHandle == m_socket.get());
    144         m_socket.clear();
    145         SocketStreamHandle* h = m_handle;
    146         m_handle = 0;
    147         if (h->m_client)
    148             h->m_client->didCloseSocketStream(h);
    149     }
    150 }
    151 
    152 void SocketStreamHandleInternal::didFail(blink::WebSocketStreamHandle* socketHandle, const blink::WebSocketStreamError& err)
    153 {
    154     WTF_LOG(Network, "SocketStreamHandleInternal %p didFail()", this);
    155     if (m_handle && m_socket) {
    156         ASSERT(socketHandle == m_socket.get());
    157         if (m_handle->m_client)
    158             m_handle->m_client->didFailSocketStream(m_handle, *(PassRefPtr<SocketStreamError>(err)));
    159     }
    160 }
    161 
    162 // SocketStreamHandle ----------------------------------------------------------
    163 
    164 SocketStreamHandle::SocketStreamHandle(SocketStreamHandleClient* client)
    165     : m_client(client)
    166     , m_state(Connecting)
    167 {
    168     m_internal = SocketStreamHandleInternal::create(this);
    169 }
    170 
    171 void SocketStreamHandle::connect(const KURL& url)
    172 {
    173     m_internal->connect(url);
    174 }
    175 
    176 SocketStreamHandle::~SocketStreamHandle()
    177 {
    178     setClient(0);
    179     m_internal.clear();
    180 }
    181 
    182 SocketStreamHandle::SocketStreamState SocketStreamHandle::state() const
    183 {
    184     return m_state;
    185 }
    186 
    187 bool SocketStreamHandle::send(const char* data, int length)
    188 {
    189     if (m_state == Connecting || m_state == Closing)
    190         return false;
    191     if (!m_buffer.isEmpty()) {
    192         if (m_buffer.size() + length > bufferSize) {
    193             // FIXME: report error to indicate that buffer has no more space.
    194             return false;
    195         }
    196         m_buffer.append(data, length);
    197         return true;
    198     }
    199     int bytesWritten = 0;
    200     if (m_state == Open)
    201         bytesWritten = sendInternal(data, length);
    202     if (bytesWritten < 0)
    203         return false;
    204     if (m_client)
    205         m_client->didConsumeBufferedAmount(this, bytesWritten);
    206     if (m_buffer.size() + length - bytesWritten > bufferSize) {
    207         // FIXME: report error to indicate that buffer has no more space.
    208         return false;
    209     }
    210     if (bytesWritten < length) {
    211         m_buffer.append(data + bytesWritten, length - bytesWritten);
    212     }
    213     return true;
    214 }
    215 
    216 void SocketStreamHandle::close()
    217 {
    218     if (m_state == Closed)
    219         return;
    220     m_state = Closing;
    221     if (!m_buffer.isEmpty())
    222         return;
    223     disconnect();
    224 }
    225 
    226 void SocketStreamHandle::disconnect()
    227 {
    228     RefPtr<SocketStreamHandle> protect(this); // closeInternal calls the client, which may make the handle get deallocated immediately.
    229 
    230     closeInternal();
    231     m_state = Closed;
    232 }
    233 
    234 void SocketStreamHandle::setClient(SocketStreamHandleClient* client)
    235 {
    236     ASSERT(!client || (!m_client && m_state == Connecting));
    237     m_client = client;
    238 }
    239 
    240 bool SocketStreamHandle::sendPendingData()
    241 {
    242     if (m_state != Open && m_state != Closing)
    243         return false;
    244     if (m_buffer.isEmpty()) {
    245         if (m_state == Open)
    246             return false;
    247         if (m_state == Closing) {
    248             disconnect();
    249             return false;
    250         }
    251     }
    252     bool pending;
    253     do {
    254         int bytesWritten = sendInternal(m_buffer.firstBlockData(), m_buffer.firstBlockSize());
    255         pending = bytesWritten != static_cast<int>(m_buffer.firstBlockSize());
    256         if (bytesWritten <= 0)
    257             return false;
    258         ASSERT(m_buffer.size() - bytesWritten <= bufferSize);
    259         m_buffer.consume(bytesWritten);
    260         // FIXME: place didConsumeBufferedAmount out of do-while.
    261         if (m_client)
    262             m_client->didConsumeBufferedAmount(this, bytesWritten);
    263     } while (!pending && !m_buffer.isEmpty());
    264     return true;
    265 }
    266 
    267 int SocketStreamHandle::sendInternal(const char* buf, int len)
    268 {
    269     if (!m_internal)
    270         return 0;
    271     return m_internal->send(buf, len);
    272 }
    273 
    274 void SocketStreamHandle::closeInternal()
    275 {
    276     if (m_internal)
    277         m_internal->close();
    278 }
    279 
    280 } // namespace WebCore
    281