Changeset 61671 in webkit


Ignore:
Timestamp:
Jun 23, 2010 12:37:50 AM (14 years ago)
Author:
morrita@google.com
Message:

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.
Location:
trunk
Files:
6 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/websocket/tests/long-invalid-header-expected.txt

    r59903 r61671  
    1 CONSOLE MESSAGE: line 0: Unexpected CR in name at pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp...
     1CONSOLE MESSAGE: line 0: Unexpected CR in name at pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp
    22Make sure WebSocket gives errors on long invalid upgrade header.
    33
  • trunk/WebCore/ChangeLog

    r61670 r61671  
     12010-06-22  Yuta Kitamura  <yutak@chromium.org>
     2
     3        Reviewed by Alexey Proskuryakov.
     4
     5        Add a new class that stores information about WebSocket handshake response.
     6
     7        In the future, instances of the new class will be passed to the Web Inspector
     8        so that it will be able to display information about WebSocket handshake
     9        response.
     10
     11        WebSocket: Add WebSocketHandshakeResponse
     12        https://bugs.webkit.org/show_bug.cgi?id=38728
     13
     14        Test: websocket/tests/handshake-fail-by-no-cr.html
     15
     16        * GNUmakefile.am:
     17        * WebCore.gypi:
     18        * WebCore.pro:
     19        * WebCore.vcproj/WebCore.vcproj:
     20        * WebCore.xcodeproj/project.pbxproj:
     21        * websockets/WebSocketHandshake.cpp:
     22        (WebCore::trimConsoleMessage):
     23        (WebCore::WebSocketHandshake::readServerHandshake):
     24        (WebCore::WebSocketHandshake::serverHandshakeResponse):
     25        (WebCore::WebSocketHandshake::readStatusLine): Moved from extractResponseCode.
     26        Add more error checks and make error messages more descriptive.
     27        (WebCore::WebSocketHandshake::readHTTPHeaders):
     28        (WebCore::WebSocketHandshake::processHeaders):
     29        * websockets/WebSocketHandshake.h:
     30        * websockets/WebSocketHandshakeResponse.cpp: Added.
     31        (WebCore::WebSocketHandshakeResponse::ChallengeResponse::ChallengeResponse):
     32        (WebCore::WebSocketHandshakeResponse::ChallengeResponse::set):
     33        (WebCore::WebSocketHandshakeResponse::WebSocketHandshakeResponse):
     34        (WebCore::WebSocketHandshakeResponse::~WebSocketHandshakeResponse):
     35        (WebCore::WebSocketHandshakeResponse::statusCode):
     36        (WebCore::WebSocketHandshakeResponse::setStatusCode):
     37        (WebCore::WebSocketHandshakeResponse::statusText):
     38        (WebCore::WebSocketHandshakeResponse::setStatusText):
     39        (WebCore::WebSocketHandshakeResponse::headerFields):
     40        (WebCore::WebSocketHandshakeResponse::addHeaderField):
     41        (WebCore::WebSocketHandshakeResponse::clearHeaderFields):
     42        (WebCore::WebSocketHandshakeResponse::challengeResponse):
     43        (WebCore::WebSocketHandshakeResponse::setChallengeResponse):
     44        * websockets/WebSocketHandshakeResponse.h: Added.
     45
    1462010-06-23  Yuzo Fujishima  <yuzo@google.com>
    247
  • trunk/WebCore/GNUmakefile.am

    r61665 r61671  
    37783778        WebCore/websockets/WebSocketHandshake.h \
    37793779        WebCore/websockets/WebSocketHandshakeRequest.cpp \
    3780         WebCore/websockets/WebSocketHandshakeRequest.h
     3780        WebCore/websockets/WebSocketHandshakeRequest.h \
     3781        WebCore/websockets/WebSocketHandshakeResponse.cpp \
     3782        WebCore/websockets/WebSocketHandshakeResponse.h
    37813783
    37823784if ENABLE_WORKERS
  • trunk/WebCore/WebCore.gypi

    r61665 r61671  
    38063806            'websockets/WebSocketHandshakeRequest.cpp',
    38073807            'websockets/WebSocketHandshakeRequest.h',
     3808            'websockets/WebSocketHandshakeResponse.cpp',
     3809            'websockets/WebSocketHandshakeResponse.h',
    38083810            'websockets/WorkerThreadableWebSocketChannel.cpp',
    38093811            'websockets/WorkerThreadableWebSocketChannel.h',
  • trunk/WebCore/WebCore.pro

    r61665 r61671  
    28932893        websockets/WebSocketHandshake.h \
    28942894        websockets/WebSocketHandshakeRequest.h \
     2895        websockets/WebSocketHandshakeResponse.h \
    28952896        platform/network/qt/SocketStreamHandlePrivate.h
    28962897
     
    29002901        websockets/WebSocketHandshake.cpp \
    29012902        websockets/WebSocketHandshakeRequest.cpp \
     2903        websockets/WebSocketHandshakeResponse.cpp \
    29022904        websockets/ThreadableWebSocketChannel.cpp \
    29032905        platform/network/SocketStreamErrorBase.cpp \
  • trunk/WebCore/WebCore.vcproj/WebCore.vcproj

    r61665 r61671  
    4773047730                        </File>
    4773147731                        <File
     47732                                RelativePath="..\websockets\WebSocketHandshakeResponse.cpp"
     47733                                >
     47734                        </File>
     47735                        <File
     47736                                RelativePath="..\websockets\WebSocketHandshakeResponse.h"
     47737                                >
     47738                        </File>
     47739                        <File
    4773247740                                RelativePath="..\websockets\WorkerThreadableWebSocketChannel.cpp"
    4773347741                                >
  • trunk/WebCore/WebCore.xcodeproj/project.pbxproj

    r61665 r61671  
    13221322                7637C541112E7B74003D6CDC /* WebSocketHandshakeRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7637C540112E7B74003D6CDC /* WebSocketHandshakeRequest.cpp */; };
    13231323                7637C543112E7B7E003D6CDC /* WebSocketHandshakeRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 7637C542112E7B7E003D6CDC /* WebSocketHandshakeRequest.h */; };
     1324                767F99BE11A1194A0080C51D /* WebSocketHandshakeResponse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 767F99BD11A1194A0080C51D /* WebSocketHandshakeResponse.cpp */; };
     1325                767F99C011A119560080C51D /* WebSocketHandshakeResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 767F99BF11A119560080C51D /* WebSocketHandshakeResponse.h */; };
    13241326                7693BAD2106C2DCA007B0823 /* HaltablePlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 7693BACE106C2DCA007B0823 /* HaltablePlugin.h */; settings = {ATTRIBUTES = (Private, ); }; };
    13251327                7693BAD3106C2DCA007B0823 /* PluginHalter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7693BACF106C2DCA007B0823 /* PluginHalter.cpp */; };
     
    69936995                7637C540112E7B74003D6CDC /* WebSocketHandshakeRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSocketHandshakeRequest.cpp; sourceTree = "<group>"; };
    69946996                7637C542112E7B7E003D6CDC /* WebSocketHandshakeRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSocketHandshakeRequest.h; sourceTree = "<group>"; };
     6997                767F99BD11A1194A0080C51D /* WebSocketHandshakeResponse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSocketHandshakeResponse.cpp; sourceTree = "<group>"; };
     6998                767F99BF11A119560080C51D /* WebSocketHandshakeResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSocketHandshakeResponse.h; sourceTree = "<group>"; };
    69956999                7693BACE106C2DCA007B0823 /* HaltablePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HaltablePlugin.h; sourceTree = "<group>"; };
    69967000                7693BACF106C2DCA007B0823 /* PluginHalter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PluginHalter.cpp; sourceTree = "<group>"; };
     
    1179311797                                7637C540112E7B74003D6CDC /* WebSocketHandshakeRequest.cpp */,
    1179411798                                7637C542112E7B7E003D6CDC /* WebSocketHandshakeRequest.h */,
     11799                                767F99BD11A1194A0080C51D /* WebSocketHandshakeResponse.cpp */,
     11800                                767F99BF11A119560080C51D /* WebSocketHandshakeResponse.h */,
    1179511801                                5112247710CFB8F4008099D7 /* WorkerThreadableWebSocketChannel.cpp */,
    1179611802                                5112247910CFB8FF008099D7 /* WorkerThreadableWebSocketChannel.h */,
     
    1941519421                                51ABAE451043AB4A008C5260 /* WebSocketHandshake.h in Headers */,
    1941619422                                7637C543112E7B7E003D6CDC /* WebSocketHandshakeRequest.h in Headers */,
     19423                                767F99C011A119560080C51D /* WebSocketHandshakeResponse.h in Headers */,
    1941719424                                0FCF332D0F2B9A25004B6795 /* WebTiledLayer.h in Headers */,
    1941819425                                85031B510A44EFC700F992E0 /* WheelEvent.h in Headers */,
     
    2174221749                                51ABAE441043AB4A008C5260 /* WebSocketHandshake.cpp in Sources */,
    2174321750                                7637C541112E7B74003D6CDC /* WebSocketHandshakeRequest.cpp in Sources */,
     21751                                767F99BE11A1194A0080C51D /* WebSocketHandshakeResponse.cpp in Sources */,
    2174421752                                0FCF332C0F2B9A25004B6795 /* WebTiledLayer.mm in Sources */,
    2174521753                                85031B500A44EFC700F992E0 /* WheelEvent.cpp in Sources */,
  • trunk/WebCore/websockets/WebSocketHandshake.cpp

    r61611 r61671  
    3636
    3737#include "AtomicString.h"
     38#include "CharacterNames.h"
    3839#include "Cookie.h"
    3940#include "CookieJar.h"
     
    5758static const char randomCharacterInSecWebSocketKey[] = "!\"#$%&'()*+,-./:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
    5859
    59 static String extractResponseCode(const char* header, int len, size_t& lineLength)
    60 {
    61     const char* space1 = 0;
    62     const char* space2 = 0;
    63     const char* p;
    64     lineLength = 0;
    65     for (p = header; p - header < len; p++, lineLength++) {
    66         if (*p == ' ') {
    67             if (!space1)
    68                 space1 = p;
    69             else if (!space2)
    70                 space2 = p;
    71         } else if (*p == '\n')
    72             break;
    73     }
    74     if (p - header == len)
    75         return String();
    76     if (!space1 || !space2)
    77         return "";
    78     return String(space1 + 1, space2 - space1 - 1);
    79 }
    80 
    8160static String resourceName(const KURL& url)
    8261{
     
    10382}
    10483
     84static const size_t maxConsoleMessageSize = 128;
    10585static String trimConsoleMessage(const char* p, size_t len)
    10686{
    107     String s = String(p, std::min<size_t>(len, 128));
    108     if (len > 128)
    109         s += "...";
     87    String s = String(p, std::min<size_t>(len, maxConsoleMessageSize));
     88    if (len > maxConsoleMessageSize)
     89        s.append(horizontalEllipsis);
    11090    return s;
    11191}
     
    323303{
    324304    m_mode = Incomplete;
    325     size_t lineLength;
    326     const String& code = extractResponseCode(header, len, lineLength);
    327     if (code.isNull()) {
    328         // Just hasn't been received yet.
     305    int statusCode;
     306    String statusText;
     307    int lineLength = readStatusLine(header, len, statusCode, statusText);
     308    if (lineLength == -1)
    329309        return -1;
    330     }
    331     if (code.isEmpty()) {
     310    if (statusCode == -1) {
    332311        m_mode = Failed;
    333         m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "No response code found: " + trimConsoleMessage(header, lineLength), 0, clientOrigin());
    334312        return len;
    335313    }
    336     LOG(Network, "response code: %s", code.utf8().data());
    337     if (code != "101") {
     314    LOG(Network, "response code: %d", statusCode);
     315    m_response.setStatusCode(statusCode);
     316    m_response.setStatusText(statusText);
     317    if (statusCode != 101) {
    338318        m_mode = Failed;
    339         m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Unexpected response code:" + code, 0, clientOrigin());
     319        m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, String::format("Unexpected response code: %d", statusCode), 0, clientOrigin());
    340320        return len;
    341321    }
     
    346326        return -1;
    347327    }
    348     HTTPHeaderMap headers;
    349     const char* headerFields = strnstr(header, "\r\n", len); // skip status line
    350     ASSERT(headerFields);
    351     headerFields += 2; // skip "\r\n".
    352     const char* p = readHTTPHeaders(headerFields, header + len, &headers);
     328    const char* p = readHTTPHeaders(header + lineLength, header + len);
    353329    if (!p) {
    354330        LOG(Network, "readHTTPHeaders failed");
     
    356332        return len;
    357333    }
    358     if (!processHeaders(headers) || !checkResponseHeaders()) {
     334    processHeaders();
     335    if (!checkResponseHeaders()) {
    359336        LOG(Network, "header process failed");
    360337        m_mode = Failed;
     
    366343        return -1;
    367344    }
     345    m_response.setChallengeResponse(static_cast<const unsigned char*>(static_cast<const void*>(p)));
    368346    if (memcmp(p, m_expectedChallengeResponse, sizeof(m_expectedChallengeResponse))) {
    369347        m_mode = Failed;
     
    427405{
    428406    m_setCookie2 = setCookie2;
     407}
     408
     409const WebSocketHandshakeResponse& WebSocketHandshake::serverHandshakeResponse() const
     410{
     411    return m_response;
    429412}
    430413
     
    437420}
    438421
    439 const char* WebSocketHandshake::readHTTPHeaders(const char* start, const char* end, HTTPHeaderMap* headers)
    440 {
     422// Returns the header length (including "\r\n"), or -1 if we have not received enough data yet.
     423// If the line is malformed or the status code is not a 3-digit number,
     424// statusCode and statusText will be set to -1 and a null string, respectively.
     425int WebSocketHandshake::readStatusLine(const char* header, size_t headerLength, int& statusCode, String& statusText)
     426{
     427    statusCode = -1;
     428    statusText = String();
     429
     430    const char* space1 = 0;
     431    const char* space2 = 0;
     432    const char* p;
     433    size_t consumedLength;
     434
     435    for (p = header, consumedLength = 0; consumedLength < headerLength; p++, consumedLength++) {
     436        if (*p == ' ') {
     437            if (!space1)
     438                space1 = p;
     439            else if (!space2)
     440                space2 = p;
     441        } else if (*p == '\n')
     442            break;
     443    }
     444    if (consumedLength == headerLength)
     445        return -1; // We have not received '\n' yet.
     446
     447    const char* end = p + 1;
     448    if (end - header > INT_MAX) {
     449        m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Status line is too long: " + trimConsoleMessage(header, maxConsoleMessageSize + 1), 0, clientOrigin());
     450        return INT_MAX;
     451    }
     452    int lineLength = end - header;
     453
     454    if (!space1 || !space2) {
     455        m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "No response code found: " + trimConsoleMessage(header, lineLength - 1), 0, clientOrigin());
     456        return lineLength;
     457    }
     458
     459    // The line must end with "\r\n".
     460    if (*(end - 2) != '\r') {
     461        m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Status line does not end with CRLF", 0, clientOrigin());
     462        return lineLength;
     463    }
     464
     465    String statusCodeString(space1 + 1, space2 - space1 - 1);
     466    if (statusCodeString.length() != 3) // Status code must consist of three digits.
     467        return lineLength;
     468    for (int i = 0; i < 3; ++i)
     469        if (statusCodeString[i] < '0' || statusCodeString[i] > '9') {
     470            m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Invalid status code: " + statusCodeString, 0, clientOrigin());
     471            return lineLength;
     472        }
     473
     474    bool ok = false;
     475    statusCode = statusCodeString.toInt(&ok);
     476    ASSERT(ok);
     477
     478    statusText = String(space2 + 1, end - space2 - 3); // Exclude "\r\n".
     479    return lineLength;
     480}
     481
     482const char* WebSocketHandshake::readHTTPHeaders(const char* start, const char* end)
     483{
     484    m_response.clearHeaderFields();
     485
    441486    Vector<char> name;
    442487    Vector<char> value;
     
    462507                break;
    463508            default:
    464                 if (*p >= 0x41 && *p <= 0x5a)
    465                     name.append(*p + 0x20);
    466                 else
    467                     name.append(*p);
     509                name.append(*p);
    468510                continue;
    469511            }
     
    506548        }
    507549        LOG(Network, "name=%s value=%s", nameStr.string().utf8().data(), valueStr.utf8().data());
    508         headers->add(nameStr, valueStr);
     550        m_response.addHeaderField(nameStr, valueStr);
    509551    }
    510552    ASSERT_NOT_REACHED();
     
    512554}
    513555
    514 bool WebSocketHandshake::processHeaders(const HTTPHeaderMap& headers)
    515 {
    516     for (HTTPHeaderMap::const_iterator it = headers.begin(); it != headers.end(); ++it) {
    517         switch (m_mode) {
    518         case Normal:
    519             if (it->first == "sec-websocket-origin")
    520                 m_wsOrigin = it->second;
    521             else if (it->first == "sec-websocket-location")
    522                 m_wsLocation = it->second;
    523             else if (it->first == "sec-websocket-protocol")
    524                 m_wsProtocol = it->second;
    525             else if (it->first == "set-cookie")
    526                 m_setCookie = it->second;
    527             else if (it->first == "set-cookie2")
    528                 m_setCookie2 = it->second;
    529             continue;
    530         case Incomplete:
    531         case Failed:
    532         case Connected:
    533             ASSERT_NOT_REACHED();
    534         }
    535         ASSERT_NOT_REACHED();
    536     }
    537     return true;
     556void WebSocketHandshake::processHeaders()
     557{
     558    ASSERT(m_mode == Normal);
     559    const HTTPHeaderMap& headers = m_response.headerFields();
     560    m_wsOrigin = headers.get("sec-websocket-origin");
     561    m_wsLocation = headers.get("sec-websocket-location");
     562    m_wsProtocol = headers.get("sec-websocket-protocol");
     563    m_setCookie = headers.get("set-cookie");
     564    m_setCookie2 = headers.get("set-cookie2");
    538565}
    539566
  • trunk/WebCore/websockets/WebSocketHandshake.h

    r59903 r61671  
    3737#include "PlatformString.h"
    3838#include "WebSocketHandshakeRequest.h"
     39#include "WebSocketHandshakeResponse.h"
    3940#include <wtf/Noncopyable.h>
    4041
    4142namespace WebCore {
    4243
    43     class HTTPHeaderMap;
    4444    class ScriptExecutionContext;
    4545
     
    8787        void setServerSetCookie2(const String& setCookie2);
    8888
     89        const WebSocketHandshakeResponse& serverHandshakeResponse() const;
     90
    8991    private:
    9092        KURL httpURLForAuthenticationAndCookies() const;
    9193
     94        int readStatusLine(const char* header, size_t headerLength, int& statusCode, String& statusText);
     95
    9296        // Reads all headers except for the two predefined ones.
    93         const char* readHTTPHeaders(const char* start, const char* end, HTTPHeaderMap* headers);
    94         bool processHeaders(const HTTPHeaderMap& headers);
     97        const char* readHTTPHeaders(const char* start, const char* end);
     98        void processHeaders();
    9599        bool checkResponseHeaders();
    96100
     
    112116        unsigned char m_key3[8];
    113117        unsigned char m_expectedChallengeResponse[16];
     118
     119        WebSocketHandshakeResponse m_response;
    114120    };
    115121
Note: See TracChangeset for help on using the changeset viewer.