Added sendRequestReceiveResponse(): static member for communication with
APISM, on ports 7777 and 7778. Each request is immediately handled in a synchronous fashion. Added several helper functions to format messages to be sent to APISM/ISMAS.
This commit is contained in:
parent
5c9c9dc917
commit
a94606ca89
@ -3,6 +3,24 @@
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h> // inet_addr()
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <string.h>
|
||||
#include <strings.h> // bzero()
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h> // read(), write(), close()
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
#include <QThread>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
#if 0
|
||||
# $1: EVENT: U0001 update finished: 100%
|
||||
# U0002 reset TRG
|
||||
@ -24,6 +42,208 @@
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
|
||||
void IsmasClient::printDebugMessage(int port,
|
||||
QString const &clientIP,
|
||||
int clientPort,
|
||||
QString const &message) {
|
||||
qDebug().noquote()
|
||||
<< "\n"
|
||||
<< "SEND-REQUEST-RECEIVE-RESPONSE ..." << "\n"
|
||||
<< "hostname ........" << "127.0.0.1" << "\n"
|
||||
<< "port ............" << port << "\n"
|
||||
<< "local address ..." << clientIP << "\n"
|
||||
<< "local port ......" << clientPort << "\n"
|
||||
<< message;
|
||||
}
|
||||
|
||||
void IsmasClient::printInfoMessage(int port,
|
||||
QString const &clientIP,
|
||||
int clientPort,
|
||||
QString const &message) {
|
||||
qInfo().noquote()
|
||||
<< "\n"
|
||||
<< "SEND-REQUEST-RECEIVE-RESPONSE ..." << "\n"
|
||||
<< "hostname ........" << "127.0.0.1" << "\n"
|
||||
<< "port ............" << port << "\n"
|
||||
<< "local address ..." << clientIP << "\n"
|
||||
<< "local port ......" << clientPort << "\n"
|
||||
<< message;
|
||||
}
|
||||
|
||||
void IsmasClient::printErrorMessage(int port,
|
||||
QString const &clientIP,
|
||||
int clientPort,
|
||||
QString const &message) {
|
||||
qCritical().noquote()
|
||||
<< "\n"
|
||||
<< "SEND-REQUEST-RECEIVE-RESPONSE ..." << "\n"
|
||||
<< "hostname ........" << "127.0.0.1" << "\n"
|
||||
<< "port ............" << port << "\n"
|
||||
<< "local address ..." << clientIP << "\n"
|
||||
<< "local port ......" << clientPort << "\n"
|
||||
<< message;
|
||||
}
|
||||
|
||||
std::optional<QString>
|
||||
IsmasClient::sendRequestReceiveResponse(int port, QString const &request) {
|
||||
|
||||
qInfo() << "REQUEST" << request;
|
||||
|
||||
int sockfd;
|
||||
int r;
|
||||
errno = 0;
|
||||
// socket create and verification
|
||||
if ((sockfd = ::socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
||||
qCritical().noquote()
|
||||
<< "\n"
|
||||
<< "SEND-REQUEST-RECEIVE-RESPONSE ..." << "\n"
|
||||
<< "SOCKET CREATION FAILED (" << strerror(errno) << ")";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
struct sockaddr_in servAddr;
|
||||
bzero(&servAddr, sizeof(servAddr));
|
||||
// assign IP, PORT
|
||||
servAddr.sin_family = AF_INET;
|
||||
servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
||||
servAddr.sin_port = htons(port);
|
||||
// connect the client socket to server socket
|
||||
if ((r = ::connect(sockfd, (struct sockaddr *)(&servAddr), sizeof(servAddr))) != 0) {
|
||||
qCritical().noquote()
|
||||
<< "\n"
|
||||
<< "SEND-REQUEST-RECEIVE-RESPONSE ..." << "\n"
|
||||
<< "CONNECTION WITH SERVER FAILED (" << strerror(r) << ")";
|
||||
::close(sockfd);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
struct sockaddr_in clientAddr;
|
||||
bzero(&clientAddr, sizeof(clientAddr));
|
||||
socklen_t sockLen = sizeof(clientAddr);
|
||||
|
||||
char clientIP[16];
|
||||
bzero(&clientIP, sizeof(clientIP));
|
||||
getsockname(sockfd, (struct sockaddr *)(&clientAddr), &sockLen);
|
||||
inet_ntop(AF_INET, &clientAddr.sin_addr, clientIP, sizeof(clientIP));
|
||||
unsigned int clientPort = ntohs(clientAddr.sin_port);
|
||||
|
||||
printDebugMessage(port, clientIP, clientPort, QString("CONNECTED TO SERVER"));
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 10; /* 10 secs timeout for read and write */
|
||||
|
||||
struct linger so_linger;
|
||||
so_linger.l_onoff = 1;
|
||||
so_linger.l_linger = 0;
|
||||
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger));
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
|
||||
int flag = 1;
|
||||
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
|
||||
|
||||
static char buf[1024*8];
|
||||
bzero(buf, sizeof(buf));
|
||||
int const bytesToWrite = strlen(request.toStdString().c_str());
|
||||
strncpy(buf, request.toStdString().c_str(), sizeof(buf)-1);
|
||||
|
||||
int bytesWritten = 0;
|
||||
while (bytesWritten < bytesToWrite) {
|
||||
int n = ::sendto(sockfd, buf+bytesWritten, bytesToWrite-bytesWritten, 0, NULL, 0);
|
||||
if (n >= 0) {
|
||||
bytesWritten += n;
|
||||
} else {
|
||||
if (errno == EWOULDBLOCK) {
|
||||
printErrorMessage(port, clientIP, clientPort,
|
||||
QString("TIMEOUT (") + strerror(errno) + ")");
|
||||
::close(sockfd);
|
||||
return std::nullopt;
|
||||
} else
|
||||
if (errno == EINTR) {
|
||||
printErrorMessage(port, clientIP, clientPort,
|
||||
QString("INTERRUPTED BY SIGNAL (1) (") + strerror(errno) + ")");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DO NOT USE SHUTDOWN! APISM CAN NOT COPE WITH IT
|
||||
// errno = 0;
|
||||
// if (shutdown(sockfd, SHUT_WR) < 0) {
|
||||
// printErrorMessage(port, clientIP, clientPort,
|
||||
// QString("CANNOT CLOSE WRITING END (") + strerror(errno) + ")");
|
||||
// }
|
||||
|
||||
printInfoMessage(port, clientIP, clientPort, QString("MESSAGE SENT ") + buf);
|
||||
|
||||
bzero(buf, sizeof(buf));
|
||||
int bytesToRead = sizeof(buf)-1;
|
||||
int bytesRead = 0;
|
||||
while (bytesRead < bytesToRead) {
|
||||
errno = 0;
|
||||
int n = ::recvfrom(sockfd, buf+bytesRead, bytesToRead-bytesRead,
|
||||
0, NULL, NULL);
|
||||
if (n > 0) { //
|
||||
bytesRead += n;
|
||||
} else
|
||||
if (n == 0) {
|
||||
// The return value will be 0 when the peer has performed an orderly shutdown.
|
||||
printErrorMessage(port, clientIP, clientPort,
|
||||
QString("PEER CLOSED CONNECTION (") + strerror(errno) + ")");
|
||||
::close(sockfd);
|
||||
return std::nullopt;
|
||||
} else
|
||||
if (n < 0) {
|
||||
if (errno == EWOULDBLOCK) {
|
||||
printErrorMessage(port, clientIP, clientPort,
|
||||
QString("TIMEOUT (") + strerror(errno) + ")");
|
||||
::close(sockfd);
|
||||
return std::nullopt;
|
||||
}
|
||||
if (errno == EINTR) {
|
||||
printErrorMessage(port, clientIP, clientPort,
|
||||
QString("INTERRUPTED BY SIGNAL (2) (") + strerror(errno) + ")");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
printInfoMessage(port, clientIP, clientPort, QString("MESSAGE RECEIVED ") + buf);
|
||||
QString response(buf);
|
||||
|
||||
if (int idx = response.indexOf("{\"error\":\"ISMAS is offline\"}")) {
|
||||
response = response.mid(0, idx);
|
||||
} else
|
||||
if (response == "RECORD SAVED") {
|
||||
printInfoMessage(port, clientIP, clientPort, "IGNORED 'RECORD SAVED' RESPONSE");
|
||||
::close(sockfd);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QJsonParseError parseError;
|
||||
QJsonDocument document(QJsonDocument::fromJson(response.toUtf8(), &parseError));
|
||||
if (parseError.error == QJsonParseError::NoError) {
|
||||
if (document.isObject()) { // done: received valid APISM response
|
||||
printInfoMessage(port, clientIP, clientPort,
|
||||
QString("VALID APISM RESPONSE .. \n") + response);
|
||||
::close(sockfd);
|
||||
return response;
|
||||
} else {
|
||||
printInfoMessage(port, clientIP, clientPort,
|
||||
QString("CORRUPTED RESPONSE ") + response);
|
||||
::close(sockfd);
|
||||
return std::nullopt;
|
||||
}
|
||||
} else {
|
||||
printDebugMessage(port, clientIP, clientPort,
|
||||
QString("PARSE ERROR ") + response + " " + parseError.errorString());
|
||||
::close(sockfd);
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
QString IsmasClient::updateNewsToIsmas(char const *event,
|
||||
int percent,
|
||||
int resultCode,
|
||||
@ -53,6 +273,54 @@ QString IsmasClient::updateNewsToIsmas(char const *event,
|
||||
return buf;
|
||||
}
|
||||
|
||||
QString IsmasClient::errorBackendNotConnected(QString const &info,
|
||||
QString const &version) {
|
||||
return updateNewsToIsmas("U0003",
|
||||
m_progressInPercent,
|
||||
RESULT_CODE::INSTALL_ERROR,
|
||||
"CHECK BACKEND CONNECTIVITY",
|
||||
info.toStdString().c_str(),
|
||||
version.toStdString().c_str());
|
||||
}
|
||||
|
||||
QString IsmasClient::backendConnected(QString const &info, QString const &version) {
|
||||
return updateNewsToIsmas("U0010",
|
||||
m_progressInPercent,
|
||||
RESULT_CODE::SUCCESS,
|
||||
"CHECK BACKEND CONNECTIVITY",
|
||||
info.toStdString().c_str(),
|
||||
version.toStdString().c_str());
|
||||
}
|
||||
|
||||
QString IsmasClient::execOpkgCommand(QString const &info, QString const &version) {
|
||||
return updateNewsToIsmas("U0010",
|
||||
m_progressInPercent,
|
||||
RESULT_CODE::SUCCESS,
|
||||
"EXECUTE OPKG COMMAND",
|
||||
info.toStdString().c_str(),
|
||||
version.toStdString().c_str());
|
||||
}
|
||||
|
||||
QString IsmasClient::updateTriggerSet(QString const &info, QString const &version) {
|
||||
return updateNewsToIsmas("U0010",
|
||||
m_progressInPercent,
|
||||
RESULT_CODE::SUCCESS,
|
||||
"CHECK UPDATE TRIGGER",
|
||||
info.toStdString().c_str(),
|
||||
version.toStdString().c_str());
|
||||
|
||||
}
|
||||
|
||||
QString IsmasClient::errorUpdateTrigger(QString const &info, QString const &version) {
|
||||
return updateNewsToIsmas("U0003",
|
||||
m_progressInPercent,
|
||||
RESULT_CODE::INSTALL_ERROR,
|
||||
"CHECK UPDATE TRIGGER",
|
||||
info.toStdString().c_str(),
|
||||
version.toStdString().c_str());
|
||||
|
||||
}
|
||||
|
||||
QString IsmasClient::updateOfPSASendVersion(PSAInstalled const &psa) {
|
||||
//static int const constexpr SIZE = 4096*8;
|
||||
static char buf[4096*2];
|
||||
@ -376,39 +644,101 @@ QString IsmasClient::updateOfPSASendVersion(PSAInstalled const &psa) {
|
||||
psa.pluginVersion.prmCalculatePriceConfigUi.toStdString().c_str(),
|
||||
psa.pluginVersion.tcpZVT.toStdString().c_str());
|
||||
|
||||
printf("buf=%s\n", buf);
|
||||
qInfo() << buf;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
QString IsmasClient::updateOfPSAActivated() {
|
||||
QString IsmasClient::updateOfPSAContinues(QString currentStage,
|
||||
QString currentStageInfo,
|
||||
QString const &version) {
|
||||
return updateNewsToIsmas("U0010",
|
||||
1,
|
||||
0,
|
||||
"activated",
|
||||
"detected WAIT state",
|
||||
"1.0.0");
|
||||
m_progressInPercent,
|
||||
RESULT_CODE::SUCCESS,
|
||||
currentStage.toStdString().c_str(),
|
||||
currentStageInfo.toStdString().c_str(),
|
||||
version.toStdString().c_str());
|
||||
}
|
||||
|
||||
QString IsmasClient::updateOfPSASucceeded() {
|
||||
QString IsmasClient::updateOfPSAStarted(QString const &version) {
|
||||
return updateNewsToIsmas("U0010",
|
||||
m_progressInPercent,
|
||||
RESULT_CODE::SUCCESS,
|
||||
"START",
|
||||
"detected WAIT state: start update process",
|
||||
version.toStdString().c_str());
|
||||
}
|
||||
|
||||
QString IsmasClient::checkoutBranch(QString const &info, QString const &version) {
|
||||
return updateNewsToIsmas("U0010",
|
||||
m_progressInPercent,
|
||||
RESULT_CODE::SUCCESS,
|
||||
"BRANCH-CHECKOUT",
|
||||
info.toStdString().c_str(),
|
||||
version.toStdString().c_str());
|
||||
}
|
||||
|
||||
QString IsmasClient::cloneAndCheckoutCustomerRepository(QString const &info, QString const &version) { // clone and checkout customer repository
|
||||
return updateNewsToIsmas("U0010",
|
||||
m_progressInPercent,
|
||||
RESULT_CODE::SUCCESS,
|
||||
"CLONE-CHECKOUT",
|
||||
info.toStdString().c_str(),
|
||||
version.toStdString().c_str());
|
||||
}
|
||||
|
||||
QString IsmasClient::gitFetch(QString const &info, QString const &version) {
|
||||
return updateNewsToIsmas("U0010",
|
||||
m_progressInPercent,
|
||||
RESULT_CODE::SUCCESS,
|
||||
"GIT-FETCH",
|
||||
info.toStdString().c_str(),
|
||||
version.toStdString().c_str());
|
||||
}
|
||||
|
||||
QString IsmasClient::errorGitFetch(int resultCode, QString const &info, QString const &version) {
|
||||
return updateNewsToIsmas("U0003",
|
||||
m_progressInPercent,
|
||||
resultCode,
|
||||
"GIT-FETCH-FAILED",
|
||||
info.toStdString().c_str(),
|
||||
version.toStdString().c_str());
|
||||
}
|
||||
|
||||
QString IsmasClient::updateOfPSAActivated(QString const &version) { // sent even after success
|
||||
m_progressInPercent = 0;
|
||||
return updateNewsToIsmas("U0002",
|
||||
m_progressInPercent,
|
||||
RESULT_CODE::SUCCESS,
|
||||
"UPDATE ACTIVATED",
|
||||
"reset WAIT state",
|
||||
version.toStdString().c_str());
|
||||
}
|
||||
|
||||
QString IsmasClient::updateOfPSASucceeded(QString const &version) {
|
||||
m_progressInPercent = 0;
|
||||
return updateNewsToIsmas("U0001",
|
||||
100,
|
||||
0,
|
||||
"update_succeeded",
|
||||
"",
|
||||
"1.0.0");
|
||||
m_progressInPercent,
|
||||
RESULT_CODE::SUCCESS,
|
||||
"UPDATE SUCCESS",
|
||||
"update process succeeded",
|
||||
version.toStdString().c_str());
|
||||
}
|
||||
|
||||
QString IsmasClient::setUpdatesAvailable() {
|
||||
return updateNewsToIsmas("U0099",
|
||||
10,
|
||||
0,
|
||||
"set_updates_available",
|
||||
"",
|
||||
"");
|
||||
QString IsmasClient::sanityCheckFailed(int resultCode, QString reason, QString const &version) {
|
||||
return updateNewsToIsmas("U0003",
|
||||
m_progressInPercent,
|
||||
resultCode,
|
||||
"SANITY-CHECK-FAILED",
|
||||
reason.toStdString().c_str(),
|
||||
version.toStdString().c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool checkForAvailableUpdates();
|
||||
QString IsmasClient::updateOfPSAFailed(int resultCode, QString reason, QString const &version) {
|
||||
return updateNewsToIsmas("U0003",
|
||||
m_progressInPercent,
|
||||
resultCode,
|
||||
"UPDATE ERROR",
|
||||
reason.toStdString().c_str(),
|
||||
version.toStdString().c_str());
|
||||
}
|
||||
|
@ -111,7 +111,28 @@ struct PSAInstalled {
|
||||
class IsmasClient : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
int m_progressInPercent;
|
||||
public:
|
||||
explicit IsmasClient() : m_progressInPercent(1) {}
|
||||
|
||||
enum APISM {
|
||||
DB_PORT = 7777,
|
||||
DIRECT_PORT = 7778
|
||||
};
|
||||
|
||||
enum RESULT_CODE {
|
||||
SUCCESS=0,
|
||||
NO_UPDATE_NECESSARY=1,
|
||||
BACKUP_FAILED=2,
|
||||
WRONG_PACKAGE=3,
|
||||
INSTALL_ERROR=4};
|
||||
|
||||
static std::optional<QString>
|
||||
sendRequestReceiveResponse(int port, QString const &request);
|
||||
|
||||
int getProgressInPercent() const {return m_progressInPercent; }
|
||||
void setProgressInPercent(int procent) { m_progressInPercent = procent; }
|
||||
|
||||
QString updateNewsToIsmas(char const *event,
|
||||
int percent,
|
||||
int resultCode,
|
||||
@ -119,12 +140,32 @@ public:
|
||||
char const *step_result,
|
||||
char const *version);
|
||||
|
||||
QString updateOfPSAActivated();
|
||||
QString updateOfPSASucceeded();
|
||||
QString updateOfPSAStarted(QString const &version = QString()); // start of update process
|
||||
QString cloneAndCheckoutCustomerRepository(QString const &info, QString const &version = QString()); // clone and checkout customer repository
|
||||
QString checkoutBranch(QString const &info, QString const &version = QString()); // checkout branch
|
||||
QString errorBackendNotConnected(QString const &info, QString const &version = QString()); // checkout branch
|
||||
QString backendConnected(QString const &info, QString const &version = QString());
|
||||
QString updateTriggerSet(QString const &info, QString const &version = QString());
|
||||
QString errorUpdateTrigger(QString const &info, QString const &version = QString());
|
||||
QString gitFetch(QString const &info, QString const &version = QString());
|
||||
QString execOpkgCommand(QString const &info, QString const &version = QString());
|
||||
QString errorGitFetch(int resultCode, QString const &info, QString const &version = QString());
|
||||
QString updateOfPSAActivated(QString const &version = QString());
|
||||
// and update accepted
|
||||
QString updateOfPSASucceeded(QString const &version = QString()); // update process succeeded
|
||||
QString updateOfPSAContinues(QString currentStage, QString currentStageInfo, QString const &version = QString());
|
||||
QString updateOfPSAFailed(int resultCode, QString reason, QString const &version = QString());
|
||||
QString sanityCheckFailed(int resultCode, QString reason, QString const &version = QString());
|
||||
|
||||
QString updateOfPSASendVersion(PSAInstalled const &psa);
|
||||
|
||||
QString setUpdatesAvailable();
|
||||
bool checkForAvailableUpdates();
|
||||
private:
|
||||
static void printDebugMessage(int port, QString const &clientIP, int clientPort,
|
||||
QString const &message);
|
||||
static void printInfoMessage(int port, QString const &clientIP, int clientPort,
|
||||
QString const &message);
|
||||
static void printErrorMessage(int port, QString const &clientIP, int clientPort,
|
||||
QString const &message);
|
||||
};
|
||||
|
||||
#endif // ISMAS_CLIENT_H_INCLUDED
|
||||
|
Loading…
Reference in New Issue
Block a user