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