void processQuery() { QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender()); QByteArray requestData = socket->readAll(); int pos = requestData.indexOf("\r\n"); QByteArray requestLine = requestData.left(pos); requestData.remove(0, pos + 2); QList<QByteArray> entries = requestLine.split(' '); QByteArray method = entries.value(0); QByteArray address = entries.value(1); QByteArray version = entries.value(2); QUrl url = QUrl::fromEncoded(address); if (!url.isValid()) { qWarning() << "Invalid URL:" << url; socket->disconnectFromHost(); return; } QString host = url.host(); int port = (url.port() < 0) ? 80 : url.port(); QByteArray req = url.encodedPath(); if (url.hasQuery()) req.append('?').append(url.encodedQuery()); requestLine = method + " " + req + " " + version + "\r\n"; requestData.prepend(requestLine); QString key = host + ':' + QString::number(port); QTcpSocket *proxySocket = socket->findChild<QTcpSocket*>(key); if (proxySocket) { proxySocket->setObjectName(key); proxySocket->setProperty("url", url); proxySocket->setProperty("requestData", requestData); proxySocket->write(requestData); } else { proxySocket = new QTcpSocket(socket); proxySocket->setObjectName(key); proxySocket->setProperty("url", url); proxySocket->setProperty("requestData", requestData); connect(proxySocket, SIGNAL(connected()), this, SLOT(sendRequest())); connect(proxySocket, SIGNAL(readyRead()), this, SLOT(transferData())); connect(proxySocket, SIGNAL(disconnected()), this, SLOT(closeConnection())); connect(proxySocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(closeConnection())); proxySocket->connectToHost(host, port); } }
/** * ブラウザとのソケットと本来のホストとのソケットを接続するトンネルを作成 */ void YASWebProxy::openTunnel() { QTcpSocket* socket = qobject_cast<QTcpSocket*>(sender()); QByteArray data = socket->readAll(); HttpParser* parser = socket->findChild<HttpParser*>("requestParser"); parser->input(data); QTcpSocket* proxySocket = socket->findChild<QTcpSocket*>("tunnel"); if (!proxySocket) { // 本来のホストへのソケットを作成 proxySocket = new QTcpSocket(socket); proxySocket->setObjectName("tunnel"); proxySocket->connectToHost(parser->url.host(), parser->url.port(80)); connect(proxySocket, SIGNAL(disconnected()), this, SLOT(closeProxySocket())); connect(proxySocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(closeProxySocket())); connect(proxySocket, SIGNAL(readyRead()), this, SLOT(forwardResponse())); if (parser->method == "CONNECT") { disconnect(socket, SIGNAL(readyRead()), this, SLOT(openTunnel())); connect(socket, SIGNAL(readyRead()), this, SLOT(forwardRequest())); } else { HttpParser* resParser = new HttpParser(HttpParser::RESPONSE, proxySocket); resParser->setObjectName("responseParser"); resParser->setProperty("url", parser->url.toString()); connect(resParser, SIGNAL(completeMessage(QByteArray)), this, SLOT(onResponse(QByteArray))); } } if (proxySocket->waitForConnected()) { if (parser->method == "CONNECT") { socket->write("HTTP/1.0 200 Connection established\r\n\r\n"); } else { proxySocket->write(parser->dequeueData()); } } else { proxySocket->disconnect(); } }
void HttpProxy::onSocketReadyRead() { QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender()); QTcpSocket *proxySocket = nullptr; QByteArray reqData = socket->readAll(); int pos = reqData.indexOf("\r\n"); QByteArray reqLine = reqData.left(pos); reqData.remove(0, pos + 2); QList<QByteArray> entries = reqLine.split(' '); QByteArray method = entries.value(0); QByteArray address = entries.value(1); QByteArray version = entries.value(2); QString host; quint16 port; QString key; if (method != "CONNECT") { QUrl url = QUrl::fromEncoded(address); if (!url.isValid()) { emit info("Invalid URL: " + url.toString()); socket->disconnectFromHost(); return; } host = url.host(); port = url.port(80); QString req = url.path(); if (url.hasQuery()) { req.append('?').append(url.query()); } reqLine = method + " " + req.toUtf8() + " " + version + "\r\n"; reqData.prepend(reqLine); key = host + ':' + QString::number(port); proxySocket = socket->findChild<QTcpSocket *>(key); if (proxySocket) { proxySocket->write(reqData); return;//if we find an existing socket, then use it and return } } else {//CONNECT method /* * according to http://tools.ietf.org/html/draft-luotonen-ssl-tunneling-03 * the first line would CONNECT HOST:PORT VERSION */ QList<QByteArray> host_port_list = address.split(':'); host = QString(host_port_list.first()); port = host_port_list.last().toUShort(); } proxySocket = new QTcpSocket(socket); proxySocket->setProxy(upstreamProxy); if (method != "CONNECT") { proxySocket->setObjectName(key); proxySocket->setProperty("reqData", reqData); connect (proxySocket, &QTcpSocket::connected, this, &HttpProxy::onProxySocketConnected); connect (proxySocket, &QTcpSocket::readyRead, this, &HttpProxy::onProxySocketReadyRead); } else { connect (proxySocket, &QTcpSocket::connected, this, &HttpProxy::onProxySocketConnectedHttps); } connect (proxySocket, &QTcpSocket::disconnected, proxySocket, &QTcpSocket::deleteLater); connect (proxySocket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QTcpSocket::error), this, &HttpProxy::onSocketError); proxySocket->connectToHost(host, port); }
/*------------------------------------------------------------------------------* *------------------------------------------------------------------------------*/ void WebProxy::processQuery() { QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender()); QByteArray requestData = socket->readAll(); int pos = requestData.indexOf("\r\n"); QByteArray requestLine = requestData.left(pos); requestData.remove(0, pos + 2); QList<QByteArray> entries = requestLine.split(' '); QByteArray method = entries.value(0); QByteArray address = entries.value(1); QByteArray version = entries.value(2); qDebug( ) << __FILE__ << __FUNCTION__ << "Processing " << address; QUrl url = QUrl::fromEncoded(address); if (!url.isValid()) { //qWarning() << "Invalid URL:" << url; socket->disconnectFromHost(); return; } //Act as server is request are for local server if ((url.host() == "") && (QFile(address).exists())) { //qDebug( ) << __FILE__ << __FUNCTION__ << "Sending " << address; QByteArray header; QTextStream headerStream(&header, QIODevice::WriteOnly); //Construct response header headerStream << "HTTP/1.0 200 OK" << endl; headerStream << "Server: gpsbook/" << qApp->applicationVersion() << endl; headerStream << "Date: " << QDateTime::currentDateTime().toUTC().toString("ddd, dd MMM yyyy hh:mm:ss") << "GMT" << endl; headerStream << "Content-Type: text/html; charset=utf-8" << endl; headerStream << "Connection: close" << endl; headerStream << "Pragma: no-cache" << endl; headerStream << "Cache-Control: no-cache" << endl; QFile file(address); if (!file.open(QFile::ReadOnly | QFile::Text)) { qWarning() << "Cannot open:" << address; socket->disconnectFromHost(); return ; } QByteArray content; QTextStream contentStream(&content, QIODevice::WriteOnly); while (!file.atEnd()) { contentStream << file.readLine() << endl; } headerStream << "Content-Length:" << content.size() << endl; headerStream << "" << endl; socket->write(header); socket->write(content); //qDebug( ) << __FILE__ << __FUNCTION__ << "File sent (" << content.size() << "bytes) :-)"; socket->disconnectFromHost(); return; } #if ( QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) ) // Some finction of QUrl have been deprecated // This code is require for the internet browser and should be reviewed. #else #ifdef Q_OS_LINUX //Remove advert to speedup development ;-) if (url.toString().contains("googlesyndication") || url.toString().contains("yieldmanager.com")) { socket->disconnectFromHost(); return; } #endif qDebug( ) << __FILE__ << __FUNCTION__ << "URL: " << url.toString(); QString host = url.host(); int port = (url.port() < 0) ? 80 : url.port(); QByteArray req = url.encodedPath(); if (url.hasQuery()) req.append('?').append(url.encodedQuery()); requestLine = method + " " + req + " " + version + "\r\n"; requestData.prepend(requestLine); QString key = host + ':' + QString::number(port); QTcpSocket *proxySocket = socket->findChild<QTcpSocket*>(key); if (proxySocket) { proxySocket->setObjectName(key); proxySocket->setProperty("url", url); proxySocket->setProperty("requestData", requestData); proxySocket->write(requestData); } else { proxySocket = new QTcpSocket(socket); proxySocket->setObjectName(key); proxySocket->setProperty("url", url); proxySocket->setProperty("requestData", requestData); connect(proxySocket, SIGNAL(connected()), this, SLOT(sendRequest())); connect(proxySocket, SIGNAL(readyRead()), this, SLOT(transferData())); connect(proxySocket, SIGNAL(disconnected()), this, SLOT(closeConnection())); connect(proxySocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(closeConnection())); proxySocket->connectToHost(host, port); } #endif } //WebProxy::processQuery