Commit 43db2b60 authored by morrita@google.com's avatar morrita@google.com

2010-06-22 Yuta Kitamura <yutak@chromium.org>

        Reviewed by Alexey Proskuryakov.

        Add a new class that stores information about WebSocket handshake response.

        In the future, instances of the new class will be passed to the Web Inspector
        so that it will be able to display information about WebSocket handshake
        response.

        WebSocket: Add WebSocketHandshakeResponse
        https://bugs.webkit.org/show_bug.cgi?id=38728

        Test: websocket/tests/handshake-fail-by-no-cr.html

        * GNUmakefile.am:
        * WebCore.gypi:
        * WebCore.pro:
        * WebCore.vcproj/WebCore.vcproj:
        * WebCore.xcodeproj/project.pbxproj:
        * websockets/WebSocketHandshake.cpp:
        (WebCore::trimConsoleMessage):
        (WebCore::WebSocketHandshake::readServerHandshake):
        (WebCore::WebSocketHandshake::serverHandshakeResponse):
        (WebCore::WebSocketHandshake::readStatusLine): Moved from extractResponseCode.
        Add more error checks and make error messages more descriptive.
        (WebCore::WebSocketHandshake::readHTTPHeaders):
        (WebCore::WebSocketHandshake::processHeaders):
        * websockets/WebSocketHandshake.h:
        * websockets/WebSocketHandshakeResponse.cpp: Added.
        (WebCore::WebSocketHandshakeResponse::ChallengeResponse::ChallengeResponse):
        (WebCore::WebSocketHandshakeResponse::ChallengeResponse::set):
        (WebCore::WebSocketHandshakeResponse::WebSocketHandshakeResponse):
        (WebCore::WebSocketHandshakeResponse::~WebSocketHandshakeResponse):
        (WebCore::WebSocketHandshakeResponse::statusCode):
        (WebCore::WebSocketHandshakeResponse::setStatusCode):
        (WebCore::WebSocketHandshakeResponse::statusText):
        (WebCore::WebSocketHandshakeResponse::setStatusText):
        (WebCore::WebSocketHandshakeResponse::headerFields):
        (WebCore::WebSocketHandshakeResponse::addHeaderField):
        (WebCore::WebSocketHandshakeResponse::clearHeaderFields):
        (WebCore::WebSocketHandshakeResponse::challengeResponse):
        (WebCore::WebSocketHandshakeResponse::setChallengeResponse):
        * websockets/WebSocketHandshakeResponse.h: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@61671 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 164cf389
