Пример #1
0
void InspectorServerRequestHandlerQt::tcpReadyRead()
{
    QHttpRequestHeader header;
    bool isWebSocket = false;
    if (!m_tcpConnection)
        return;

    if (!m_endOfHeaders) {
        while (m_tcpConnection->bytesAvailable() && !m_endOfHeaders) {
            QByteArray line = m_tcpConnection->readLine();
            m_data.append(line);
            if (line == "\r\n")
                m_endOfHeaders = true;
        }
        if (m_endOfHeaders) {
            header = QHttpRequestHeader(QString::fromLatin1(m_data));
            if (header.isValid()) {
                m_path = header.path();
                m_contentType = header.contentType().toLatin1();
                m_contentLength = header.contentLength();
                if (header.hasKey("Upgrade") && (header.value("Upgrade") == QLatin1String("WebSocket")))
                    isWebSocket = true;

                m_data.clear();
            }
        }
    }

    if (m_endOfHeaders) {
        QStringList pathAndQuery = m_path.split("?");
        m_path = pathAndQuery[0];
        QStringList words = m_path.split(QString::fromLatin1("/"));

        if (isWebSocket) {
            // switch to websocket-style WebSocketService messaging
            if (m_tcpConnection) {
                m_tcpConnection->disconnect(SIGNAL(readyRead()));
                connect(m_tcpConnection, SIGNAL(readyRead()), SLOT(webSocketReadyRead()));

                QByteArray key3 = m_tcpConnection->read(8);

                quint32 number1 = parseWebSocketChallengeNumber(header.value("Sec-WebSocket-Key1"));
                quint32 number2 = parseWebSocketChallengeNumber(header.value("Sec-WebSocket-Key2"));

                char responseData[16];
                generateWebSocketChallengeResponse(number1, number2, (unsigned char*)key3.data(), (unsigned char*)responseData);
                QByteArray response(responseData, sizeof(responseData));

                QHttpResponseHeader responseHeader(101, "WebSocket Protocol Handshake", 1, 1);
                responseHeader.setValue("Upgrade", header.value("Upgrade"));
                responseHeader.setValue("Connection", header.value("Connection"));
                responseHeader.setValue("Sec-WebSocket-Origin", header.value("Origin"));
                responseHeader.setValue("Sec-WebSocket-Location", ("ws://" + header.value("Host") + m_path));
                responseHeader.setContentLength(response.size());
                m_tcpConnection->write(responseHeader.toString().toLatin1());
                m_tcpConnection->write(response);
                m_tcpConnection->flush();

                if ((words.size() == 4)
                        && (words[1] == QString::fromLatin1("devtools"))
                        && (words[2] == QString::fromLatin1("page"))) {
                    int pageNum = words[3].toInt();

                    m_inspectorClient = m_server->inspectorClientForPage(pageNum);
                    // Attach remoteFrontendChannel to inspector, also transferring ownership.
                    if (m_inspectorClient)
                        m_inspectorClient->attachAndReplaceRemoteFrontend(new RemoteFrontendChannel(this));
                }

            }

            return;
        }
        if (m_contentLength && (m_tcpConnection->bytesAvailable() < m_contentLength))
            return;

        QByteArray content = m_tcpConnection->read(m_contentLength);
        m_endOfHeaders = false;

        QByteArray response;
        int code = 200;
        QString text = QString::fromLatin1("OK");

        // If no path is specified, generate an index page.
        if ((m_path == "") || (m_path == "/")) {
            QString indexHtml = "<html><head><title>Remote Web Inspector</title></head><body><ul>\n";
            for (QMap<int, InspectorClientQt* >::const_iterator it = m_server->m_inspectorClients.begin();
                    it != m_server->m_inspectorClients.end();
                    ++it) {
                indexHtml.append(QString("<li><a href=\"/webkit/inspector/inspector.html?page=%1\">%2</li>\n")
                                 .arg(it.key())
                                 .arg(it.value()->m_inspectedWebPage->mainFrame()->url().toString()));
            }
            indexHtml.append("</ul></body></html>");
            response = indexHtml.toLatin1();
        } else {
            QString path = QString(":%1").arg(m_path);
            QFile file(path);
            // It seems that there should be an enum or define for these status codes somewhere in Qt or WebKit,
            // but grep fails to turn one up.
            // QNetwork uses the numeric values directly.
            if (file.exists()) {
                file.open(QIODevice::ReadOnly);
                response = file.readAll();
            } else {
                code = 404;
                text = QString::fromLatin1("Not OK");
            }
        }

        QHttpResponseHeader responseHeader(code, text, 1, 0);
        responseHeader.setContentLength(response.size());
        if (!m_contentType.isEmpty())
            responseHeader.setContentType(QString::fromLatin1(m_contentType));

        QByteArray asciiHeader = responseHeader.toString().toAscii();
        m_tcpConnection->write(asciiHeader);

        m_tcpConnection->write(response);
        m_tcpConnection->flush();
        m_tcpConnection->close();

        return;
    }
}