2 * Copyright (C) 2009, 2011, 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
32 #include "platform/network/SocketStreamHandle.h"
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"
46 static const unsigned bufferSize = 100 * 1024 * 1024;
48 SocketStreamHandleInternal::SocketStreamHandleInternal(SocketStreamHandle* handle)
50 , m_socket(adoptPtr(blink::Platform::current()->createSocketStreamHandle()))
51 , m_maxPendingSendAllowed(0)
52 , m_pendingAmountSent(0)
56 SocketStreamHandleInternal::~SocketStreamHandleInternal()
63 void SocketStreamHandleInternal::connect(const KURL& url)
65 WTF_LOG(Network, "SocketStreamHandleInternal %p connect()", this);
68 m_socket->connect(url, this);
71 int SocketStreamHandleInternal::send(const char* data, int len)
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
78 WTF_LOG(Network, "SocketStreamHandleInternal %p send() m_socket is NULL", this);
81 if (m_pendingAmountSent + len > m_maxPendingSendAllowed)
82 len = m_maxPendingSendAllowed - m_pendingAmountSent;
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);
92 WTF_LOG(Network, "SocketStreamHandleInternal %p send() m_socket->send() failed", this);
96 void SocketStreamHandleInternal::close()
98 WTF_LOG(Network, "SocketStreamHandleInternal %p close()", this);
103 void SocketStreamHandleInternal::didOpenStream(blink::WebSocketStreamHandle* socketHandle, int maxPendingSendAllowed)
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);
116 WTF_LOG(Network, "SocketStreamHandleInternal %p didOpenStream() m_handle or m_socket is NULL", this);
119 void SocketStreamHandleInternal::didSendData(blink::WebSocketStreamHandle* socketHandle, int amountSent)
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();
131 void SocketStreamHandleInternal::didReceiveData(blink::WebSocketStreamHandle* socketHandle, const blink::WebData& data)
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());
141 void SocketStreamHandleInternal::didClose(blink::WebSocketStreamHandle* socketHandle)
143 WTF_LOG(Network, "SocketStreamHandleInternal %p didClose()", this);
144 if (m_handle && m_socket) {
145 ASSERT(socketHandle == m_socket.get());
147 SocketStreamHandle* h = m_handle;
150 h->m_client->didCloseSocketStream(h);
154 void SocketStreamHandleInternal::didFail(blink::WebSocketStreamHandle* socketHandle, const blink::WebSocketStreamError& err)
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)));
164 void SocketStreamHandleInternal::trace(Visitor* visitor)
166 visitor->trace(m_handle);
169 // SocketStreamHandle ----------------------------------------------------------
171 SocketStreamHandle::SocketStreamHandle(SocketStreamHandleClient* client)
173 , m_state(Connecting)
175 m_internal = SocketStreamHandleInternal::create(this);
178 void SocketStreamHandle::connect(const KURL& url)
180 m_internal->connect(url);
183 SocketStreamHandle::~SocketStreamHandle()
190 SocketStreamHandle::SocketStreamState SocketStreamHandle::state() const
195 bool SocketStreamHandle::send(const char* data, int length)
197 if (m_state == Connecting || m_state == Closing)
199 if (!m_buffer.isEmpty()) {
200 if (m_buffer.size() + length > bufferSize) {
201 // FIXME: report error to indicate that buffer has no more space.
204 m_buffer.append(data, length);
207 int bytesWritten = 0;
209 bytesWritten = sendInternal(data, length);
210 if (bytesWritten < 0)
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.
218 if (bytesWritten < length) {
219 m_buffer.append(data + bytesWritten, length - bytesWritten);
224 void SocketStreamHandle::close()
226 if (m_state == Closed)
229 if (!m_buffer.isEmpty())
234 void SocketStreamHandle::disconnect()
240 void SocketStreamHandle::setClient(SocketStreamHandleClient* client)
242 ASSERT(!client || (!m_client && m_state == Connecting));
246 bool SocketStreamHandle::sendPendingData()
248 if (m_state != Open && m_state != Closing)
250 if (m_buffer.isEmpty()) {
253 if (m_state == Closing) {
260 int bytesWritten = sendInternal(m_buffer.firstBlockData(), m_buffer.firstBlockSize());
261 pending = bytesWritten != static_cast<int>(m_buffer.firstBlockSize());
262 if (bytesWritten <= 0)
264 ASSERT(m_buffer.size() - bytesWritten <= bufferSize);
265 m_buffer.consume(bytesWritten);
266 // FIXME: place didConsumeBufferedAmount out of do-while.
268 m_client->didConsumeBufferedAmount(this, bytesWritten);
269 } while (!pending && !m_buffer.isEmpty());
273 int SocketStreamHandle::sendInternal(const char* buf, int len)
277 return m_internal->send(buf, len);
280 void SocketStreamHandle::closeInternal()
286 void SocketStreamHandle::trace(Visitor* visitor)
288 visitor->trace(m_client);
289 visitor->trace(m_internal);