CONSOLE MESSAGE: line 0: Status line does not end with CRLF
Handshake should fail when the first line does not end with CRLF.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS connected is false
PASS origin is undefined.
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
<script src="../../fast/js/resources/js-test-pre.js"></script>
<script src="../../fast/js/resources/js-test-post-function.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script src="script-tests/handshake-fail-by-no-cr.js"></script>
</body>
</html>
def web_socket_do_extra_handshake(request):
msg = 'HTTP/1.1 101 WebSocket Protocol Handshake\n' # Does not end with "\r\n".
msg += 'Upgrade: WebSocket\r\n'
msg += 'Connection: Upgrade\r\n'
msg += 'Sec-WebSocket-Location: ' + request.ws_location + '\r\n'
msg += 'Sec-WebSocket-Origin: ' + request.ws_origin + '\r\n'
msg += '\r\n'
msg += request.ws_challenge_md5
request.connection.write(msg)
print msg
def web_socket_transfer_data(request):
pass
CONSOLE MESSAGE: line 0: Unexpected CR in name at pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp...
CONSOLE MESSAGE: line 0: Unexpected CR in name at pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp
Make sure WebSocket gives errors on long invalid upgrade header.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
......
description('Handshake should fail when the first line does not end with CRLF.');
if (window.layoutTestController)
layoutTestController.waitUntilDone()
var connected = false;
var origin;
function endTest() {
shouldBeFalse('connected');
shouldBeUndefined('origin');
clearTimeout(timeoutID);
isSuccessfullyParsed();
if (window.layoutTestController)
layoutTestController.notifyDone();
}
var url = 'ws://localhost:8880/websocket/tests/handshake-fail-by-no-cr';
var ws = new WebSocket(url);
ws.onopen = function()
{
debug('Connected');
connected = true;
}
ws.onmessage = function(messageEvent)
{
origin = messageEvent.data;
debug('origin = ' + origin);
ws.close();
}
ws.onclose = function()
{
endTest();
}
function timeoutCallback()
{
debug('Timed out (state = ' + ws.readyState + ')');
endTest();
}
var timeoutID = setTimeout(timeoutCallback, 3000);
var successfullyParsed = true;
2010-06-22 Yuta Kitamura <yutak@chromium.org>
Reviewed by Alexey Proskuryakov.
Add a new class that stores information about WebSocket handshake response.
In the future, instances of the new class will be passed to the Web Inspector
so that it will be able to display information about WebSocket handshake
response.
WebSocket: Add WebSocketHandshakeResponse
https://bugs.webkit.org/show_bug.cgi?id=38728
Test: websocket/tests/handshake-fail-by-no-cr.html
* GNUmakefile.am:
* WebCore.gypi:
* WebCore.pro:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* websockets/WebSocketHandshake.cpp:
(WebCore::trimConsoleMessage):
(WebCore::WebSocketHandshake::readServerHandshake):
(WebCore::WebSocketHandshake::serverHandshakeResponse):
(WebCore::WebSocketHandshake::readStatusLine): Moved from extractResponseCode.
Add more error checks and make error messages more descriptive.
(WebCore::WebSocketHandshake::readHTTPHeaders):
(WebCore::WebSocketHandshake::processHeaders):
* websockets/WebSocketHandshake.h:
* websockets/WebSocketHandshakeResponse.cpp: Added.
(WebCore::WebSocketHandshakeResponse::ChallengeResponse::ChallengeResponse):
(WebCore::WebSocketHandshakeResponse::ChallengeResponse::set):
(WebCore::WebSocketHandshakeResponse::WebSocketHandshakeResponse):
(WebCore::WebSocketHandshakeResponse::~WebSocketHandshakeResponse):
(WebCore::WebSocketHandshakeResponse::statusCode):
(WebCore::WebSocketHandshakeResponse::setStatusCode):
(WebCore::WebSocketHandshakeResponse::statusText):
(WebCore::WebSocketHandshakeResponse::setStatusText):
(WebCore::WebSocketHandshakeResponse::headerFields):
(WebCore::WebSocketHandshakeResponse::addHeaderField):
(WebCore::WebSocketHandshakeResponse::clearHeaderFields):
(WebCore::WebSocketHandshakeResponse::challengeResponse):
(WebCore::WebSocketHandshakeResponse::setChallengeResponse):
* websockets/WebSocketHandshakeResponse.h: Added.
2010-06-23 Yuzo Fujishima <yuzo@google.com>
Reviewed by Shinichiro Hamaji.
......
......@@ -3777,7 +3777,9 @@ webcore_sources += \
WebCore/websockets/WebSocketHandshake.cpp \
WebCore/websockets/WebSocketHandshake.h \
WebCore/websockets/WebSocketHandshakeRequest.cpp \
WebCore/websockets/WebSocketHandshakeRequest.h
WebCore/websockets/WebSocketHandshakeRequest.h \
WebCore/websockets/WebSocketHandshakeResponse.cpp \
WebCore/websockets/WebSocketHandshakeResponse.h
if ENABLE_WORKERS
webcore_sources += \
......
......@@ -3805,6 +3805,8 @@
'websockets/WebSocketHandshake.h',
'websockets/WebSocketHandshakeRequest.cpp',
'websockets/WebSocketHandshakeRequest.h',
'websockets/WebSocketHandshakeResponse.cpp',
'websockets/WebSocketHandshakeResponse.h',
'websockets/WorkerThreadableWebSocketChannel.cpp',
'websockets/WorkerThreadableWebSocketChannel.h',
'workers/AbstractWorker.cpp',
......
......@@ -2892,6 +2892,7 @@ contains(DEFINES, ENABLE_WEB_SOCKETS=1) {
websockets/WebSocketChannelClient.h \
websockets/WebSocketHandshake.h \
websockets/WebSocketHandshakeRequest.h \
websockets/WebSocketHandshakeResponse.h \
platform/network/qt/SocketStreamHandlePrivate.h
SOURCES += \
......@@ -2899,6 +2900,7 @@ contains(DEFINES, ENABLE_WEB_SOCKETS=1) {
websockets/WebSocketChannel.cpp \
websockets/WebSocketHandshake.cpp \
websockets/WebSocketHandshakeRequest.cpp \
websockets/WebSocketHandshakeResponse.cpp \
websockets/ThreadableWebSocketChannel.cpp \
platform/network/SocketStreamErrorBase.cpp \
platform/network/SocketStreamHandleBase.cpp \
......
......@@ -47728,6 +47728,14 @@
RelativePath="..\websockets\WebSocketHandshakeRequest.h"
>
</File>
<File
RelativePath="..\websockets\WebSocketHandshakeResponse.cpp"
>
</File>
<File
RelativePath="..\websockets\WebSocketHandshakeResponse.h"
>
</File>
<File
RelativePath="..\websockets\WorkerThreadableWebSocketChannel.cpp"
>
......@@ -1321,6 +1321,8 @@
75793ED50D0CE85B007FC0AC /* DOMMessageEventInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 75793ED20D0CE85B007FC0AC /* DOMMessageEventInternal.h */; };
7637C541112E7B74003D6CDC /* WebSocketHandshakeRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7637C540112E7B74003D6CDC /* WebSocketHandshakeRequest.cpp */; };
7637C543112E7B7E003D6CDC /* WebSocketHandshakeRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 7637C542112E7B7E003D6CDC /* WebSocketHandshakeRequest.h */; };
767F99BE11A1194A0080C51D /* WebSocketHandshakeResponse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 767F99BD11A1194A0080C51D /* WebSocketHandshakeResponse.cpp */; };
767F99C011A119560080C51D /* WebSocketHandshakeResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 767F99BF11A119560080C51D /* WebSocketHandshakeResponse.h */; };
7693BAD2106C2DCA007B0823 /* HaltablePlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 7693BACE106C2DCA007B0823 /* HaltablePlugin.h */; settings = {ATTRIBUTES = (Private, ); }; };
7693BAD3106C2DCA007B0823 /* PluginHalter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7693BACF106C2DCA007B0823 /* PluginHalter.cpp */; };
7693BAD4106C2DCA007B0823 /* PluginHalter.h in Headers */ = {isa = PBXBuildFile; fileRef = 7693BAD0106C2DCA007B0823 /* PluginHalter.h */; };
......@@ -6992,6 +6994,8 @@
75793ED20D0CE85B007FC0AC /* DOMMessageEventInternal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DOMMessageEventInternal.h; sourceTree = "<group>"; };
7637C540112E7B74003D6CDC /* WebSocketHandshakeRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSocketHandshakeRequest.cpp; sourceTree = "<group>"; };
7637C542112E7B7E003D6CDC /* WebSocketHandshakeRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSocketHandshakeRequest.h; sourceTree = "<group>"; };
767F99BD11A1194A0080C51D /* WebSocketHandshakeResponse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSocketHandshakeResponse.cpp; sourceTree = "<group>"; };
767F99BF11A119560080C51D /* WebSocketHandshakeResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSocketHandshakeResponse.h; sourceTree = "<group>"; };
7693BACE106C2DCA007B0823 /* HaltablePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HaltablePlugin.h; sourceTree = "<group>"; };
7693BACF106C2DCA007B0823 /* PluginHalter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PluginHalter.cpp; sourceTree = "<group>"; };
7693BAD0106C2DCA007B0823 /* PluginHalter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PluginHalter.h; sourceTree = "<group>"; };
......@@ -11792,6 +11796,8 @@
51ABAE431043AB4A008C5260 /* WebSocketHandshake.h */,
7637C540112E7B74003D6CDC /* WebSocketHandshakeRequest.cpp */,
7637C542112E7B7E003D6CDC /* WebSocketHandshakeRequest.h */,
767F99BD11A1194A0080C51D /* WebSocketHandshakeResponse.cpp */,
767F99BF11A119560080C51D /* WebSocketHandshakeResponse.h */,
5112247710CFB8F4008099D7 /* WorkerThreadableWebSocketChannel.cpp */,
5112247910CFB8FF008099D7 /* WorkerThreadableWebSocketChannel.h */,
);
......@@ -19414,6 +19420,7 @@
510D4A50103177A20049EA54 /* WebSocketChannelClient.h in Headers */,
51ABAE451043AB4A008C5260 /* WebSocketHandshake.h in Headers */,
7637C543112E7B7E003D6CDC /* WebSocketHandshakeRequest.h in Headers */,
767F99C011A119560080C51D /* WebSocketHandshakeResponse.h in Headers */,
0FCF332D0F2B9A25004B6795 /* WebTiledLayer.h in Headers */,
85031B510A44EFC700F992E0 /* WheelEvent.h in Headers */,
9380F47409A11AB4001FDB34 /* Widget.h in Headers */,
......@@ -21741,6 +21748,7 @@
510D4A4E103177A20049EA54 /* WebSocketChannel.cpp in Sources */,
51ABAE441043AB4A008C5260 /* WebSocketHandshake.cpp in Sources */,
7637C541112E7B74003D6CDC /* WebSocketHandshakeRequest.cpp in Sources */,
767F99BE11A1194A0080C51D /* WebSocketHandshakeResponse.cpp in Sources */,
0FCF332C0F2B9A25004B6795 /* WebTiledLayer.mm in Sources */,
85031B500A44EFC700F992E0 /* WheelEvent.cpp in Sources */,
935C477309AC4D7700A6AAB4 /* WheelEventMac.mm in Sources */,
......@@ -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;
}
......@@ -322,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;
......@@ -345,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;
......@@ -365,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);
......@@ -428,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();
......@@ -436,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++) {
......@@ -461,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 == ':') {
......@@ -505,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()
......
......@@ -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
......
/*
* 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()