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