• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SocketStreamHandleInternal(SocketStreamHandle * handle)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 
~SocketStreamHandleInternal()56 SocketStreamHandleInternal::~SocketStreamHandleInternal()
57 {
58     m_handle = 0;
59 }
60 
connect(const KURL & url)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 
send(const char * data,int len)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 
close()94 void SocketStreamHandleInternal::close()
95 {
96     WTF_LOG(Network, "SocketStreamHandleInternal %p close()", this);
97     if (m_socket)
98         m_socket->close();
99 }
100 
didOpenStream(blink::WebSocketStreamHandle * socketHandle,int maxPendingSendAllowed)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 
didSendData(blink::WebSocketStreamHandle * socketHandle,int amountSent)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 
didReceiveData(blink::WebSocketStreamHandle * socketHandle,const blink::WebData & data)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 
didClose(blink::WebSocketStreamHandle * socketHandle)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 
didFail(blink::WebSocketStreamHandle * socketHandle,const blink::WebSocketStreamError & err)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 
SocketStreamHandle(SocketStreamHandleClient * client)164 SocketStreamHandle::SocketStreamHandle(SocketStreamHandleClient* client)
165     : m_client(client)
166     , m_state(Connecting)
167 {
168     m_internal = SocketStreamHandleInternal::create(this);
169 }
170 
connect(const KURL & url)171 void SocketStreamHandle::connect(const KURL& url)
172 {
173     m_internal->connect(url);
174 }
175 
~SocketStreamHandle()176 SocketStreamHandle::~SocketStreamHandle()
177 {
178     setClient(0);
179     m_internal.clear();
180 }
181 
state() const182 SocketStreamHandle::SocketStreamState SocketStreamHandle::state() const
183 {
184     return m_state;
185 }
186 
send(const char * data,int length)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 
close()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 
disconnect()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 
setClient(SocketStreamHandleClient * client)234 void SocketStreamHandle::setClient(SocketStreamHandleClient* client)
235 {
236     ASSERT(!client || (!m_client && m_state == Connecting));
237     m_client = client;
238 }
239 
sendPendingData()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 
sendInternal(const char * buf,int len)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 
closeInternal()274 void SocketStreamHandle::closeInternal()
275 {
276     if (m_internal)
277         m_internal->close();
278 }
279 
280 } // namespace WebCore
281