int WebSocketHandshake::readServerHandshake(const char* header, size_t len) { m_mode = Incomplete; int statusCode; String statusText; int lineLength = readStatusLine(header, len, statusCode, statusText); if (lineLength == -1) return -1; if (statusCode == -1) { m_mode = Failed; // m_failureReason is set inside readStatusLine(). return len; } LOG(Network, "response code: %d", statusCode); m_response.setStatusCode(statusCode); m_response.setStatusText(statusText); if (statusCode != 101) { m_mode = Failed; m_failureReason = "Unexpected response code: " + String::number(statusCode); return len; } m_mode = Normal; if (!strnstr(header, "\r\n\r\n", len)) { // Just hasn't been received fully yet. m_mode = Incomplete; return -1; } const char* p = readHTTPHeaders(header + lineLength, header + len); if (!p) { LOG(Network, "readHTTPHeaders failed"); m_mode = Failed; // m_failureReason is set inside readHTTPHeaders(). return len; } if (!checkResponseHeaders()) { LOG(Network, "header process failed"); m_mode = Failed; return p - header; } if (!m_useHixie76Protocol) { // Hybi-10 handshake is complete at this point. m_mode = Connected; return p - header; } // In hixie-76 protocol, server's handshake contains sixteen-byte data (called "challenge response") // after the header fields. if (len < static_cast<size_t>(p - header + sizeof(m_hixie76ExpectedChallengeResponse))) { // Just hasn't been received /expected/ yet. m_mode = Incomplete; return -1; } m_response.setChallengeResponse(static_cast<const unsigned char*>(static_cast<const void*>(p))); if (memcmp(p, m_hixie76ExpectedChallengeResponse, sizeof(m_hixie76ExpectedChallengeResponse))) { m_mode = Failed; return (p - header) + sizeof(m_hixie76ExpectedChallengeResponse); } m_mode = Connected; return (p - header) + sizeof(m_hixie76ExpectedChallengeResponse); }
int WebSocketHandshake::readServerHandshake(const char* header, size_t len) { m_mode = Incomplete; int statusCode; String statusText; int lineLength = readStatusLine(header, len, statusCode, statusText); if (lineLength == -1) return -1; if (statusCode == -1) { m_mode = Failed; return len; } 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: " + String::number(statusCode), 0, clientOrigin(), 0); return len; } m_mode = Normal; if (!strnstr(header, "\r\n\r\n", len)) { // Just hasn't been received fully yet. m_mode = Incomplete; return -1; } const char* p = readHTTPHeaders(header + lineLength, header + len); if (!p) { LOG(Network, "readHTTPHeaders failed"); m_mode = Failed; return len; } if (!checkResponseHeaders()) { LOG(Network, "header process failed"); m_mode = Failed; return p - header; } if (len < static_cast<size_t>(p - header + sizeof(m_expectedChallengeResponse))) { // Just hasn't been received /expected/ yet. 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); } m_mode = Connected; return (p - header) + sizeof(m_expectedChallengeResponse); }
int WebSocketHandshake::readServerHandshake(const char* header, size_t len) { m_mode = Incomplete; int statusCode; String statusText; int lineLength = readStatusLine(header, len, statusCode, statusText); if (lineLength == -1) return -1; if (statusCode == -1) { m_mode = Failed; // m_failureReason is set inside readStatusLine(). return len; } LOG(Network, "WebSocketHandshake %p readServerHandshake() Status code is %d", this, statusCode); m_serverHandshakeResponse = ResourceResponse(); m_serverHandshakeResponse.setHTTPStatusCode(statusCode); m_serverHandshakeResponse.setHTTPStatusText(statusText); if (statusCode != 101) { m_mode = Failed; m_failureReason = "Unexpected response code: " + String::number(statusCode); return len; } m_mode = Normal; if (!strnstr(header, "\r\n\r\n", len)) { // Just hasn't been received fully yet. m_mode = Incomplete; return -1; } const char* p = readHTTPHeaders(header + lineLength, header + len); if (!p) { LOG(Network, "WebSocketHandshake %p readServerHandshake() readHTTPHeaders() failed", this); m_mode = Failed; // m_failureReason is set inside readHTTPHeaders(). return len; } if (!checkResponseHeaders()) { LOG(Network, "WebSocketHandshake %p readServerHandshake() checkResponseHeaders() failed", this); m_mode = Failed; return p - header; } m_mode = Connected; return p - header; }
int WebSocketHandshake::readServerHandshake(const char* header, size_t len) { m_mode = Incomplete; if (len < sizeof(webSocketServerHandshakeHeader) - 1) { // Just hasn't been received fully yet. return -1; } if (!memcmp(header, webSocketServerHandshakeHeader, sizeof(webSocketServerHandshakeHeader) - 1)) m_mode = Normal; else { const String& code = extractResponseCode(header, len); if (code.isNull()) { m_context->addMessage(ConsoleDestination, JSMessageSource, LogMessageType, ErrorMessageLevel, "Short server handshake: " + String(header, len), 0, clientOrigin()); return -1; } if (code.isEmpty()) { m_mode = Failed; m_context->addMessage(ConsoleDestination, JSMessageSource, LogMessageType, ErrorMessageLevel, "No response code found: " + String(header, len), 0, clientOrigin()); return len; } LOG(Network, "response code: %s", code.utf8().data()); if (code == "401") { m_mode = Failed; m_context->addMessage(ConsoleDestination, JSMessageSource, LogMessageType, ErrorMessageLevel, "Authentication required, but not implemented yet.", 0, clientOrigin()); return len; } else { m_mode = Failed; m_context->addMessage(ConsoleDestination, JSMessageSource, LogMessageType, ErrorMessageLevel, "Unexpected response code:" + code, 0, clientOrigin()); return len; } } const char* p = header + sizeof(webSocketServerHandshakeHeader) - 1; const char* end = header + len + 1; if (m_mode == Normal) { size_t headerSize = end - p; if (headerSize < sizeof(webSocketUpgradeHeader) - 1) { m_mode = Incomplete; return 0; } if (memcmp(p, webSocketUpgradeHeader, sizeof(webSocketUpgradeHeader) - 1)) { m_mode = Failed; m_context->addMessage(ConsoleDestination, JSMessageSource, LogMessageType, ErrorMessageLevel, "Bad Upgrade header: " + String(p, end - p), 0, clientOrigin()); return p - header + sizeof(webSocketUpgradeHeader) - 1; } p += sizeof(webSocketUpgradeHeader) - 1; headerSize = end - p; if (headerSize < sizeof(webSocketConnectionHeader) - 1) { m_mode = Incomplete; return -1; } if (memcmp(p, webSocketConnectionHeader, sizeof(webSocketConnectionHeader) - 1)) { m_mode = Failed; m_context->addMessage(ConsoleDestination, JSMessageSource, LogMessageType, ErrorMessageLevel, "Bad Connection header: " + String(p, end - p), 0, clientOrigin()); return p - header + sizeof(webSocketConnectionHeader) - 1; } p += sizeof(webSocketConnectionHeader) - 1; } if (!strnstr(p, "\r\n\r\n", end - p)) { // Just hasn't been received fully yet. m_mode = Incomplete; return -1; } HTTPHeaderMap headers; p = readHTTPHeaders(p, end, &headers); if (!p) { LOG(Network, "readHTTPHeaders failed"); m_mode = Failed; return len; } if (!processHeaders(headers)) { LOG(Network, "header process failed"); m_mode = Failed; return p - header; } switch (m_mode) { case Normal: checkResponseHeaders(); break; default: m_mode = Failed; break; } return p - header; }