summaryrefslogtreecommitdiffstats
path: root/WebCore/websockets
diff options
context:
space:
mode:
authorKristian Monsen <kristianm@google.com>2010-06-28 16:42:48 +0100
committerKristian Monsen <kristianm@google.com>2010-07-02 10:29:56 +0100
commit06ea8e899e48f1f2f396b70e63fae369f2f23232 (patch)
tree20c1428cd05c76f32394ab354ea35ed99acd86d8 /WebCore/websockets
parent72aad67af14193199e29cdd5c4ddc095a8b9a8a8 (diff)
downloadexternal_webkit-06ea8e899e48f1f2f396b70e63fae369f2f23232.zip
external_webkit-06ea8e899e48f1f2f396b70e63fae369f2f23232.tar.gz
external_webkit-06ea8e899e48f1f2f396b70e63fae369f2f23232.tar.bz2
Merge WebKit at r61871: Initial merge by git.
Change-Id: I6cff43abca9cc4782e088a469ad4f03f166a65d5
Diffstat (limited to 'WebCore/websockets')
-rw-r--r--WebCore/websockets/WebSocket.idl9
-rw-r--r--WebCore/websockets/WebSocketChannel.cpp22
-rw-r--r--WebCore/websockets/WebSocketChannel.h2
-rw-r--r--WebCore/websockets/WebSocketHandshake.cpp183
-rw-r--r--WebCore/websockets/WebSocketHandshake.h12
-rw-r--r--WebCore/websockets/WebSocketHandshakeRequest.cpp62
-rw-r--r--WebCore/websockets/WebSocketHandshakeRequest.h36
-rw-r--r--WebCore/websockets/WebSocketHandshakeResponse.cpp110
-rw-r--r--WebCore/websockets/WebSocketHandshakeResponse.h76
9 files changed, 378 insertions, 134 deletions
diff --git a/WebCore/websockets/WebSocket.idl b/WebCore/websockets/WebSocket.idl
index cc4a07b..6850d36 100644
--- a/WebCore/websockets/WebSocket.idl
+++ b/WebCore/websockets/WebSocket.idl
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2010 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -32,7 +33,10 @@ module websockets {
interface [
Conditional=WEB_SOCKETS,
- CustomConstructor,
+ CanBeConstructed,
+ CustomConstructFunction,
+ ConstructorParameters=1,
+ V8CustomConstructor,
EventTarget,
NoStaticTables
] WebSocket {
@@ -52,8 +56,7 @@ module websockets {
attribute EventListener onerror;
attribute EventListener onclose;
- [Custom] boolean send(in DOMString data)
- raises(DOMException);
+ [RequiresAllArguments] boolean send(in DOMString data) raises(DOMException);
void close();
// EventTarget interface
diff --git a/WebCore/websockets/WebSocketChannel.cpp b/WebCore/websockets/WebSocketChannel.cpp
index 9ca2b20..5859fd7 100644
--- a/WebCore/websockets/WebSocketChannel.cpp
+++ b/WebCore/websockets/WebSocketChannel.cpp
@@ -58,6 +58,7 @@ WebSocketChannel::WebSocketChannel(ScriptExecutionContext* context, WebSocketCha
, m_handshake(url, protocol, context)
, m_buffer(0)
, m_bufferSize(0)
+ , m_resumeTimer(this, &WebSocketChannel::resumeTimerFired)
, m_suspended(false)
, m_closed(false)
, m_unhandledBufferedAmount(0)
@@ -125,12 +126,8 @@ void WebSocketChannel::suspend()
void WebSocketChannel::resume()
{
m_suspended = false;
- RefPtr<WebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference.
- while (!m_suspended && m_client && m_buffer)
- if (!processBuffer())
- break;
- if (!m_suspended && m_client && m_closed && m_handle)
- didClose(m_handle.get());
+ if ((m_buffer || m_closed) && m_client && !m_resumeTimer.isActive())
+ m_resumeTimer.startOneShot(0);
}
void WebSocketChannel::didOpen(SocketStreamHandle* handle)
@@ -234,6 +231,7 @@ bool WebSocketChannel::processBuffer()
ASSERT(!m_suspended);
ASSERT(m_client);
ASSERT(m_buffer);
+
if (m_handshake.mode() == WebSocketHandshake::Incomplete) {
int headerLength = m_handshake.readServerHandshake(m_buffer, m_bufferSize);
if (headerLength <= 0)
@@ -318,6 +316,18 @@ bool WebSocketChannel::processBuffer()
return false;
}
+void WebSocketChannel::resumeTimerFired(Timer<WebSocketChannel>* timer)
+{
+ ASSERT_UNUSED(timer, timer == &m_resumeTimer);
+
+ RefPtr<WebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference.
+ while (!m_suspended && m_client && m_buffer)
+ if (!processBuffer())
+ break;
+ if (!m_suspended && m_client && m_closed && m_handle)
+ didClose(m_handle.get());
+}
+
} // namespace WebCore
#endif // ENABLE(WEB_SOCKETS)
diff --git a/WebCore/websockets/WebSocketChannel.h b/WebCore/websockets/WebSocketChannel.h
index 0cb411d..a90c6dc 100644
--- a/WebCore/websockets/WebSocketChannel.h
+++ b/WebCore/websockets/WebSocketChannel.h
@@ -82,6 +82,7 @@ namespace WebCore {
bool appendToBuffer(const char* data, int len);
void skipBuffer(int len);
bool processBuffer();
+ void resumeTimerFired(Timer<WebSocketChannel>* timer);
ScriptExecutionContext* m_context;
WebSocketChannelClient* m_client;
@@ -90,6 +91,7 @@ namespace WebCore {
char* m_buffer;
int m_bufferSize;
+ Timer<WebSocketChannel> m_resumeTimer;
bool m_suspended;
bool m_closed;
unsigned long m_unhandledBufferedAmount;
diff --git a/WebCore/websockets/WebSocketHandshake.cpp b/WebCore/websockets/WebSocketHandshake.cpp
index ea4f5e5..ba14732 100644
--- a/WebCore/websockets/WebSocketHandshake.cpp
+++ b/WebCore/websockets/WebSocketHandshake.cpp
@@ -35,6 +35,7 @@
#include "WebSocketHandshake.h"
#include "AtomicString.h"
+#include "CharacterNames.h"
#include "Cookie.h"
#include "CookieJar.h"
#include "Document.h"
@@ -56,28 +57,6 @@ namespace WebCore {
static const char randomCharacterInSecWebSocketKey[] = "!\"#$%&'()*+,-./:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
-static String extractResponseCode(const char* header, int len, size_t& lineLength)
-{
- const char* space1 = 0;
- const char* space2 = 0;
- const char* p;
- lineLength = 0;
- for (p = header; p - header < len; p++, lineLength++) {
- if (*p == ' ') {
- if (!space1)
- space1 = p;
- else if (!space2)
- space2 = p;
- } else if (*p == '\n')
- break;
- }
- if (p - header == len)
- return String();
- if (!space1 || !space2)
- return "";
- return String(space1 + 1, space2 - space1 - 1);
-}
-
static String resourceName(const KURL& url)
{
String name = url.path();
@@ -102,11 +81,12 @@ static String hostName(const KURL& url, bool secure)
return builder.toString();
}
+static const size_t maxConsoleMessageSize = 128;
static String trimConsoleMessage(const char* p, size_t len)
{
- String s = String(p, std::min<size_t>(len, 128));
- if (len > 128)
- s += "...";
+ String s = String(p, std::min<size_t>(len, maxConsoleMessageSize));
+ if (len > maxConsoleMessageSize)
+ s.append(horizontalEllipsis);
return s;
}
@@ -279,17 +259,27 @@ WebSocketHandshakeRequest WebSocketHandshake::clientHandshakeRequest() const
// Keep the following consistent with clientHandshakeMessage().
// FIXME: do we need to store m_secWebSocketKey1, m_secWebSocketKey2 and
// m_key3 in WebSocketHandshakeRequest?
- WebSocketHandshakeRequest request(m_url, clientOrigin(), m_clientProtocol);
+ WebSocketHandshakeRequest request("GET", m_url);
+ request.addHeaderField("Upgrade", "WebSocket");
+ request.addHeaderField("Connection", "Upgrade");
+ request.addHeaderField("Host", hostName(m_url, m_secure));
+ request.addHeaderField("Origin", clientOrigin());
+ if (!m_clientProtocol.isEmpty())
+ request.addHeaderField("Sec-WebSocket-Protocol:", m_clientProtocol);
KURL url = httpURLForAuthenticationAndCookies();
if (m_context->isDocument()) {
Document* document = static_cast<Document*>(m_context);
String cookie = cookieRequestHeaderFieldValue(document, url);
if (!cookie.isEmpty())
- request.addExtraHeaderField("Cookie", cookie);
+ request.addHeaderField("Cookie", cookie);
// Set "Cookie2: <cookie>" if cookies 2 exists for url?
}
+ request.addHeaderField("Sec-WebSocket-Key1", m_secWebSocketKey1);
+ request.addHeaderField("Sec-WebSocket-Key2", m_secWebSocketKey2);
+ request.setKey3(m_key3);
+
return request;
}
@@ -312,21 +302,21 @@ void WebSocketHandshake::clearScriptExecutionContext()
int WebSocketHandshake::readServerHandshake(const char* header, size_t len)
{
m_mode = Incomplete;
- size_t lineLength;
- const String& code = extractResponseCode(header, len, lineLength);
- if (code.isNull()) {
- // Just hasn't been received yet.
+ int statusCode;
+ String statusText;
+ int lineLength = readStatusLine(header, len, statusCode, statusText);
+ if (lineLength == -1)
return -1;
- }
- if (code.isEmpty()) {
+ if (statusCode == -1) {
m_mode = Failed;
- m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "No response code found: " + trimConsoleMessage(header, lineLength), 0, clientOrigin());
return len;
}
- LOG(Network, "response code: %s", code.utf8().data());
- if (code != "101") {
+ LOG(Network, "response code: %d", statusCode);
+ m_response.setStatusCode(statusCode);
+ m_response.setStatusText(statusText);
+ if (statusCode != 101) {
m_mode = Failed;
- m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Unexpected response code:" + code, 0, clientOrigin());
+ m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, String::format("Unexpected response code: %d", statusCode), 0, clientOrigin());
return len;
}
m_mode = Normal;
@@ -335,17 +325,14 @@ int WebSocketHandshake::readServerHandshake(const char* header, size_t len)
m_mode = Incomplete;
return -1;
}
- HTTPHeaderMap headers;
- const char* headerFields = strnstr(header, "\r\n", len); // skip status line
- ASSERT(headerFields);
- headerFields += 2; // skip "\r\n".
- const char* p = readHTTPHeaders(headerFields, header + len, &headers);
+ const char* p = readHTTPHeaders(header + lineLength, header + len);
if (!p) {
LOG(Network, "readHTTPHeaders failed");
m_mode = Failed;
return len;
}
- if (!processHeaders(headers) || !checkResponseHeaders()) {
+ processHeaders();
+ if (!checkResponseHeaders()) {
LOG(Network, "header process failed");
m_mode = Failed;
return p - header;
@@ -355,6 +342,7 @@ int WebSocketHandshake::readServerHandshake(const char* header, size_t len)
m_mode = Incomplete;
return -1;
}
+ m_response.setChallengeResponse(static_cast<const unsigned char*>(static_cast<const void*>(p)));
if (memcmp(p, m_expectedChallengeResponse, sizeof(m_expectedChallengeResponse))) {
m_mode = Failed;
return (p - header) + sizeof(m_expectedChallengeResponse);
@@ -418,6 +406,11 @@ void WebSocketHandshake::setServerSetCookie2(const String& setCookie2)
m_setCookie2 = setCookie2;
}
+const WebSocketHandshakeResponse& WebSocketHandshake::serverHandshakeResponse() const
+{
+ return m_response;
+}
+
KURL WebSocketHandshake::httpURLForAuthenticationAndCookies() const
{
KURL url = m_url.copy();
@@ -426,8 +419,70 @@ KURL WebSocketHandshake::httpURLForAuthenticationAndCookies() const
return url;
}
-const char* WebSocketHandshake::readHTTPHeaders(const char* start, const char* end, HTTPHeaderMap* headers)
+// Returns the header length (including "\r\n"), or -1 if we have not received enough data yet.
+// If the line is malformed or the status code is not a 3-digit number,
+// statusCode and statusText will be set to -1 and a null string, respectively.
+int WebSocketHandshake::readStatusLine(const char* header, size_t headerLength, int& statusCode, String& statusText)
{
+ statusCode = -1;
+ statusText = String();
+
+ const char* space1 = 0;
+ const char* space2 = 0;
+ const char* p;
+ size_t consumedLength;
+
+ for (p = header, consumedLength = 0; consumedLength < headerLength; p++, consumedLength++) {
+ if (*p == ' ') {
+ if (!space1)
+ space1 = p;
+ else if (!space2)
+ space2 = p;
+ } else if (*p == '\n')
+ break;
+ }
+ if (consumedLength == headerLength)
+ return -1; // We have not received '\n' yet.
+
+ const char* end = p + 1;
+ if (end - header > INT_MAX) {
+ m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Status line is too long: " + trimConsoleMessage(header, maxConsoleMessageSize + 1), 0, clientOrigin());
+ return INT_MAX;
+ }
+ int lineLength = end - header;
+
+ if (!space1 || !space2) {
+ m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "No response code found: " + trimConsoleMessage(header, lineLength - 1), 0, clientOrigin());
+ return lineLength;
+ }
+
+ // The line must end with "\r\n".
+ if (*(end - 2) != '\r') {
+ m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Status line does not end with CRLF", 0, clientOrigin());
+ return lineLength;
+ }
+
+ String statusCodeString(space1 + 1, space2 - space1 - 1);
+ if (statusCodeString.length() != 3) // Status code must consist of three digits.
+ return lineLength;
+ for (int i = 0; i < 3; ++i)
+ if (statusCodeString[i] < '0' || statusCodeString[i] > '9') {
+ m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Invalid status code: " + statusCodeString, 0, clientOrigin());
+ return lineLength;
+ }
+
+ bool ok = false;
+ statusCode = statusCodeString.toInt(&ok);
+ ASSERT(ok);
+
+ statusText = String(space2 + 1, end - space2 - 3); // Exclude "\r\n".
+ return lineLength;
+}
+
+const char* WebSocketHandshake::readHTTPHeaders(const char* start, const char* end)
+{
+ m_response.clearHeaderFields();
+
Vector<char> name;
Vector<char> value;
for (const char* p = start; p < end; p++) {
@@ -451,10 +506,7 @@ const char* WebSocketHandshake::readHTTPHeaders(const char* start, const char* e
case ':':
break;
default:
- if (*p >= 0x41 && *p <= 0x5a)
- name.append(*p + 0x20);
- else
- name.append(*p);
+ name.append(*p);
continue;
}
if (*p == ':') {
@@ -495,36 +547,21 @@ const char* WebSocketHandshake::readHTTPHeaders(const char* start, const char* e
return 0;
}
LOG(Network, "name=%s value=%s", nameStr.string().utf8().data(), valueStr.utf8().data());
- headers->add(nameStr, valueStr);
+ m_response.addHeaderField(nameStr, valueStr);
}
ASSERT_NOT_REACHED();
return 0;
}
-bool WebSocketHandshake::processHeaders(const HTTPHeaderMap& headers)
-{
- for (HTTPHeaderMap::const_iterator it = headers.begin(); it != headers.end(); ++it) {
- switch (m_mode) {
- case Normal:
- if (it->first == "sec-websocket-origin")
- m_wsOrigin = it->second;
- else if (it->first == "sec-websocket-location")
- m_wsLocation = it->second;
- else if (it->first == "sec-websocket-protocol")
- m_wsProtocol = it->second;
- else if (it->first == "set-cookie")
- m_setCookie = it->second;
- else if (it->first == "set-cookie2")
- m_setCookie2 = it->second;
- continue;
- case Incomplete:
- case Failed:
- case Connected:
- ASSERT_NOT_REACHED();
- }
- ASSERT_NOT_REACHED();
- }
- return true;
+void WebSocketHandshake::processHeaders()
+{
+ ASSERT(m_mode == Normal);
+ const HTTPHeaderMap& headers = m_response.headerFields();
+ m_wsOrigin = headers.get("sec-websocket-origin");
+ m_wsLocation = headers.get("sec-websocket-location");
+ m_wsProtocol = headers.get("sec-websocket-protocol");
+ m_setCookie = headers.get("set-cookie");
+ m_setCookie2 = headers.get("set-cookie2");
}
bool WebSocketHandshake::checkResponseHeaders()
diff --git a/WebCore/websockets/WebSocketHandshake.h b/WebCore/websockets/WebSocketHandshake.h
index 3e0c66a..a5b4260 100644
--- a/WebCore/websockets/WebSocketHandshake.h
+++ b/WebCore/websockets/WebSocketHandshake.h
@@ -36,11 +36,11 @@
#include "KURL.h"
#include "PlatformString.h"
#include "WebSocketHandshakeRequest.h"
+#include "WebSocketHandshakeResponse.h"
#include <wtf/Noncopyable.h>
namespace WebCore {
- class HTTPHeaderMap;
class ScriptExecutionContext;
class WebSocketHandshake : public Noncopyable {
@@ -86,12 +86,16 @@ namespace WebCore {
const String& serverSetCookie2() const;
void setServerSetCookie2(const String& setCookie2);
+ const WebSocketHandshakeResponse& serverHandshakeResponse() const;
+
private:
KURL httpURLForAuthenticationAndCookies() const;
+ int readStatusLine(const char* header, size_t headerLength, int& statusCode, String& statusText);
+
// Reads all headers except for the two predefined ones.
- const char* readHTTPHeaders(const char* start, const char* end, HTTPHeaderMap* headers);
- bool processHeaders(const HTTPHeaderMap& headers);
+ const char* readHTTPHeaders(const char* start, const char* end);
+ void processHeaders();
bool checkResponseHeaders();
KURL m_url;
@@ -111,6 +115,8 @@ namespace WebCore {
String m_secWebSocketKey2;
unsigned char m_key3[8];
unsigned char m_expectedChallengeResponse[16];
+
+ WebSocketHandshakeResponse m_response;
};
} // namespace WebCore
diff --git a/WebCore/websockets/WebSocketHandshakeRequest.cpp b/WebCore/websockets/WebSocketHandshakeRequest.cpp
index 9a41167..1132a44 100644
--- a/WebCore/websockets/WebSocketHandshakeRequest.cpp
+++ b/WebCore/websockets/WebSocketHandshakeRequest.cpp
@@ -34,60 +34,60 @@
#include "WebSocketHandshakeRequest.h"
-#include "AtomicString.h"
-#include "StringBuilder.h"
-#include <utility>
-#include <wtf/Assertions.h>
+#include <cstring>
using namespace std;
namespace WebCore {
-WebSocketHandshakeRequest::WebSocketHandshakeRequest(const KURL& url, const String& origin, const String& webSocketProtocol)
+WebSocketHandshakeRequest::Key3::Key3()
+{
+ memset(value, 0, sizeof(value));
+}
+
+void WebSocketHandshakeRequest::Key3::set(const unsigned char key3[8])
+{
+ memcpy(value, key3, sizeof(value));
+}
+
+WebSocketHandshakeRequest::WebSocketHandshakeRequest(const String& requestMethod, const KURL& url)
: m_url(url)
- , m_secure(m_url.protocolIs("wss"))
- , m_origin(origin)
- , m_webSocketProtocol(webSocketProtocol)
+ , m_requestMethod(requestMethod)
{
- ASSERT(!origin.isNull());
}
WebSocketHandshakeRequest::~WebSocketHandshakeRequest()
{
}
-void WebSocketHandshakeRequest::addExtraHeaderField(const AtomicString& name, const String& value)
+String WebSocketHandshakeRequest::requestMethod() const
+{
+ return m_requestMethod;
+}
+
+KURL WebSocketHandshakeRequest::url() const
+{
+ return m_url;
+}
+
+void WebSocketHandshakeRequest::addHeaderField(const char* name, const String& value)
{
- m_extraHeaderFields.append(HeaderField(name, value));
+ m_headerFields.add(name, value);
}
-void WebSocketHandshakeRequest::addExtraHeaderField(const char* name, const String& value)
+const HTTPHeaderMap& WebSocketHandshakeRequest::headerFields() const
{
- m_extraHeaderFields.append(HeaderField(name, value));
+ return m_headerFields;
}
-Vector<WebSocketHandshakeRequest::HeaderField> WebSocketHandshakeRequest::headerFields() const
+WebSocketHandshakeRequest::Key3 WebSocketHandshakeRequest::key3() const
{
- Vector<HeaderField> fields;
- fields.append(HeaderField("Upgrade", "WebSocket"));
- fields.append(HeaderField("Connection", "Upgrade"));
- fields.append(HeaderField("Host", host()));
- fields.append(HeaderField("Origin", m_origin));
- if (!m_webSocketProtocol.isEmpty())
- fields.append(HeaderField("WebSocket-Protocol", m_webSocketProtocol));
- fields.append(m_extraHeaderFields);
- return fields;
+ return m_key3;
}
-String WebSocketHandshakeRequest::host() const
+void WebSocketHandshakeRequest::setKey3(const unsigned char key3[8])
{
- StringBuilder builder;
- builder.append(m_url.host().lower());
- if ((!m_secure && m_url.port() != 80) || (m_secure && m_url.port() != 443)) {
- builder.append(":");
- builder.append(String::number(m_url.port()));
- }
- return builder.toString();
+ m_key3.set(key3);
}
} // namespace WebCore
diff --git a/WebCore/websockets/WebSocketHandshakeRequest.h b/WebCore/websockets/WebSocketHandshakeRequest.h
index d488135..792f67e 100644
--- a/WebCore/websockets/WebSocketHandshakeRequest.h
+++ b/WebCore/websockets/WebSocketHandshakeRequest.h
@@ -33,37 +33,37 @@
#if ENABLE(WEB_SOCKETS)
+#include "HTTPHeaderMap.h"
#include "KURL.h"
#include "PlatformString.h"
-#include <wtf/Vector.h>
namespace WebCore {
-class AtomicString;
-
class WebSocketHandshakeRequest {
public:
- WebSocketHandshakeRequest(const KURL&, const String& origin, const String& webSocketProtocol);
+ WebSocketHandshakeRequest(const String& requestMethod, const KURL&);
~WebSocketHandshakeRequest();
- // According to current Web Socket protocol specification, four mandatory headers (Upgrade, Connection, Host, and Origin) and
- // one optional header (WebSocket-Protocol) should be sent in this order, at the beginning of the handshake request.
- // The remaining headers can be set by using the following function.
- void addExtraHeaderField(const AtomicString& name, const String& value);
- void addExtraHeaderField(const char* name, const String& value);
+ String requestMethod() const;
+ KURL url() const;
- // Returns the list of header fields including five special ones.
- typedef std::pair<AtomicString, String> HeaderField;
- Vector<HeaderField> headerFields() const;
+ const HTTPHeaderMap& headerFields() const;
+ void addHeaderField(const char* name, const String& value);
-private:
- String host() const;
+ struct Key3 {
+ unsigned char value[8];
+ Key3();
+ void set(const unsigned char key3[8]);
+ };
+ Key3 key3() const;
+ void setKey3(const unsigned char key3[8]);
+
+private:
KURL m_url;
- bool m_secure;
- String m_origin;
- String m_webSocketProtocol;
- Vector<HeaderField> m_extraHeaderFields;
+ String m_requestMethod;
+ HTTPHeaderMap m_headerFields;
+ Key3 m_key3;
};
} // namespace WebCore
diff --git a/WebCore/websockets/WebSocketHandshakeResponse.cpp b/WebCore/websockets/WebSocketHandshakeResponse.cpp
new file mode 100644
index 0000000..753cecf
--- /dev/null
+++ b/WebCore/websockets/WebSocketHandshakeResponse.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(WEB_SOCKETS)
+
+#include "WebSocketHandshakeResponse.h"
+
+#include "AtomicString.h"
+#include <wtf/Assertions.h>
+
+using namespace std;
+
+namespace WebCore {
+
+WebSocketHandshakeResponse::ChallengeResponse::ChallengeResponse()
+{
+ memset(value, 0, sizeof(value));
+}
+
+void WebSocketHandshakeResponse::ChallengeResponse::set(const unsigned char challengeResponse[16])
+{
+ memcpy(value, challengeResponse, sizeof(value));
+}
+
+WebSocketHandshakeResponse::WebSocketHandshakeResponse()
+{
+}
+
+WebSocketHandshakeResponse::~WebSocketHandshakeResponse()
+{
+}
+
+int WebSocketHandshakeResponse::statusCode() const
+{
+ return m_statusCode;
+}
+
+void WebSocketHandshakeResponse::setStatusCode(int statusCode)
+{
+ ASSERT(statusCode >= 100 && statusCode < 600);
+ m_statusCode = statusCode;
+}
+
+const String& WebSocketHandshakeResponse::statusText() const
+{
+ return m_statusText;
+}
+
+void WebSocketHandshakeResponse::setStatusText(const String& statusText)
+{
+ m_statusText = statusText;
+}
+
+const HTTPHeaderMap& WebSocketHandshakeResponse::headerFields() const
+{
+ return m_headerFields;
+}
+
+void WebSocketHandshakeResponse::addHeaderField(const AtomicString& name, const String& value)
+{
+ m_headerFields.add(name, value);
+}
+
+void WebSocketHandshakeResponse::clearHeaderFields()
+{
+ m_headerFields.clear();
+}
+
+const WebSocketHandshakeResponse::ChallengeResponse& WebSocketHandshakeResponse::challengeResponse() const
+{
+ return m_challengeResponse;
+}
+
+void WebSocketHandshakeResponse::setChallengeResponse(const unsigned char challengeResponse[16])
+{
+ m_challengeResponse.set(challengeResponse);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_SOCKETS)
diff --git a/WebCore/websockets/WebSocketHandshakeResponse.h b/WebCore/websockets/WebSocketHandshakeResponse.h
new file mode 100644
index 0000000..c385a1b
--- /dev/null
+++ b/WebCore/websockets/WebSocketHandshakeResponse.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebSocketHandshakeResponse_h
+#define WebSocketHandshakeResponse_h
+
+#if ENABLE(WEB_SOCKETS)
+
+#include "HTTPHeaderMap.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+class AtomicString;
+
+class WebSocketHandshakeResponse {
+public:
+ WebSocketHandshakeResponse();
+ ~WebSocketHandshakeResponse();
+
+ int statusCode() const;
+ void setStatusCode(int statusCode);
+ const String& statusText() const;
+ void setStatusText(const String& statusText);
+ const HTTPHeaderMap& headerFields() const;
+ void addHeaderField(const AtomicString& name, const String& value);
+ void clearHeaderFields();
+
+ struct ChallengeResponse {
+ unsigned char value[16];
+
+ ChallengeResponse();
+ void set(const unsigned char challengeResponse[16]);
+ };
+ const ChallengeResponse& challengeResponse() const;
+ void setChallengeResponse(const unsigned char challengeResponse[16]);
+
+private:
+ int m_statusCode;
+ String m_statusText;
+ HTTPHeaderMap m_headerFields;
+ ChallengeResponse m_challengeResponse;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_SOCKETS)
+
+#endif // WebSocketHandshakeResponse_h