2
* Copyright (C) 2011 Apple Inc. All Rights Reserved.
3
* Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
14
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
#if ENABLE(INSPECTOR_SERVER)
31
#include "WebSocketServerConnection.h"
33
#include "WebSocketServer.h"
34
#include "WebSocketServerClient.h"
35
#include <WebCore/HTTPRequest.h>
36
#include <WebCore/NotImplemented.h>
37
#include <WebCore/SocketStreamError.h>
38
#include <WebCore/SocketStreamHandle.h>
39
#include <WebCore/WebSocketChannel.h>
40
#include <WebCore/WebSocketHandshake.h>
41
#include <wtf/text/CString.h>
42
#include <wtf/text/StringBuilder.h>
44
using namespace WebCore;
48
WebSocketServerConnection::WebSocketServerConnection(WebSocketServerClient* client, WebSocketServer* server)
53
, m_shutdownAfterSend(false)
57
WebSocketServerConnection::~WebSocketServerConnection()
62
void WebSocketServerConnection::setSocketHandle(PassRefPtr<WebCore::SocketStreamHandle> socket)
68
void WebSocketServerConnection::shutdownNow()
72
RefPtr<SocketStreamHandle> socket = m_socket.release();
74
m_shutdownAfterSend = false;
77
void WebSocketServerConnection::shutdownAfterSendOrNow()
79
if (m_socket->bufferedAmount()) {
80
m_shutdownAfterSend = true;
87
void WebSocketServerConnection::sendWebSocketMessage(const String& message)
89
CString payload = message.utf8();
90
const bool final = true, compress = false, masked = false;
91
WebSocketFrame frame(WebSocketFrame::OpCodeText, final, compress, masked, payload.data(), payload.length());
93
Vector<char> frameData;
94
frame.makeFrameData(frameData);
96
m_socket->send(frameData.data(), frameData.size());
99
void WebSocketServerConnection::sendHTTPResponseHeader(int statusCode, const String& statusText, const HTTPHeaderMap& headerFields)
101
StringBuilder builder;
102
builder.appendLiteral("HTTP/1.1 ");
103
builder.appendNumber(statusCode);
105
builder.append(statusText);
106
builder.appendLiteral("\r\n");
107
HTTPHeaderMap::const_iterator end = headerFields.end();
108
for (HTTPHeaderMap::const_iterator it = headerFields.begin(); it != end; ++it) {
109
builder.append(it->key);
110
builder.appendLiteral(": ");
111
builder.append(it->value);
112
builder.appendLiteral("\r\n");
114
builder.appendLiteral("\r\n");
116
CString header = builder.toString().latin1();
117
m_socket->send(header.data(), header.length());
120
void WebSocketServerConnection::sendRawData(const char* data, size_t length)
122
m_socket->send(data, length);
125
void WebSocketServerConnection::didCloseSocketStream(SocketStreamHandle*)
127
// Destroy the SocketStreamHandle now to prevent closing an already closed socket later.
131
if (m_mode == WebSocket)
132
m_client->didCloseWebSocketConnection(this);
134
// Tell the server to get rid of this.
135
m_server->didCloseWebSocketServerConnection(this);
138
void WebSocketServerConnection::didReceiveSocketStreamData(SocketStreamHandle*, const char* data, int length)
140
// Each didReceiveData call adds more data to our buffer.
141
// We clear the buffer when we have handled data from it.
142
m_bufferedData.append(data, length);
149
readWebSocketFrames();
152
// For any new modes added in the future.
153
ASSERT_NOT_REACHED();
157
void WebSocketServerConnection::didUpdateBufferedAmount(WebCore::SocketStreamHandle*, size_t)
159
if (m_shutdownAfterSend && !m_socket->bufferedAmount())
163
void WebSocketServerConnection::didFailSocketStream(SocketStreamHandle*, const SocketStreamError&)
165
// Possible read or write error.
168
void WebSocketServerConnection::readHTTPMessage()
170
String failureReason;
171
RefPtr<HTTPRequest> request = HTTPRequest::parseHTTPRequestFromBuffer(m_bufferedData.data(), m_bufferedData.size(), failureReason);
175
// Assume all the input has been read if we are reading an HTTP Request.
176
m_bufferedData.clear();
178
// If this is a WebSocket request, perform the WebSocket Handshake.
179
const HTTPHeaderMap& headers = request->headerFields();
180
String upgradeHeaderValue = headers.get("Upgrade");
181
if (upgradeHeaderValue == "websocket") {
182
upgradeToWebSocketServerConnection(request);
185
if (upgradeHeaderValue == "WebSocket") {
186
LOG_ERROR("WebSocket protocol version < Hybi-10 not supported. Upgrade your client.");
190
// Otherwise, this is an HTTP Request we don't know how to deal with.
191
m_client->didReceiveUnrecognizedHTTPRequest(this, request);
194
void WebSocketServerConnection::upgradeToWebSocketServerConnection(PassRefPtr<HTTPRequest> request)
197
ASSERT(m_mode == HTTP);
199
RefPtr<HTTPRequest> protectedRequest(request);
201
// Ask the client if we should upgrade for this or not.
202
if (!m_client->didReceiveWebSocketUpgradeHTTPRequest(this, protectedRequest)) {
207
// Build and send the WebSocket handshake response.
208
const HTTPHeaderMap& requestHeaders = protectedRequest->headerFields();
209
String accept = WebSocketHandshake::getExpectedWebSocketAccept(requestHeaders.get("Sec-WebSocket-Key"));
210
HTTPHeaderMap responseHeaders;
211
responseHeaders.add("Upgrade", requestHeaders.get("Upgrade"));
212
responseHeaders.add("Connection", requestHeaders.get("Connection"));
213
responseHeaders.add("Sec-WebSocket-Accept", accept);
215
sendHTTPResponseHeader(101, "WebSocket Protocol Handshake", responseHeaders);
217
m_client->didEstablishWebSocketConnection(this, protectedRequest);
220
void WebSocketServerConnection::readWebSocketFrames()
223
bool didReadOneFrame = readWebSocketFrame();
224
if (!didReadOneFrame)
226
if (m_bufferedData.isEmpty())
231
bool WebSocketServerConnection::readWebSocketFrame()
233
WebSocketFrame frame;
234
const char* frameEnd;
236
WebSocketFrame::ParseFrameResult result = WebSocketFrame::parseFrame(m_bufferedData.data(), m_bufferedData.size(), frame, frameEnd, errorString);
238
// Incomplete frame. Wait to receive more data.
239
if (result == WebSocketFrame::FrameIncomplete)
242
if (result == WebSocketFrame::FrameError) {
244
} else if (frame.opCode == WebSocketFrame::OpCodeText) {
245
// Delegate Text frames to our client.
246
String msg = String::fromUTF8(frame.payload, frame.payloadLength);
247
m_client->didReceiveWebSocketMessage(this, msg);
251
// Remove the frame from our buffer.
252
m_bufferedData.remove(0, frameEnd - m_bufferedData.data());
259
#endif // ENABLE(INSPECTOR_SERVER)