i have made changes to the code - c++

this is my method and it does not work.
void ApplicationUI::Post(const QString &id,const QString &name,const QString &surname,const QString &grade, const QString &dob,const QString &language,const QString &school, const QString &gender,const QString &cellno,const QString &registrationDate)
{
this->connection = new QNetworkAccessManager(this);
connect(this->connection, SIGNAL(finished(QNetworkReply*)), this, SLOT(postFinished()));
QUrl url("http://172.27.15.7/BB10_Scripts/Registration.php");
QUrl postParams;
postParams.addQueryItem("id",id);
postParams.addQueryItem("name", name);
postParams.addQueryItem("surname",surname);
postParams.addQueryItem("grade",grade);
postParams.addQueryItem("dob",dob);
postParams.addQueryItem("language",language);
postParams.addQueryItem("school",school);
postParams.addQueryItem("gender",gender);
postParams.addQueryItem("cellno",cellno);
postParams.addQueryItem("registrationDate",registrationDate);
QByteArray data;
data.append(postParams.data);
data.remove(0,1);
QNetworkRequest req;
req.setUrl(url);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
this->connection->post(req,postParams.encodedQuery());());
bool ok = QObject::connect(connection, SIGNAL(finished(QNetworkReply*)), this, SLOT(postFinished()));
Q_ASSERT(ok);
Q_UNUSED(ok);
qDebug() << "Connection is success : ? : " << ok;
}
i get the message
Connection is success : ? : true
Process 476930267 (CascadesProject) terminated SIGSEGV code=1 fltno=11 >ip=79f70ce2 >(/base/usr/lib/qt4/lib/libQtNetwork.so.4.8.5#_ZNK13QNetworkReply5errorEv+0x9) >mapaddr=00060ce2. ref=00000004 bdslot=1

postParams.addQueryItem("id", id);
postParams.addQueryItem("name", name);
postParams.addQueryItem("surname", surname);
postParams.addQueryItem("grade", grade);
postParams.addQueryItem("dob", dob);
postParams.addQueryItem("language", language);
postParams.addQueryItem("school", school);
postParams.addQueryItem("gender", gender);
postParams.addQueryItem("cellno", cellno);
postParams.addQueryItem("registrationDate",registrationDate);
QNetworkRequest request;
request.setUrl(QUrl("http://172.27.15.7/BB10_Scripts/Registration.php?"));
bool res;
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
Q_UNUSED(res);
this->reply = connection->post(request, postParams.encodedQuery());
res = QObject::connect(this->reply, SIGNAL(finished()),this, SLOT(postFinished()));
Q_ASSERT(res);
Q_UNUSED(res);
qDebug() << "Connection is success : ? : " << res;

Related

How can I get qjsonvalue to string?

What should i do to get output for example: Bid value is 2248.48?
Here is code:
QNetworkRequest request = QNetworkRequest(QUrl("https://api.30.bossa.pl/API/GPW/v2/Q/C/_cat_name/WIG20?_t=1637005413888"));
QNetworkReply* reply = m_manager.get(request);
QObject::connect(reply, &QNetworkReply::finished, [reply]() {
QByteArray rawData = reply->readAll();
QString textData(rawData);
// qDebug() << textData;
QJsonDocument doc = QJsonDocument::fromJson(textData.toUtf8());
auto rootObj = doc.object();
auto _d = rootObj.value("_d").toArray();
auto _t = _d[0].toObject().value("_t").toArray();
auto _quote = _t[0].toObject().value(QString("_quote"));
qDebug() << _quote;
eply->deleteLater();
Now i get QJsonValue (string, "2248.48)
when i tried this:
QJsonObject root = _t[0].toObject().value(QString("_quote"));
qDebug() << root;
QJsonValue value = obj.value(QString("_quote"));
qDebug() << "Bid value is" << value.toString();;
https://api.30.bossa.pl/API/GPW/v2/Q/C/_cat_name/WIG20?_t=1637005413888
{"message":"OK","_quote_date":null,"_type":"C","_symbol":["WIG20"],"_d":[{"_h":"Własne - 22 listopada 2021 16:42","_hs":"Własne","_max_quote_dtm":"22 listopada 2021","_max_quote_dtm_lc":"22 listopada, 16:42","_ret_quote_dtm":"2021-11-22","_t":[{"_symbol":"WIG20","_symbol_short":"WIG20","_group":"X1","_isin":"PL9999999987","_quote_date":"2021.11.22","_quote_time":"16:42","_time":"16:42","_phase":"Sesja","_quote_max":"2262.74","_quote_min":"2237.64","_quote_open":"2251.08","_quote_ref":"2248.18","_quote_imp":"2254.37","_bid_size":null,"_bid_volume":null,"_bid_orders_nr":null,"_ask_size":null,"_ask_volume":null,"_ask_orders_nr":null,"_volume":null,"_open_positions":null,"_quote_volume":null,"_transactions_nr":null,"_turnover_value":841977698,"_quote":"2254.10","_step":"2","_type_of_instrument":"0","_settlement_price":null,"_change_proc":0.26,"_change_pnts":5.9200,"_30d_change_max":2449.6400,"_30d_change_min":2221.6800,"_change_type":"_change_proc","_quote_type":"_quote","_debut":"0","_live":"1","_sw_symbol_short":0,"_is_indice":"1","_change":"+0.26","_change_suffix":"%","_change_max_min":"+1.12","_change_close_open":"+0.13","_change_settl_ref":null}]}],"_i":[null],"_count":1,"_d_fx":{"_h":null,"_hs":null,"_max_quote_dtm":null,"_max_quote_dtm_lc":null,"_t":[]}}
I got erros "QJsonValue to non-scalar type QJsonObject requested"
You either want _quote.toString() (first listing) or root.toString() (second listing)

Passing QString as parameter to a QFuture

I need to pass a filename as QString with path to a function covered in a QFuture and watched by a QFutureWatcher, but only the first character of this QString will be passed to this function. Here the declaration in the *.h file:
qint64 processDataFile(const QString &fileName);
...
QFutureWatcher<qint64> *watcher;
And here the call of the function:
watcher = new QFutureWatcher<qint64>;
connect(watcher, &QFutureWatcher<qint64>::finished, this, &SmartDCPD::fileProcessingFinished);
qDebug() << log.fileName; // something like C:/users/.....
watcher->setFuture(QtConcurrent::mapped(log.fileName, std::bind(&SmartDCPD::processDataFile, this, std::placeholders::_1)));
And the code of the function:
qint64 SmartDCPD::processDataFile(const QString &fileName)
{
qDebug() << fileName; //Only C (just the first char of the whole QString)
QElapsedTimer t;
t.start();
rapidcsv::Document doc(fileName.toUtf8().constData(), rapidcsv::LabelParams(-1, -1), rapidcsv::SeparatorParams(';'));
QString stamp = QDateTime::currentDateTime().toString("dd.MM.yyyy hh:mm:ss.zzz");
doc.SetCell<std::string>(1, 2, stamp.toUtf8().constData());
doc.Save();
return t.nsecsElapsed() / 1000000;
}
What am I doing wrong?

AWS execute API request using QT 5

i am trying to create an API request to an AWS API, right now i fix the first issue that is related to generate de signature version 4, but no matter what i do, AWS response tell me that the signature is not welll generated, i already check the signature using nodejs code and works, according what i see and what AWS SUpport say, it is possible that some request headers are missing.
I am adding my QT Code i know that is not the best but is only an example, the function that i using to make the post request is loginWekall
#include "hash.h"
#include <QDateTime>
#include <QJsonObject>
#include <QJsonDocument>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QBuffer>
#include <QNetworkReply>
CryptoHash::CryptoHash(QObject *parent) : QObject(parent)
{
}
QString CryptoHash::getKey(){
return this->key;
}
void CryptoHash::setKey(QString key){
this->key = key;
}
void CryptoHash::setSecret(QString secret){
this->secret = secret;
}
void CryptoHash::setRegion(QString region){
this->region = region;
}
void CryptoHash::setMethod(QString method){
this->method = method;
}
void CryptoHash::setEndpoint(QString endpoint){
this->endpoint = endpoint;
}
void CryptoHash::setHost(QString host){
this->host = host;
}
void CryptoHash::setURL(QString URL){
this->url = URL;
}
QString CryptoHash::getHash() {
return this->hashvalue;
}
const QByteArray CryptoHash::getSignatureKey(QString datestamp) {
QMessageAuthenticationCode code(QCryptographicHash::Sha256);
code.setKey(datestamp.toUtf8());
code.addData("AWS4" + this->key.toUtf8());
QByteArray kDate = code.result();
code.reset();
code.setKey(this->region.toUtf8());
code.addData(kDate);
QByteArray kRegion = code.result();
code.reset();
code.setKey(this->service.toUtf8());
code.addData(kRegion);
QByteArray kService = code.result();
code.reset();
code.setKey("aws4_request");
code.addData(kService);
const QByteArray kSignin = code.result();
return kSignin;
}
QByteArray CryptoHash::algorithmDesignation(const QCryptographicHash::Algorithm algorithm) {
switch (algorithm) {
case QCryptographicHash::Md4: return "AWS4-HMAC-MD4";
case QCryptographicHash::Md5: return "AWS4-HMAC-MD5";
case QCryptographicHash::Sha1: return "AWS4-HMAC-SHA1";
case QCryptographicHash::Sha224: return "AWS4-HMAC-SHA224";
case QCryptographicHash::Sha256: return "AWS4-HMAC-SHA256";
case QCryptographicHash::Sha384: return "AWS4-HMAC-SHA384";
case QCryptographicHash::Sha512: return "AWS4-HMAC-SHA512";
default:
Q_ASSERT_X(false, Q_FUNC_INFO, "invalid algorithm");
return "invalid-algorithm";
}
}
QByteArray CryptoHash::canonicalHeader(const QByteArray &headerName, const QByteArray &headerValue) {
QByteArray header = headerName.toLower() + ':';
const QByteArray trimmedHeaderValue = headerValue.trimmed();
bool isInQuotes = false;
char previousChar = '\0';
for (int index = 0; index < trimmedHeaderValue.size(); ++index) {
char thisChar = trimmedHeaderValue.at(index);
header += thisChar;
if (isInQuotes) {
if ((thisChar == '"') && (previousChar != '\\'))
isInQuotes = false;
} else {
if ((thisChar == '"') && (previousChar != '\\')) {
isInQuotes = true;
} else if (isspace(thisChar)) {
while ((index < trimmedHeaderValue.size()-1) &&
(isspace(trimmedHeaderValue.at(index+1))))
++index;
}
}
previousChar = thisChar;
}
return header;
}
QByteArray CryptoHash::canonicalHeaders(const QNetworkRequest &request, QByteArray * const signedHeaders) {
Q_CHECK_PTR(signedHeaders);
signedHeaders->clear();
QMap<QByteArray,QByteArray> headers;
foreach (const QByteArray &rawHeader, request.rawHeaderList()) {
headers.insert(rawHeader.toLower(), request.rawHeader(rawHeader));
}
headers.insert("host", request.url().host().toUtf8());
headers.insert("x-amz-date", this->amz.toUtf8());
QByteArray canonicalHeaders;
for (QMap<QByteArray,QByteArray>::const_iterator iter = headers.constBegin(); iter != headers.constEnd(); ++iter) {
canonicalHeaders += canonicalHeader(iter.key(), iter.value()) + '\n';
if (!signedHeaders->isEmpty()) *signedHeaders += ';';
*signedHeaders += iter.key();
}
return canonicalHeaders;
}
QByteArray CryptoHash::canonicalRequest(const QNetworkAccessManager::Operation operation,
const QNetworkRequest &request,
const QByteArray &payload,
QByteArray * const signedHeaders) {
//qInfo() <<"payload";
//qInfo() << payload;
//qInfo() << QCryptographicHash::hash(payload, QCryptographicHash::Sha256).toHex();
return this->method.toUtf8() + '\n' +
this->endpoint.toUtf8() + '\n' +
"\n" + canonicalHeaders(request, signedHeaders) + '\n' +
*signedHeaders + '\n' +
QCryptographicHash::hash(payload, QCryptographicHash::Sha256).toHex();
}
QByteArray CryptoHash::credentialScope(const QDateTime &date, const QString &region, const QString &service) {
return this->dstamp.toUtf8() + '/' + region.toUtf8() + '/' + service.toUtf8() + "/aws4_request";
}
QByteArray CryptoHash::stringToSign(const QByteArray &algorithmDesignation, const QString &requestDate,
const QByteArray &credentialScope, const QByteArray &canonicalRequest) {
return algorithmDesignation + '\n' +
this->amz.toUtf8() + '\n' +
credentialScope + '\n' +
QCryptographicHash::hash(canonicalRequest, QCryptographicHash::Sha256).toHex();
}
QByteArray CryptoHash::signingKey( const QDate &date,
const QString &region, const QString &service) {
const QCryptographicHash::Algorithm hashAlgorithm = QCryptographicHash::Sha256;
return QMessageAuthenticationCode::hash("aws4_request",
QMessageAuthenticationCode::hash(service.toUtf8(),
QMessageAuthenticationCode::hash(region.toUtf8(),
QMessageAuthenticationCode::hash(this->dstamp.toUtf8(), "AWS4"+this->secret.toUtf8(),
hashAlgorithm), hashAlgorithm), hashAlgorithm), hashAlgorithm);
}
void debugRequest(QNetworkRequest request, QByteArray data = QByteArray())
{
qDebug() << request.url().toString();
const QList<QByteArray>& rawHeaderList(request.rawHeaderList());
foreach (QByteArray rawHeader, rawHeaderList) {
qDebug() << request.rawHeader(rawHeader);
}
qDebug() << data;
}
QString CryptoHash::loginWekall(const QString AWSV4, const QString timestamp){
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QUrl url("https://asdasdasd.execute-api.us-east-1.amazonaws.com/master/users/login");
QNetworkRequest request(url);
QJsonObject obj;
obj["email"] = "user#test.co";
obj["password"] = "password";
QJsonDocument doc(obj);
QByteArray data = doc.toJson();
// FIXME for debug
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("Content-Type", "application/json");
request.setRawHeader("Authorization", AWSV4.toUtf8());
request.setRawHeader("X-Amz-Date", this->amz.toUtf8());
request.setRawHeader("Host","g298zqijvh.execute-api.us-east-1.amazonaws.com");
request.setRawHeader("Accept","application/json, text/plain, */*");
qDebug() << request.url().toString();
const QList<QByteArray>& rawHeaderList(request.rawHeaderList());
foreach (QByteArray rawHeader, rawHeaderList) {
qDebug() << request.rawHeader(rawHeader);
}
qDebug() << data;
QNetworkReply *reply = manager->post(request, data);
QObject::connect(reply, &QNetworkReply::finished, [=](){
if(reply->error() == QNetworkReply::NoError){
QString contents = QString::fromUtf8(reply->readAll());
qDebug() << contents;
}
else{
qInfo()<< QString::fromUtf8(reply->readAll());
QString err = reply->errorString();
qDebug() << err;
}
reply->deleteLater();
});
return "true";
}
QString CryptoHash::getDate(){
return this->amz;
}
QString CryptoHash::hash(){
const QDateTime datetime;
QDateTime* dtime = new QDateTime();
QString amzdate = dtime->currentDateTimeUtc().toString("yyyyMMddThhmmssZ").toUtf8();
QString datestamp = dtime->currentDateTimeUtc().toString("yyyyMMdd").toUtf8();
QJsonObject data;
this->amz = amzdate;
//this->amz = "20210306T142037Z";
this->dstamp = datestamp;
qInfo() <<"amztime";
qInfo() << amzdate;
qInfo() <<"date";
qInfo() << datestamp;
data["email"] = "user#test.co";
data["password"] = "password";
QJsonDocument doc(data);
QByteArray strData(doc.toJson(QJsonDocument::Compact));
qInfo() << "JSON parameters";
qInfo() << strData;
const QByteArray algorithmDesignation = this->algorithmDesignation(QCryptographicHash::Sha256);
const QString endpoint = this->endpoint;
QString signa = "host;x-amz-date";;
const QByteArray credentialScope = this->credentialScope(datetime, this->region, this->service);
QString access = "ACCESSKEYID/";
this->scope = access.toUtf8() + this->dstamp+ "/us-east-1/execute-api/aws4_request";
qInfo() << "credentialScope";
qInfo() << credentialScope;
QByteArray signedHeaders = signa.toUtf8();
qInfo() << "signedHeaders";
qInfo() << signedHeaders;
const QUrl URL("https://asdasd.execute-api.us-east-1.amazonaws.com/master/users/login");
const QNetworkRequest request(URL);
const QByteArray canonicalRequest = this->canonicalRequest(QNetworkAccessManager::Operation::PostOperation, request, strData, &signedHeaders);
qInfo() << "canonical request";
qInfo() << canonicalRequest;
const QByteArray stringToSign = this->stringToSign(algorithmDesignation, this->amz, credentialScope, canonicalRequest);
qInfo() << "stringToSign";
qInfo() << stringToSign;
const QByteArray signingKey = this->signingKey(datetime.date(), this->region, this->service);
qInfo() << "signinKey";
qInfo() << signingKey;
const QByteArray signature = QMessageAuthenticationCode::hash(stringToSign, signingKey, QCryptographicHash::Sha256);
qInfo() << "signature";
qInfo() << signature;
this->hashvalue = algorithmDesignation + " Credential=" + this->key.toUtf8() + '/' + credentialScope +
", SignedHeaders=" + signedHeaders + ", Signature=" + signature.toHex();
qInfo() << "AWS SIGNATURE VERSION 4";
qInfo() << this->hashvalue;
this->loginWekall(hashvalue, this->amz);
return 0;
}
CryptoHash::~CryptoHash(){};

Can not send udp packet in QT

all
I want to use QUdpSocket to send udp packet to get config parameter from specific server,but It failed and I can not capture the sending packet using wireshark.here is my code:
CGetConfig.cpp:
CGetConfig::CGetConfig(const QString &conf_server,const uint16_t port)
:m_conf_server(conf_server)
,m_port(port)
{
m_socket = NULL;
}
CGetConfig::~CGetConfig()
{}
void CGetConfig::init()
{
// create a QUDP socket
m_socket = new QUdpSocket(this);
m_socket->bind(QHostAddress::LocalHost, 12345);
connect(m_socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
m_ip_addr = get_ip_address(m_conf_server);
}
bool CGetConfig::get_reflector(const QString &mac)
{
qDebug() << "CGetConfig::get_reflector():Entry\n";
if(m_ip_addr.isEmpty())
{
qDebug() << "CGetConfig::get_reflector():ip address of cofnig server could not be resolved\n";
return 0;
}
QString msg("id=1&mac=");
msg+= mac;
msg+= "&get_config=fw_type=v.1,cfg_ver=4,set_ver=0,ip=192.168.1.101";
qDebug() << m_ip_addr;
qDebug() << m_port;
qDebug() << msg.toLatin1();
int count = 0;
while(count < 3)
{
int t = m_socket->writeDatagram(msg.toLatin1(), QHostAddress(m_ip_addr), m_port);
count++;
}
}
Main.cpp
CGetConfig cfg(cfg_server,cfg_port);
cfg.init();
local_mac = "00d033120001";
cfg.get_reflector(local_mac);
Can anyone help me figure out the problem?

Qt, Sending multiple data types from client to server + data Streaming

I have a Client/Server based Qt application, using QTcpServer and QTcpSocket, I managed to do the connection and send some data back and forth between the client and the server.
The client sends many types of data to the server (string, int, files and a real time audio stream) and since my server impliment a single data input SLOT (readyRead()):
connect(socket, SIGNAL(readyRead()),this, SLOT(readyRead()));
I don't know how could I distinguish between all this received data and call respectively the right function in the server.
Example (in the server):
- if I receive string => call function showData(QString data);
- if I receive file => call function saveFile(QFile file);
- if I receive audio stream => play audio stream
- ...
SERVER:
void Server::newClientConnection()
{
QTcpSocket *socket = server->nextPendingConnection();
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
//...
}
void Server::readyRead()
{
QTcpSocket *clientSocket = qobject_cast<QTcpSocket *>(sender());
if (clientSocket == 0) {
return;
}
QDataStream in(clientSocket);
if (sizeMessageClient == 0)
{
if (clientSocket->bytesAvailable() < (int)sizeof(quint16)){
return;
}
in >> sizeMessageClient;
}
if (clientSocket->bytesAvailable() < sizeMessageClient) {
return;
}
sizeMessageClient = 0;
in >> data;
/*
I don't know the type of the received data !!
- if I receive string => call function showData(QString data);
- if I receive file => call function saveFile(QFile file);
- if I receive audio stream => play audio stream
- ...
*/
}
CLIENT:
Client::Client()
{
socket = new QTcpSocket(this);
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
sizeMessageServer = 0;
}
void Client::readyRead()
{
QDataStream in(socket);
if (sizeMessageServer == 0)
{
if (socket->bytesAvailable() < (int)sizeof(quint16)) {
return;
}
in >> sizeMessageServer;
}
if (socket->bytesAvailable() < sizeMessageServer) {
return;
}
int messageReceived;
in >> messageReceived;
messageReceived = static_cast<int>(messageReceived);
sizeMessageServer = 0;
switch(messageReceived)
{
case 1:
qDebug() << "send a File";
sendFile();
break;
case 2:
qDebug() << "send a string data";
sendStringData();
break;
case 3:
qDebug() << "stream audio to the server";
streamAudioToServer();
break;
case n:
// ...
}
}
I am not looking for a complete solution, all I am looking for is some guidance in the right direction.
The implementation of your protocol doesn't fully leverage QDataStream in Qt 5.7. Here's how it might look now - it can be quite simple.
First, let's define the requests we know of:
enum class Req : quint32 {
Unknown, String, File
};
Q_DECLARE_METATYPE(Req)
QDataStream & operator<<(QDataStream & ds, Req req) {
return ds << (quint32)req;
}
QDataStream & operator>>(QDataStream & ds, Req & req) {
quint32 val;
ds >> val;
if (ds.status() == QDataStream::Ok)
req = Req(val);
return ds;
}
It'd also be handy to have a transaction RAII helper.
struct Transaction {
QDataStream & stream;
Transaction(QDataStream & stream) : stream{stream} {
stream.startTransaction();
}
~Transaction() {
stream.commitTransaction();
}
bool ok() {
return stream.status() == QDataStream::Ok;
}
};
The client receives requests from the server and signals the need to reply with data. The code that uses the client would react to these signals and reply back by invoking a matching slot. E.g.
void clientUser(Client & client) {
QObject::connect(&client, &Client::needString, &client, [&]{
client.sendString(QStringLiteral{"You got string!"});
});
And:
class Client : public QObject {
Q_OBJECT
QIODevice & m_dev;
QDataStream m_str{&m_dev};
void onReadyRead() {
Transaction tr{m_str};
Req req;
m_str >> req;
if (!tr.ok()) return;
if (req == Req::String)
emit needString();
else if (req == Req::File) {
QString fileName;
m_str >> fileName;
if (!tr.ok()) return;
emit needFile(fileName);
}
else emit unknownRequest(req);
}
public:
Client(QIODevice & dev) : m_dev{dev} {
connect(&m_dev, &QIODevice::readyRead, this, &Client::onReadyRead);
}
Q_SIGNAL void unknownRequest(Req);
Q_SIGNAL void needString();
Q_SIGNAL void needFile(const QString & fileName);
Q_SLOT void sendString(const QString & str) {
m_str << Req::String << str;
}
Q_SLOT void sendFile(const QString & fileName, const QByteArray & data) {
m_str << Req::File << fileName << data;
}
};
The server is very similar. Its user sends the request to a client via request slots. Once the server hears back from the client, it indicates it through the has signals:
class Server : public QObject {
Q_OBJECT
QIODevice & m_dev;
QDataStream m_str{&m_dev};
void onReadyRead() {
Transaction tr{m_str};
Req req;
m_str >> req;
if (!tr.ok()) return;
if (req == Req::String) {
QString str;
m_str >> str;
if (!tr.ok()) return;
emit hasString(str);
}
else if (req == Req::File) {
QString fileName;
QByteArray data;
m_str >> fileName >> data;
if (!tr.ok()) return;
emit hasFile(fileName, data);
}
else emit hasUnknownRequest(req);
}
public:
Server(QIODevice & dev) : m_dev{dev} {
connect(&m_dev, &QIODevice::readyRead, this, &Server::onReadyRead);
}
Q_SIGNAL void hasUnknownRequest(Req);
Q_SIGNAL void hasString(const QString &);
Q_SIGNAL void hasFile(const QString & name, const QByteArray &);
Q_SLOT void requestString() {
m_str << Req::String;
}
Q_SLOT void requestFile(const QString & name) {
m_str << Req::File << name;
}
};