Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(341)

Side by Side Diff: WebCore/websockets/WebSocketChannel.cpp

Issue 155079: WebSocket implementation in WebKit (Closed)
Patch Set: Rewrite to use SocketStreamHandle Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « WebCore/websockets/WebSocketChannel.h ('k') | WebCore/websockets/WebSocketChannelClient.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2009 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 "WebSocketChannel.h"
33
34 #include "CString.h"
35 #include "Logging.h"
36 #include "PlatformString.h"
37 #include "ScriptExecutionContext.h"
38 #include "SharedBuffer.h"
39 #include "SocketStreamHandle.h"
40 #include "StringHash.h"
41 #include "WebSocketChannelClient.h"
42
43 #include <wtf/HashMap.h>
44 #include <wtf/Deque.h>
45
46 #include "NotImplemented.h"
47
48 #undef LOG
49 #define LOG(channel, ...) do { fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n "); } while (0);
50
51 namespace {
52
53 bool CheckWebSocketHandshake(const WebCore::WebSocketRequest &req, const WebCore ::WebSocketResponse& resp)
54 {
55 if (!resp.isValidHeader()) {
56 LOG(Network, "Wrong response header");
57 return false;
58 }
59 if (req.origin() != resp.websocket_origin()) {
60 LOG(Network, "Mismatch origin: %s != %s", req.origin().utf8().data(), re sp.websocket_origin().utf8().data());
61 return false;
62 }
63 if (req.location() != resp.websocket_location()) {
64 LOG(Network, "Mismatch location: %s != %s", req.location().utf8().data() , resp.websocket_location().utf8().data());
65 return false;
66 }
67 if (!req.protocol().isEmpty() && req.protocol() != resp.websocket_protocol() ) {
68 LOG(Network, "Mismatch protocol: %s != %s", req.protocol().utf8().data() , resp.websocket_protocol().utf8().data());
69 return false;
70 }
71 return true;
72 }
73
74 } // anonymous namespace
75
76 namespace WebCore {
77
78 WebSocketChannel::WebSocketChannel(ScriptExecutionContext* context, WebSocketCha nnelClient* client, const WebSocketRequest& request)
79 : m_context(context)
80 , m_client(client)
81 , m_request(request)
82 , m_handshaked(false)
83 , m_buffered_amount(0)
84 , m_buffer(SharedBuffer::create())
85 {
86 // TODO(ukai): additional parameters?
87 }
88
89 WebSocketChannel::~WebSocketChannel()
90 {
91 }
92
93 void WebSocketChannel::connect()
94 {
95 LOG(Network, "WebSocketChannel %p connect", this);
96
97 // ??? defer connection in SocketStreamHandle
98 m_handle = SocketStreamHandle::create(m_request.url(), this);
99 }
100
101 bool WebSocketChannel::send(const String& msg)
102 {
103 LOG(Network, "WebSocketChannel %p send %s", this, msg.utf8().data());
104 static const char frame_type[1] = {'\0'};
105 static const char frame_end[1] = {'\xff'};
106 RefPtr<SharedBuffer> buf(SharedBuffer::create());
107 buf->append(frame_type, sizeof(frame_type));
108 buf->append(msg.utf8().data(), msg.utf8().length());
109 buf->append(frame_end, sizeof(frame_end));
110 m_buffered_amount += buf->size();
111 return m_handle->send(buf->data(), buf->size());
112 }
113
114 unsigned long WebSocketChannel::bufferedAmount() const
115 {
116 LOG(Network, "WebSocketChannel %p bufferedAmount", this);
117 return m_buffered_amount;
118 }
119
120 void WebSocketChannel::close()
121 {
122 LOG(Network, "WebSocketChannel %p close", this);
123 if (m_handle.get()) {
124 m_handle->close(); // will call didClose()
125 }
126 }
127
128 void WebSocketChannel::didOpen(SocketStreamHandle* handle)
129 {
130 LOG(Network, "WebSocketChannel %p didConnect", this);
131 ASSERT(handle == m_handle.get() || m_handle.get() == 0);
132 if (m_handle.get() == 0)
133 return;
134 const CString& request_message = m_request.flattenToString();
135 m_handle->send(request_message.data(), request_message.length());
136 }
137
138 void WebSocketChannel::didClose(SocketStreamHandle* handle)
139 {
140 LOG(Network, "WebSocketChannel %p didClose", this);
141 ASSERT(handle == m_handle.get() || m_handle.get() == 0);
142 if (m_handle.get() == 0)
143 return;
144 m_handle = NULL;
145 WebSocketChannelClient* client = m_client;
146 m_client = NULL;
147 client->didClose();
148 }
149
150 void WebSocketChannel::didReceivedData(SocketStreamHandle* handle, const char* d ata, int len)
151 {
152 LOG(Network, "WebSocketChannel %p didReceiveData %d", this, len);
153 ASSERT(handle == m_handle.get() || m_handle.get() == 0);
154 if (m_handle.get() == 0)
155 return;
156 m_buffer->append(data, len);
157 if (!m_handshaked) {
158 int header_len = m_response.readHandshakeResponse(m_buffer->data(), m_bu ffer->size());
159 if (header_len <= 0)
160 return;
161 m_handshaked = CheckWebSocketHandshake(m_request, m_response);
162 if (m_handshaked) {
163 LOG(Network, "WebSocketChannel %p connected", this);
164 m_client->didConnect();
165 } else {
166 LOG(Network, "WebSocketChannel %p connection failed", this);
167 didClose(handle);
168 }
169 if (header_len == len)
170 return;
171 RefPtr<SharedBuffer> buf(SharedBuffer::create());
172 buf->append(m_buffer->data() + header_len, m_buffer->size() - header_len );
173 m_buffer.swap(buf);
174 }
175 RefPtr<SharedBuffer> buf(SharedBuffer::create());
176 buf.swap(m_buffer);
177
178 const char *next_frame = buf->data();
179 const char *p = buf->data();
180 const char *end = p + buf->size();
181 while (p < end) {
182 unsigned char frame_byte = static_cast<unsigned char>(*p++);
183 if ((frame_byte & 0x80) == 0x80) {
184 // TODO(ukai): overflow check
185 int length = 0;
186 while (p < end && (*p & 0x80) == 0x80) {
187 length = length * 127 + *p & 0x7f;
188 ++p;
189 }
190 if (p + length < end) {
191 p += length;
192 next_frame = p;
193 }
194 } else {
195 const char *msg_start = p;
196 while (p < end && *p != '\xff') {
197 ++p;
198 }
199 if (p < end && *p == '\xff') {
200 if (frame_byte == 0x00)
201 m_client->didReceiveMessage(String::fromUTF8(msg_start, p - msg_start));
202 ++p;
203 next_frame = p;
204 }
205 }
206 }
207 if (next_frame < end) {
208 m_buffer->append(next_frame, end - next_frame);
209 }
210 }
211
212 void WebSocketChannel::didFail(SocketStreamHandle* handle, const SocketStreamHan dleError& err)
213 {
214 LOG(Network, "WebSocketChannel %p didFaile", this);
215 ASSERT(handle == m_handle.get() || m_handle.get() == 0);
216 didClose(handle);
217 }
218
219 } // namespace WebCore
OLDNEW
« no previous file with comments | « WebCore/websockets/WebSocketChannel.h ('k') | WebCore/websockets/WebSocketChannelClient.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698