Commit 3315517e authored by Soheil Armin's avatar Soheil Armin
Browse files

Initial commit

parents
cmake_minimum_required(VERSION 3.16)
project(UnixsocketPlayground2 VERSION 0.1 LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 6.2 COMPONENTS Quick REQUIRED)
qt_add_executable(appUnixsocketPlayground2
main.cpp
qunixsockettotcpserver.h qunixsockettotcpserver.cpp
qunixsockettotcpbridge.h qunixsockettotcpbridge.cpp
qhttprequest.h qhttprequest.cpp
)
qt_add_qml_module(appUnixsocketPlayground2
URI UnixsocketPlayground2
VERSION 1.0
QML_FILES main.qml
)
set_target_properties(appUnixsocketPlayground2 PROPERTIES
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
target_compile_definitions(appUnixsocketPlayground2
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
target_link_libraries(appUnixsocketPlayground2
PRIVATE Qt6::Quick)
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "qunixsockettotcpserver.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
auto server = new QUnixsocketToTcpServer("/var/run/docker.sock");
server->listen(QHostAddress::LocalHost,2323);
QQmlApplicationEngine engine;
const QUrl url(u"qrc:/UnixsocketPlayground2/main.qml"_qs);
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
import QtQuick
import HttpRequest
Window {
width: 640
height: 480
visible: true
title: qsTr("QtAA Docker build")
HttpRequest {
url: "http://localhost:2323/info"
running: true
onResponseBodyChanged: function(responseBody) {
console.log(responseBodys)
}
}
}
#include "qhttprequest.h"
#include <QTimer>
#include <QUrl>
#include <QUrlQuery>
QHttpRequest::QHttpRequest(QObject *parent)
: m_method(QStringLiteral("GET")),
m_networkError(QNetworkReply::NoError),
m_httpStatusCode(0),
m_running(false),
QObject{parent}
{
connect(this,&QHttpRequest::runningChanged,this,[=](bool running){
if(running)
QTimer::singleShot(0,this,&QHttpRequest::start);
});
}
void QHttpRequest::start()
{
QUrl url(m_url);
QUrlQuery urlQuery(url.query());
for (auto iter = m_parameters.constBegin(); iter != m_parameters.constEnd(); ++iter) {
if (iter.value().canConvert<QString>())
urlQuery.addQueryItem(iter.key(),iter.value().toString());
else
qWarning() << QStringLiteral("Cannot convert URL parameter '%1' to QString").arg(iter.key());
}
url.setQuery(urlQuery);
QNetworkRequest req(url);
for (auto iter = m_headers.constBegin(); iter != m_headers.constEnd(); ++iter)
req.setRawHeader(iter.key().toLatin1(),iter.value().toString().toLatin1());
auto reply = net.sendCustomRequest(req,
m_method.toLatin1(),
m_requestBody);
connect(reply,&QNetworkReply::finished,this,&QHttpRequest::processReply);
}
void QHttpRequest::processReply()
{
auto reply = qobject_cast<QNetworkReply *>(sender());
if (reply == nullptr)
return;
if (reply->error() == QNetworkReply::NoError)
createResponse(reply);
auto httpStatusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (m_httpStatusCode != httpStatusCode) {
m_httpStatusCode = httpStatusCode;
emit httpStatusCodeChanged(m_httpStatusCode);
}
if( m_networkError != reply->error()) {
m_networkError = reply->error();
emit networkErrorChanged(m_networkError);
}
if (reply->error() != QNetworkReply::NoError)
emit error();
emit finished();
}
QJSValue QHttpRequest::getResponseBody() const
{
return m_responseBody;
}
int QHttpRequest::getNetworkError() const
{
return m_networkError;
}
int QHttpRequest::getHttpStatusCode() const
{
return m_httpStatusCode;
}
void QHttpRequest::createResponse(QNetworkReply *reply)
{
auto mimeType = reply->header(QNetworkRequest::ContentTypeHeader).toString();
if (mimeType == QStringLiteral("application/json"))
setResponseFromJson(reply->readAll());
else
setResponseFromBytes(reply->readAll());
}
void QHttpRequest::setResponseFromJson(const QByteArray &response)
{
//TODO handling errors
auto jsEngine = qjsEngine(this);
if (jsEngine) {
auto payload = QString(response);
auto parse = jsEngine->evaluate("JSON.parse");
m_responseBody = parse.call({payload});
emit responseBodyChanged(m_responseBody);
} else {
//TODO error?
}
}
void QHttpRequest::setResponseFromBytes(const QByteArray &response)
{
//TODO handling errors
auto jsEngine = qjsEngine(this);
if (jsEngine) {
m_responseBody = jsEngine->toScriptValue<QByteArray>(response);
emit responseBodyChanged(m_responseBody);
} else {
//TODO error?
}
}
#ifndef QHTTPREQUEST_H
#define QHTTPREQUEST_H
#include <QObject>
#include <QQmlEngine>
#include <QJsonValue>
#include <QCoreApplication>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
class QHttpRequest : public QObject
{
Q_OBJECT
Q_PROPERTY(QString method MEMBER m_method NOTIFY methodChanged)
Q_PROPERTY(QString url MEMBER m_url NOTIFY urlChanged)
Q_PROPERTY(QVariantMap headers MEMBER m_headers NOTIFY headersChanged)
Q_PROPERTY(QVariantMap parameters MEMBER m_parameters NOTIFY parametersChanged)
Q_PROPERTY(QByteArray requestBody MEMBER m_requestBody NOTIFY requestBodyChanged)
Q_PROPERTY(QJSValue responseBody READ getResponseBody NOTIFY responseBodyChanged)
Q_PROPERTY(int networkError READ getNetworkError NOTIFY networkErrorChanged)
Q_PROPERTY(int httpStatusCode READ getHttpStatusCode NOTIFY httpStatusCodeChanged)
Q_PROPERTY(bool running MEMBER m_running NOTIFY runningChanged)
public:
explicit QHttpRequest(QObject *parent = nullptr);
public Q_SLOTS:
void start();
void processReply();
private:
QJSValue getResponseBody() const;
int getNetworkError() const;
int getHttpStatusCode() const;
void createResponse(QNetworkReply *reply);
void setResponseFromJson(const QByteArray &response);
void setResponseFromBytes(const QByteArray &response);
QNetworkAccessManager net;
QString m_method;
QString m_url;
QVariantMap m_headers;
QVariantMap m_parameters;
QByteArray m_requestBody;
QJSValue m_responseBody;
int m_networkError;
int m_httpStatusCode;
bool m_running;
signals:
void methodChanged(const QString &method);
void urlChanged(const QString &url);
void headersChanged(const QVariantMap &headers);
void parametersChanged(const QVariantMap &parameters);
void requestBodyChanged(const QByteArray &requestBody);
void responseBodyChanged(const QJSValue &responseBody);
void networkErrorChanged(int networkError);
void httpStatusCodeChanged(int httpStatusCode);
void runningChanged(bool running);
void finished();
void error();
};
static void registerQHttpRequest()
{
qmlRegisterType<QHttpRequest>("HttpRequest", 1, 0, "HttpRequest");
}
Q_COREAPP_STARTUP_FUNCTION(registerQHttpRequest)
#endif // QHTTPREQUEST_H
#include "qunixsockettotcpbridge.h"
QUnixsocketToTcpBridge::QUnixsocketToTcpBridge(QTcpSocket *tcpSocket,
const QString &unixSocketName,
QObject *parent)
: m_tcpSocket(tcpSocket),
QLocalSocket{parent}
{
connect(this,&QLocalSocket::connected,this,&QUnixsocketToTcpBridge::localSocketConnected);
connect(this,&QLocalSocket::disconnected,this,&QUnixsocketToTcpBridge::localSocketDisconnected);
connect(this,&QLocalSocket::readyRead,this,&QUnixsocketToTcpBridge::readLocalData);
connect(m_tcpSocket,&QTcpSocket::readyRead,this,&QUnixsocketToTcpBridge::readTcpData);
connect(m_tcpSocket,&QTcpSocket::disconnected,this,&QUnixsocketToTcpBridge::tcpDisconnected);
setServerName(unixSocketName);
open(QIODevice::ReadWrite);
}
void QUnixsocketToTcpBridge::localSocketConnected()
{
}
void QUnixsocketToTcpBridge::localSocketDisconnected()
{
m_tcpSocket->close();
}
void QUnixsocketToTcpBridge::readTcpData()
{
const auto b = m_tcpSocket->readAll();
qDebug() << b;
this->write(b);
}
void QUnixsocketToTcpBridge::readLocalData()
{
m_tcpSocket->write(this->readAll());
}
void QUnixsocketToTcpBridge::tcpDisconnected()
{
this->close();
this->deleteLater();
}
#ifndef QUNIXSOCKETTOTCPBRIDGE_H
#define QUNIXSOCKETTOTCPBRIDGE_H
#include <QObject>
#include <QLocalSocket>
#include <QTcpSocket>
class QUnixsocketToTcpBridge : public QLocalSocket
{
Q_OBJECT
public:
explicit QUnixsocketToTcpBridge(QTcpSocket *tcpSocket,
const QString &unixSocketName,
QObject *parent = nullptr);
private:
QTcpSocket *m_tcpSocket;
private slots:
void localSocketConnected();
void localSocketDisconnected();
void readTcpData();
void readLocalData();
void tcpDisconnected();
signals:
};
#endif // QUNIXSOCKETTOTCPBRIDGE_H
#include "qunixsockettotcpserver.h"
#include "qunixsockettotcpbridge.h"
QUnixsocketToTcpServer::QUnixsocketToTcpServer(const QString &serverName, QObject *parent):
m_serverName{serverName},
QTcpServer{parent}
{
connect(this,&QUnixsocketToTcpServer::newConnection,this,&QUnixsocketToTcpServer::acceptIncomingConnection);
}
void QUnixsocketToTcpServer::setUnixSocketServerName(const QString &serverName)
{
m_serverName = serverName;
}
void QUnixsocketToTcpServer::acceptIncomingConnection()
{
if (hasPendingConnections()) {
auto socket = nextPendingConnection();
if (socket)
new QUnixsocketToTcpBridge(socket, m_serverName, socket);
}
}
#ifndef QUNIXSOCKETTOTCPSERVER_H
#define QUNIXSOCKETTOTCPSERVER_H
#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
class QUnixsocketToTcpServer : public QTcpServer
{
Q_OBJECT
public:
explicit QUnixsocketToTcpServer(const QString &serverName, QObject *parent = nullptr);
void setUnixSocketServerName(const QString &serverName);
private:
QString m_serverName;
private Q_SLOTS:
void acceptIncomingConnection();
signals:
};
#endif // QUNIXSOCKETTOTCPSERVER_H
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment