diff options
author | Kristian Monsen <kristianm@google.com> | 2010-06-28 16:42:48 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2010-07-02 10:29:56 +0100 |
commit | 06ea8e899e48f1f2f396b70e63fae369f2f23232 (patch) | |
tree | 20c1428cd05c76f32394ab354ea35ed99acd86d8 /WebCore/websockets | |
parent | 72aad67af14193199e29cdd5c4ddc095a8b9a8a8 (diff) | |
download | external_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.idl | 9 | ||||
-rw-r--r-- | WebCore/websockets/WebSocketChannel.cpp | 22 | ||||
-rw-r--r-- | WebCore/websockets/WebSocketChannel.h | 2 | ||||
-rw-r--r-- | WebCore/websockets/WebSocketHandshake.cpp | 183 | ||||
-rw-r--r-- | WebCore/websockets/WebSocketHandshake.h | 12 | ||||
-rw-r--r-- | WebCore/websockets/WebSocketHandshakeRequest.cpp | 62 | ||||
-rw-r--r-- | WebCore/websockets/WebSocketHandshakeRequest.h | 36 | ||||
-rw-r--r-- | WebCore/websockets/WebSocketHandshakeResponse.cpp | 110 | ||||
-rw-r--r-- | WebCore/websockets/WebSocketHandshakeResponse.h | 76 |
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 |