mirror of
https://github.com/YACReader/yacreader
synced 2025-05-28 03:10:27 -04:00
171 lines
5.6 KiB
C++
171 lines
5.6 KiB
C++
/**
|
||
@file
|
||
@author Stefan Frings
|
||
*/
|
||
|
||
#include "httpconnectionhandler.h"
|
||
#include "httpresponse.h"
|
||
#include <QTimer>
|
||
#include <QCoreApplication>
|
||
|
||
HttpConnectionHandler::HttpConnectionHandler(QSettings* settings, HttpRequestHandler* requestHandler)
|
||
: QThread()
|
||
{
|
||
Q_ASSERT(settings!=0);
|
||
Q_ASSERT(requestHandler!=0);
|
||
this->settings=settings;
|
||
this->requestHandler=requestHandler;
|
||
currentRequest=0;
|
||
busy = false;
|
||
// execute signals in my own thread
|
||
moveToThread(this);
|
||
socket.moveToThread(this);
|
||
readTimer.moveToThread(this);
|
||
connect(&socket, SIGNAL(readyRead()), SLOT(read()));
|
||
connect(&socket, SIGNAL(disconnected()), SLOT(disconnected()));
|
||
connect(&readTimer, SIGNAL(timeout()), SLOT(readTimeout()));
|
||
readTimer.setSingleShot(true);
|
||
qDebug("HttpConnectionHandler (%p): constructed", this);
|
||
this->start();
|
||
}
|
||
|
||
|
||
HttpConnectionHandler::~HttpConnectionHandler() {
|
||
socket.close();
|
||
quit();
|
||
wait();
|
||
qDebug("HttpConnectionHandler (%p): destroyed", this);
|
||
}
|
||
|
||
|
||
void HttpConnectionHandler::run() {
|
||
qDebug("HttpConnectionHandler (%p): thread started", this);
|
||
try {
|
||
exec();
|
||
}
|
||
catch (...) {
|
||
qCritical("HttpConnectionHandler (%p): an uncatched exception occured in the thread",this);
|
||
}
|
||
qDebug("HttpConnectionHandler (%p): thread stopped", this);
|
||
// Change to the main thread, otherwise deleteLater() would not work
|
||
moveToThread(QCoreApplication::instance()->thread());
|
||
}
|
||
|
||
|
||
void HttpConnectionHandler::handleConnection(tSocketDescriptor socketDescriptor) {
|
||
qDebug("HttpConnectionHandler (%p): handle new connection", this);
|
||
busy = true;
|
||
Q_ASSERT(socket.isOpen()==false); // if not, then the handler is already busy
|
||
|
||
if (!socket.setSocketDescriptor(socketDescriptor)) {
|
||
qCritical("HttpConnectionHandler (%p): cannot initialize socket: %s", this,qPrintable(socket.errorString()));
|
||
return;
|
||
}
|
||
// Start timer for read timeout
|
||
int readTimeout=settings->value("readTimeout",10000).toInt();
|
||
readTimer.start(readTimeout);
|
||
// delete previous request
|
||
delete currentRequest;
|
||
currentRequest=0;
|
||
}
|
||
|
||
|
||
bool HttpConnectionHandler::isBusy() {
|
||
return busy;
|
||
}
|
||
|
||
void HttpConnectionHandler::setBusy() {
|
||
this->busy = true;
|
||
}
|
||
|
||
|
||
void HttpConnectionHandler::readTimeout() {
|
||
qDebug("HttpConnectionHandler (%p): read timeout occured",this);
|
||
|
||
//Commented out because QWebView cannot handle this.
|
||
//socket.write("HTTP/1.1 408 request timeout\r\nConnection: close\r\n\r\n408 request timeout\r\n");
|
||
|
||
socket.disconnectFromHost();
|
||
delete currentRequest;
|
||
currentRequest=0;
|
||
}
|
||
|
||
|
||
void HttpConnectionHandler::disconnected() {
|
||
qDebug("HttpConnectionHandler (%p): disconnected", this);
|
||
socket.close();
|
||
readTimer.stop();
|
||
busy = false;
|
||
}
|
||
|
||
void HttpConnectionHandler::read() {
|
||
while (socket.bytesAvailable()) {
|
||
#ifdef SUPERVERBOSE
|
||
qDebug("HttpConnectionHandler (%p): read input",this);
|
||
#endif
|
||
|
||
// Create new HttpRequest object if necessary
|
||
if (!currentRequest) {
|
||
currentRequest=new HttpRequest(settings);
|
||
}
|
||
|
||
// Collect data for the request object
|
||
while (socket.bytesAvailable() && currentRequest->getStatus()!=HttpRequest::complete && currentRequest->getStatus()!=HttpRequest::abort) {
|
||
currentRequest->readFromSocket(socket);
|
||
if (currentRequest->getStatus()==HttpRequest::waitForBody) {
|
||
// Restart timer for read timeout, otherwise it would
|
||
// expire during large file uploads.
|
||
int readTimeout=settings->value("readTimeout",10000).toInt();
|
||
readTimer.start(readTimeout);
|
||
}
|
||
}
|
||
|
||
// If the request is aborted, return error message and close the connection
|
||
if (currentRequest->getStatus()==HttpRequest::abort) {
|
||
socket.write("HTTP/1.1 413 entity too large\r\nConnection: close\r\n\r\n413 Entity too large\r\n");
|
||
socket.disconnectFromHost();
|
||
delete currentRequest;
|
||
currentRequest=0;
|
||
return;
|
||
}
|
||
|
||
// If the request is complete, let the request mapper dispatch it
|
||
if (currentRequest->getStatus()==HttpRequest::complete) {
|
||
readTimer.stop();
|
||
qDebug("HttpConnectionHandler (%p): received request",this);
|
||
HttpResponse response(&socket);
|
||
//response.setHeader("Connection","close"); No funciona bien con NSURLConnection
|
||
try {
|
||
requestHandler->service(*currentRequest, response);
|
||
}
|
||
catch (...) {
|
||
qCritical("HttpConnectionHandler (%p): An uncatched exception occured in the request handler",this);
|
||
}
|
||
|
||
// Finalize sending the response if not already done
|
||
if (!response.hasSentLastPart()) {
|
||
response.write(QByteArray(),true);
|
||
}
|
||
|
||
//socket.disconnectFromHost(); //CAMBIADO s<>lo se van a soportar conexiones NO persistentes
|
||
|
||
// Close the connection after delivering the response, if requested
|
||
if (QString::compare(currentRequest->getHeader("Connection"),"close",Qt::CaseInsensitive)==0) {
|
||
socket.disconnectFromHost();
|
||
}
|
||
else {
|
||
// Start timer for next request
|
||
int readTimeout=settings->value("readTimeout",10000).toInt();
|
||
readTimer.start(readTimeout);
|
||
}
|
||
// Prepare for next request
|
||
delete currentRequest;
|
||
currentRequest=0;
|
||
}
|
||
else
|
||
{
|
||
qDebug("HttpConnectionHandler (%p): received request",this);
|
||
}
|
||
}
|
||
}
|