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