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