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 blink { 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 #if !ENABLE(OILPAN) 59 m_handle = nullptr; 60 #endif 61 } 62 63 void 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 71 int 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 96 void SocketStreamHandleInternal::close() 97 { 98 WTF_LOG(Network, "SocketStreamHandleInternal %p close()", this); 99 if (m_socket) 100 m_socket->close(); 101 } 102 103 void 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 119 void 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 131 void 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 141 void 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 154 void 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 164 void SocketStreamHandleInternal::trace(Visitor* visitor) 165 { 166 visitor->trace(m_handle); 167 } 168 169 // SocketStreamHandle ---------------------------------------------------------- 170 171 SocketStreamHandle::SocketStreamHandle(SocketStreamHandleClient* client) 172 : m_client(client) 173 , m_state(Connecting) 174 { 175 m_internal = SocketStreamHandleInternal::create(this); 176 } 177 178 void SocketStreamHandle::connect(const KURL& url) 179 { 180 m_internal->connect(url); 181 } 182 183 SocketStreamHandle::~SocketStreamHandle() 184 { 185 #if !ENABLE(OILPAN) 186 setClient(0); 187 #endif 188 } 189 190 SocketStreamHandle::SocketStreamState SocketStreamHandle::state() const 191 { 192 return m_state; 193 } 194 195 bool 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 224 void 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 234 void SocketStreamHandle::disconnect() 235 { 236 closeInternal(); 237 m_state = Closed; 238 } 239 240 void SocketStreamHandle::setClient(SocketStreamHandleClient* client) 241 { 242 ASSERT(!client || (!m_client && m_state == Connecting)); 243 m_client = client; 244 } 245 246 bool 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 273 int SocketStreamHandle::sendInternal(const char* buf, int len) 274 { 275 if (!m_internal) 276 return 0; 277 return m_internal->send(buf, len); 278 } 279 280 void SocketStreamHandle::closeInternal() 281 { 282 if (m_internal) 283 m_internal->close(); 284 } 285 286 void SocketStreamHandle::trace(Visitor* visitor) 287 { 288 visitor->trace(m_client); 289 visitor->trace(m_internal); 290 } 291 292 } // namespace blink 293