bool TEpollHttpSocket::seekRecvBuffer(int pos) { int len = httpBuffer.size(); if (Q_UNLIKELY(pos <= 0 || len + pos > httpBuffer.capacity())) { return false; } len += pos; httpBuffer.resize(len); if (lengthToRead < 0) { parse(); } else { if (limitBodyBytes > 0 && httpBuffer.length() > limitBodyBytes) { throw ClientErrorException(413); // Request Entity Too Large } lengthToRead = qMax(lengthToRead - pos, 0LL); } // WebSocket? if (lengthToRead == 0) { // Check connection header THttpRequestHeader header(httpBuffer); QByteArray connectionHeader = header.rawHeader("Connection").toLower(); if (connectionHeader.contains("upgrade")) { QByteArray upgradeHeader = header.rawHeader("Upgrade").toLower(); tSystemDebug("Upgrade: %s", upgradeHeader.data()); if (upgradeHeader == "websocket") { if (TWebSocket::searchEndpoint(header)) { // Switch protocols switchToWebSocket(header); } else { // WebSocket closing disconnect(); } } clear(); // buffer clear } } return true; }
void TEpollHttpSocket::parse() { if (Q_UNLIKELY(limitBodyBytes < 0)) { limitBodyBytes = Tf::appSettings()->value(Tf::LimitRequestBody, "0").toInt(); } if (Q_LIKELY(lengthToRead < 0)) { int idx = httpBuffer.indexOf("\r\n\r\n"); if (idx > 0) { THttpRequestHeader header(httpBuffer); tSystemDebug("content-length: %d", header.contentLength()); if (limitBodyBytes > 0 && header.contentLength() > (uint)limitBodyBytes) { throw ClientErrorException(413); // Request Entity Too Large } lengthToRead = qMax(idx + 4 + (qint64)header.contentLength() - httpBuffer.length(), 0LL); tSystemDebug("lengthToRead: %d", (int)lengthToRead); } } else { tSystemWarn("Unreachable code in normal communication"); } }
void THttpSocket::readRequest() { T_TRACEFUNC(""); uint limitBodyBytes = Tf::appSettings()->value(Tf::LimitRequestBody, "0").toUInt(); qint64 bytes = 0; QByteArray buf; while ((bytes = bytesAvailable()) > 0) { buf.resize(bytes); int rd = QTcpSocket::read(buf.data(), bytes); if (Q_UNLIKELY(rd != bytes)) { tSystemError("socket read error"); buf.resize(0); break; } idleElapsed = std::time(nullptr); if (lengthToRead > 0) { // Writes to buffer if (fileBuffer.isOpen()) { if (fileBuffer.write(buf.data(), bytes) < 0) { throw RuntimeException(QLatin1String("write error: ") + fileBuffer.fileName(), __FILE__, __LINE__); } } else { readBuffer.append(buf.data(), bytes); } lengthToRead = qMax(lengthToRead - bytes, 0LL); } else if (lengthToRead < 0) { readBuffer.append(buf); int idx = readBuffer.indexOf("\r\n\r\n"); if (idx > 0) { THttpRequestHeader header(readBuffer); tSystemDebug("content-length: %d", header.contentLength()); if (Q_UNLIKELY(limitBodyBytes > 0 && header.contentLength() > limitBodyBytes)) { throw ClientErrorException(413); // Request Entity Too Large } lengthToRead = qMax(idx + 4 + (qint64)header.contentLength() - readBuffer.length(), 0LL); if (header.contentType().trimmed().startsWith("multipart/form-data") || header.contentLength() > READ_THRESHOLD_LENGTH) { // Writes to file buffer if (Q_UNLIKELY(!fileBuffer.open())) { throw RuntimeException(QLatin1String("temporary file open error: ") + fileBuffer.fileTemplate(), __FILE__, __LINE__); } if (readBuffer.length() > idx + 4) { tSystemDebug("fileBuffer name: %s", qPrintable(fileBuffer.fileName())); if (fileBuffer.write(readBuffer.data() + idx + 4, readBuffer.length() - (idx + 4)) < 0) { throw RuntimeException(QLatin1String("write error: ") + fileBuffer.fileName(), __FILE__, __LINE__); } } } } } else { // do nothing break; } if (lengthToRead == 0) { emit newRequest(); } } }