void Widget::tcpProcessPendingDatagrams() { // On détermine quel client envoie le message (recherche du QTcpSocket du client) QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender()); if (socket == 0) // Si par hasard on n'a pas trouvé le client à l'origine du signal, on arrête la méthode return; unsigned nTries = 0; // Acquire data while(socket->state()==QAbstractSocket::ConnectedState && nTries<3) // Exit if disconnected, too much retries, malformed HTTP request, or after all requests are processed { // TODO: Give up after three tries reading the same message tcpReceivedDatas->append(socket->readAll()); nTries++; if (!tcpReceivedDatas->startsWith("POST") && !tcpReceivedDatas->startsWith("GET")) // Not HTTP, clear the buffer { logMessage("TCP: Received non-HTTP request"); tcpReceivedDatas->clear(); socket->close(); return; } else if (tcpReceivedDatas->contains("Content-Length:")) // POST or GET request, wait for Content-Length header { QByteArray contentLength = *tcpReceivedDatas; contentLength = contentLength.right(contentLength.size() - contentLength.indexOf("Content-Length:") - 15); QList<QByteArray> lengthList = contentLength.trimmed().split('\n'); if (lengthList.size()>1) // We want a number on this line and a next line to be sure we've got the full number { bool isNumeric; int length = lengthList[0].trimmed().toInt(&isNumeric); if (!isNumeric) // We've got something but it's not a number { logMessage("TCP: Content-Length must be a decimal number"); tcpReceivedDatas->clear(); socket->close(); return; } // Detect and send data files if we need to // TODO: Process and send all the requested data QByteArray data = *tcpReceivedDatas; int i1=0; do { i1 = data.indexOf("GET"); if (i1 != -1) { int i2 = data.indexOf("HTTP")-1; QString path = data.mid(i1 + 4, i2-i1-4); logMessage("Received GET:"+path); QFile head(QString(NETDATAPATH)+"/test.bin"); QFile res("gameFiles"+path); head.open(QIODevice::ReadOnly); res.open(QIODevice::ReadOnly); socket->write(head.readAll()); socket->write(QString("Content-Length: "+QString().setNum(res.size())+"\n\n").toLatin1()); socket->write(res.readAll()); head.close(); res.close(); logMessage("Sent ("+QString().setNum(res.size())+" bytes)"); data = removeHTTPHeader(data, "POST "); data = removeHTTPHeader(data, "GET "); } } while (i1 != -1); // Get the HTML data/payload data = removeHTTPHeader(data, "POST "); data = removeHTTPHeader(data, "GET "); data = removeHTTPHeader(data, "User-Agent:"); data = removeHTTPHeader(data, "Host:"); data = removeHTTPHeader(data, "Accept:"); data = removeHTTPHeader(data, "Content-Length:"); data = removeHTTPHeader(data, "Content-Type:"); data = removeHTTPHeader(data, "Server:"); data = removeHTTPHeader(data, "Date:"); data = removeHTTPHeader(data, "Transfert-Encoding:"); data = removeHTTPHeader(data, "Connection:"); data = removeHTTPHeader(data, "Vary:"); data = removeHTTPHeader(data, "X-Powered-By:"); data = removeHTTPHeader(data, "accept-encoding:"); data = removeHTTPHeader(data, "if-modified-since:"); if (data.size() >= length) // Wait until we have all the data { data.truncate(length); // Process data, if the buffer is not empty, keep reading tcpProcessData(data, socket); if (tcpReceivedDatas->isEmpty()) return; nTries=0; } } } } }
void Widget::tcpProcessPendingDatagrams() { // Find who's sending QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender()); if (socket == 0) return; unsigned nTries = 0; // Acquire data while(socket->state()==QAbstractSocket::ConnectedState && nTries<3) // Exit if disconnected, too much retries, malformed HTTP request, or after all requests are processed { tcpReceivedDatas->append(socket->readAll()); nTries++; if (!tcpReceivedDatas->startsWith("POST") && !tcpReceivedDatas->startsWith("GET")) // Not HTTP, clear the buffer { logMessage("TCP: Received non-HTTP request"); tcpReceivedDatas->clear(); socket->close(); return; } else if (tcpReceivedDatas->contains("Content-Length:")) // POST or GET request, wait for Content-Length header { QByteArray contentLength = *tcpReceivedDatas; contentLength = contentLength.right(contentLength.size() - contentLength.indexOf("Content-Length:") - 15); QList<QByteArray> lengthList = contentLength.trimmed().split('\n'); if (lengthList.size()>1) // We want a number on this line and a next line to be sure we've got the full number { bool isNumeric; int length = lengthList[0].trimmed().toInt(&isNumeric); if (!isNumeric) // We've got something but it's not a number { logMessage("TCP: Error: Content-Length must be a (decimal) number !"); tcpReceivedDatas->clear(); socket->close(); return; } // Detect and send data files if we need to QByteArray data = *tcpReceivedDatas; //logMessage("DataReceived:"+data); // Get the payload only (remove headers) data = removeHTTPHeader(data, "POST "); data = removeHTTPHeader(data, "GET "); data = removeHTTPHeader(data, "User-Agent:"); data = removeHTTPHeader(data, "Host:"); data = removeHTTPHeader(data, "host:"); data = removeHTTPHeader(data, "Accept:"); data = removeHTTPHeader(data, "Content-Length:"); data = removeHTTPHeader(data, "Content-Type:"); data = removeHTTPHeader(data, "Server:"); data = removeHTTPHeader(data, "Date:"); data = removeHTTPHeader(data, "Transfert-Encoding:"); data = removeHTTPHeader(data, "Connection:"); data = removeHTTPHeader(data, "Vary:"); data = removeHTTPHeader(data, "X-Powered-By:"); data = removeHTTPHeader(data, "accept-encoding:"); data = removeHTTPHeader(data, "if-modified-since:"); if (data.size() >= length) // Wait until we have all the data { data.truncate(length); // Process data, if the buffer is not empty, keep reading tcpProcessData(data, socket); // Delete the processed message from the buffer *tcpReceivedDatas = tcpReceivedDatas->right(tcpReceivedDatas->size() - tcpReceivedDatas->indexOf(data) - data.size()); if (tcpReceivedDatas->isEmpty()) return; nTries=0; } } } else if (tcpReceivedDatas->contains("\r\n\r\n")) // POST or GET request, without a Content-Length header { QByteArray data = *tcpReceivedDatas; data = data.left(data.indexOf("\r\n\r\n")+4); int i1=0; do { i1 = data.indexOf("GET"); if (i1 != -1) { int i2 = data.indexOf("HTTP")-1; QString path = data.mid(i1 + 4, i2-i1-4); data = removeHTTPHeader(data, "POST "); data = removeHTTPHeader(data, "GET "); logMessage("Received GET:"+path); QFile head(QString(NETDATAPATH)+"/dataHeader.bin"); QFile res("data/"+path); head.open(QIODevice::ReadOnly); if (!head.isOpen()) { logMessage("Can't open header : "+head.errorString()); continue; } res.open(QIODevice::ReadOnly); if (!res.isOpen()) { logMessage("File not found"); head.close(); continue; } socket->write(head.readAll()); socket->write(QString("Content-Length: "+QString().setNum(res.size())+"\r\n\r\n").toLocal8Bit()); socket->write(res.readAll()); head.close(); res.close(); logMessage("Sent "+QString().setNum(res.size()+head.size())+" bytes"); } } while (i1 != -1); *tcpReceivedDatas = tcpReceivedDatas->mid(data.size()); } } }
void Widget::tcpProcessPendingDatagrams() { // Find who's sending QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender()); if (socket == nullptr) return; QByteArray* recvBuffer=nullptr; for (auto pair : tcpClientsList) { if (pair.first == socket) { recvBuffer = pair.second; break; } } if (recvBuffer == nullptr) { logMessage("TCP: Error fetching the socket's associated recv buffer"); return; } unsigned nTries = 0; // Acquire data while(socket->state()==QAbstractSocket::ConnectedState && nTries<3) // Exit if disconnected, too much retries, malformed HTTP request, or after all requests are processed { recvBuffer->append(socket->readAll()); nTries++; if (!recvBuffer->size()) { #if DEBUG_LOG logMessage("TCP: Nothing to read"); #endif continue; } if (!recvBuffer->startsWith("POST") && !recvBuffer->startsWith("GET")) // Not HTTP, clear the buffer { #if DEBUG_LOG logMessage(QString("TCP: Received non-HTTP request : ")+*recvBuffer->toHex()); #endif recvBuffer->clear(); socket->close(); return; } else if (recvBuffer->contains("Content-Length:")) // POST or GET request, wait for Content-Length header { QByteArray contentLength = *recvBuffer; contentLength = contentLength.right(contentLength.size() - contentLength.indexOf("Content-Length:") - 15); QList<QByteArray> lengthList = contentLength.trimmed().split('\n'); if (lengthList.size()>1) // We want a number on this line and a next line to be sure we've got the full number { bool isNumeric; int length = lengthList[0].trimmed().toInt(&isNumeric); if (!isNumeric) // We've got something but it's not a number { logMessage("TCP: Error: Content-Length must be a (decimal) number !"); recvBuffer->clear(); socket->close(); return; } // Detect and send data files if we need to QByteArray data = *recvBuffer; #if DEBUG_LOG logMessage("TCP: Got content-length request:"+data); #endif // Get the payload only (remove headers) data = removeHTTPHeader(data, "POST "); data = removeHTTPHeader(data, "GET "); data = removeHTTPHeader(data, "User-Agent:"); data = removeHTTPHeader(data, "Host:"); data = removeHTTPHeader(data, "host:"); data = removeHTTPHeader(data, "Accept:"); data = removeHTTPHeader(data, "Content-Length:"); data = removeHTTPHeader(data, "Content-Type:"); data = removeHTTPHeader(data, "Server:"); data = removeHTTPHeader(data, "Date:"); data = removeHTTPHeader(data, "Transfert-Encoding:"); data = removeHTTPHeader(data, "Connection:"); data = removeHTTPHeader(data, "Vary:"); data = removeHTTPHeader(data, "X-Powered-By:"); data = removeHTTPHeader(data, "accept-encoding:"); data = removeHTTPHeader(data, "if-modified-since:"); if (data.size() >= length) // Wait until we have all the data { data.truncate(length); // Process data, if the buffer is not empty, keep reading tcpProcessData(data, socket); // Delete the processed message from the buffer *recvBuffer = recvBuffer->right(recvBuffer->size() - recvBuffer->indexOf(data) - data.size()); if (recvBuffer->isEmpty()) return; nTries=0; } } } else if (recvBuffer->contains("\r\n\r\n")) // POST or GET request, without a Content-Length header { QByteArray data = *recvBuffer; data = data.left(data.indexOf("\r\n\r\n")+4); int dataSize = data.size(); #if DEBUG_LOG logMessage("Got non-content length request:"+data); #endif int i1=0; do { i1 = data.indexOf("GET"); if (i1 != -1) { int i2 = data.indexOf("HTTP")-1; QString path = data.mid(i1 + 4, i2-i1-4); if (path == "/log") // GET /log { data = removeHTTPHeader(data, "POST "); data = removeHTTPHeader(data, "GET "); data = removeHTTPHeader(data, "if-modified-since:"); data = removeHTTPHeader(data, "accept-encoding:"); data = removeHTTPHeader(data, "host:"); if (!enableGetlog) continue; QFile head(QString(NETDATAPATH)+"/dataTextHeader.bin"); head.open(QIODevice::ReadOnly); if (!head.isOpen()) { logMessage("Can't open header : "+head.errorString()); continue; } QByteArray logData = ui->log->toPlainText().toLatin1(); socket->write(head.readAll()); socket->write(QString("Content-Length: "+QString().setNum(logData.size())+"\r\n\r\n").toLocal8Bit()); socket->write(logData); head.close(); logMessage("Sent log to "+socket->peerAddress().toString()); continue; } // Other GETs (not getlog) data = removeHTTPHeader(data, "POST "); data = removeHTTPHeader(data, "GET "); logMessage("TCP: Replying to HTTP GET "+path); QFile head(QString(NETDATAPATH)+"/dataHeader.bin"); QFile res("data/"+path); head.open(QIODevice::ReadOnly); if (!head.isOpen()) { logMessage("TCP: Can't open header : "+head.errorString()); continue; } res.open(QIODevice::ReadOnly); if (!res.isOpen()) { logMessage("TCP: File not found"); head.close(); QFile head404(QString(NETDATAPATH)+"/notmodified.bin"); head404.open(QIODevice::ReadOnly); if (!head404.isOpen()) { logMessage("TCP: Can't open 304 Not Modified header : "+head404.errorString()); continue; } socket->write(head404.readAll()); head404.close(); continue; } socket->write(head.readAll()); socket->write(QString("Content-Length: "+QString().setNum(res.size())+"\r\n\r\n").toLocal8Bit()); socket->write(res.readAll()); head.close(); res.close(); #if DEBUG_LOG logMessage("TCP: Sent "+QString().setNum(res.size()+head.size())+" bytes"); #endif } } while (i1 != -1); *recvBuffer = recvBuffer->mid(dataSize); } } }