jce-manager/src/jceConnection/jcesslclient.cpp

454 lines
16 KiB
C++
Raw Normal View History

2014-09-08 15:54:52 +00:00
#include "jcesslclient.h"
/**
* @brief jceSSLClient::jceSSLClient Constructer, setting the signals
*/
2014-10-12 22:14:26 +00:00
jceSSLClient::jceSSLClient(jceStatusBar *statusBar) : loggedIAndConnectedFlag(false), readingFlag(false),
2014-10-10 15:20:33 +00:00
reConnectionFlag(false), networkConf(), packet(""), recieveLastPacket(false), packetSizeRecieved(0)
2014-09-08 15:54:52 +00:00
{
2014-10-12 22:14:26 +00:00
this->statusBar = statusBar;
2014-10-04 00:54:27 +00:00
//setting signals
connect(this,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(checkErrors(QAbstractSocket::SocketError)));
connect(this,SIGNAL(connected()),this,SLOT(setConnected()));
connect(this,SIGNAL(encrypted()),this,SLOT(setEncrypted()));
connect(this,SIGNAL(disconnected()),this,SLOT(setDisconnected()));
connect(&networkConf,SIGNAL(onlineStateChanged(bool)),this,SLOT(setOnlineState(bool)));
//loop event will connect the server, and when it is connected, it will quit - but connection will be open
2014-10-10 15:20:33 +00:00
connect(this, SIGNAL(encrypted()), &loginThreadLoop, SLOT(quit()));
connect(this, SIGNAL(error(QAbstractSocket::SocketError)),&loginThreadLoop,SLOT(quit()));
2014-09-08 15:54:52 +00:00
}
/**
* @brief jceSSLClient::makeConnect connecting to server with given port. using eventloop to assure it wont stuck the application.
* @param server - server to connect to
* @param port - the using port
* @return - true if connected, false otherwise
*/
bool jceSSLClient::makeConnect(QString server, int port)
2014-09-08 15:54:52 +00:00
{
2014-10-04 00:54:27 +00:00
if (this->supportsSsl() == false)
{
2014-10-04 00:54:27 +00:00
qCritical() << Q_FUNC_INFO << "Couldnt load ssl package. ERROR";
return false;
}
2014-10-04 00:54:27 +00:00
else
qDebug() << Q_FUNC_INFO << "ssl loaded.";
2014-10-04 00:54:27 +00:00
if (isConnectedToNetwork() == false)
{
2014-10-04 00:54:27 +00:00
qDebug() << Q_FUNC_INFO << "return false. not online";
return false;
}
2014-10-04 00:54:27 +00:00
else
qDebug() << Q_FUNC_INFO << "we're online";
2014-10-10 15:20:33 +00:00
if (reConnectionFlag) //reset reconnectiong flag
2014-09-21 10:31:26 +00:00
{
2014-10-04 00:54:27 +00:00
qDebug() << Q_FUNC_INFO << "Making Reconnection";
2014-09-21 10:31:26 +00:00
}
2014-10-04 00:54:27 +00:00
else
qDebug() << Q_FUNC_INFO << "Making Connection";
2014-09-21 10:31:26 +00:00
2014-10-04 00:54:27 +00:00
if (isConnected())
{
2014-10-04 00:54:27 +00:00
qDebug() << Q_FUNC_INFO << "flag=true, calling makeDisconnect()";
makeDiconnect();
}
2014-09-21 10:31:26 +00:00
2014-10-04 00:54:27 +00:00
qDebug() << Q_FUNC_INFO << "Connection to: " << server << "On Port: " << port;
connectToHostEncrypted(server.toStdString().c_str(), port);
2014-10-10 15:20:33 +00:00
loginThreadLoop.exec(); //starting connection, waiting to encryption and then it ends
2014-09-08 15:54:52 +00:00
2014-10-04 00:54:27 +00:00
qDebug() << Q_FUNC_INFO << "returning the connection status: " << isConnected();
2014-10-10 15:20:33 +00:00
if (reConnectionFlag)
2014-09-21 10:31:26 +00:00
{
2014-10-10 15:20:33 +00:00
reConnectionFlag = false;
2014-10-04 00:54:27 +00:00
emit serverDisconnectedbyRemote();
2014-09-21 10:31:26 +00:00
}
2014-10-04 00:54:27 +00:00
return isConnected();
2014-09-08 15:54:52 +00:00
}
/**
* @brief jceSSLClient::makeDiconnect from current server
* @return the flag of connection status
*/
2014-09-08 15:54:52 +00:00
bool jceSSLClient::makeDiconnect()
{
2014-10-10 15:20:33 +00:00
if (loginThreadLoop.isRunning())
{
2014-10-04 00:54:27 +00:00
qWarning() << Q_FUNC_INFO << "Killing connection thread";
2014-10-10 15:20:33 +00:00
loginThreadLoop.exit();
}
2014-10-04 00:54:27 +00:00
qDebug() << Q_FUNC_INFO << "disconnecting from host and emitting disconnected()";
this->disconnectFromHost(); //emits disconnected > setDisconnected
setSocketState(QAbstractSocket::SocketState::UnconnectedState);
return (!isConnected());
2014-09-08 15:54:52 +00:00
}
/**
* @brief jceSSLClient::isConnected connection checking
* @return regardless to state, it checks if there's a connection
*/
2014-09-08 15:54:52 +00:00
bool jceSSLClient::isConnected()
{
2014-10-04 00:54:27 +00:00
bool tempFlag = false;
//checking state before returning flag!
if (state() == QAbstractSocket::SocketState::UnconnectedState)
{
2014-10-04 00:54:27 +00:00
tempFlag = false;
}
2014-10-04 00:54:27 +00:00
else if (state() == QAbstractSocket::SocketState::ClosingState)
{
2014-10-04 00:54:27 +00:00
tempFlag = false;
}
2014-10-04 00:54:27 +00:00
else if (state() == QAbstractSocket::SocketState::ConnectedState)
{
2014-10-04 00:54:27 +00:00
if (isConnectedToNetwork())
tempFlag = true;
else
{
2014-10-04 00:54:27 +00:00
this->setSocketState(QAbstractSocket::SocketState::UnconnectedState);
tempFlag = false;
}
}
2014-10-04 00:54:27 +00:00
if (!isConnectedToNetwork()) //no link, ethernet\wifi
tempFlag = false;
2014-10-10 15:20:33 +00:00
return ((loggedIAndConnectedFlag) && (tempFlag));
2014-09-08 15:54:52 +00:00
}
/**
* @brief jceSSLClient::sendData - given string, send it to server
* @param str - string to send
* @return true if succeed and byte were written
*/
bool jceSSLClient::sendData(QString str)
2014-09-08 15:54:52 +00:00
{
2014-10-04 00:54:27 +00:00
bool sendDataFlag = false;
2014-10-10 15:20:33 +00:00
int amount = 0;
2014-10-04 00:54:27 +00:00
if (isConnected()) //if connected
2014-09-08 15:54:52 +00:00
{
2014-10-12 22:14:26 +00:00
statusBar->setIconConnectionStatus(jceStatusBar::Sending);
2014-10-10 15:20:33 +00:00
amount = write(str.toStdString().c_str(),str.length());
qDebug() << Q_FUNC_INFO << "lenght send: " << str.length() << "lenght recieved: " << amount;
if (amount == -1)
{
qCritical() << Q_FUNC_INFO << "SendData ended with -1";
sendDataFlag = false;
}
else if (waitForBytesWritten())
2014-10-04 00:54:27 +00:00
sendDataFlag = true;
2014-09-08 15:54:52 +00:00
}
2014-10-04 00:54:27 +00:00
qDebug() << Q_FUNC_INFO << "Sending Data status is: " << sendDataFlag;
return sendDataFlag;
2014-09-08 15:54:52 +00:00
}
/**
2014-10-10 15:50:07 +00:00
* @brief jceSSLClient::recieveData - recieving data through threaded reading and mutex
* @param str - string to fill with data.
* @return true if packet has recieced the last packet -> true, otherwise ->false
2014-09-08 15:54:52 +00:00
*/
2014-10-10 15:20:33 +00:00
bool jceSSLClient::recieveData(QString *str)
2014-09-08 15:54:52 +00:00
{
2014-10-12 22:14:26 +00:00
statusBar->setIconConnectionStatus(jceStatusBar::Recieving);
2014-10-04 00:54:27 +00:00
qDebug() << Q_FUNC_INFO << "Data receiving!";
2014-10-10 15:20:33 +00:00
str->clear();
2014-10-04 00:54:27 +00:00
packet = "";
2014-10-10 15:20:33 +00:00
recieveLastPacket = false;
packetSizeRecieved = 0; //counting packet size
readingFlag = true; //to ignore timeout socket error
2014-09-08 15:54:52 +00:00
2014-10-10 15:50:07 +00:00
timer.setSingleShot(true); //counting just once.
2014-10-10 15:20:33 +00:00
timer.start(milisTimeOut); //if timer is timeout -> it means the connection takes long time
2014-10-04 00:54:27 +00:00
2014-10-10 15:20:33 +00:00
connect(this, SIGNAL(readyRead()), this, SLOT(readIt())); //we have something to read
connect(&timer, SIGNAL(timeout()), &readerLoop, SLOT(quit())); //if timer timeout > exiting event
2014-10-04 00:54:27 +00:00
2014-10-10 15:20:33 +00:00
readerLoop.exec();
disconnect(&timer, SIGNAL(timeout()), &readerLoop, SLOT(quit()));
disconnect(this, SIGNAL(readyRead()), this, SLOT(readIt()));
str->append(packet);
qDebug() << *str; //if you want to see the whole packet, unmark me
2014-10-10 15:20:33 +00:00
qDebug() << Q_FUNC_INFO << "packet size: " << packetSizeRecieved << "received data lenght: " << str->length();
2014-10-10 15:50:07 +00:00
qDebug() << Q_FUNC_INFO << "return with flag: " << recieveLastPacket;
readingFlag = false; //finished reading session
return recieveLastPacket; //we have the last packet
2014-09-08 15:54:52 +00:00
}
/**
2014-10-10 15:50:07 +00:00
* @brief jceSSLClient::readIt
* this method, called by a thread to read the bytes avilable by the remote server
* each packet we append into the class private var 'packet' (mutexed)
* if we recieve the last packet (see tags below) we set the timer of the calling function to 100msc
*
*/
2014-09-08 15:54:52 +00:00
void jceSSLClient::readIt()
{
2014-10-10 15:20:33 +00:00
int packSize = bytesAvailable();
int doTimes=0;
QByteArray tempPacket;
2014-09-08 15:54:52 +00:00
2014-10-04 00:54:27 +00:00
do
{
// qDebug() << Q_FUNC_INFO << "packet size" << packSize;
2014-10-10 15:20:33 +00:00
if (doTimes++ > 0) //for debbuging, checking thread looping times
qDebug() << Q_FUNC_INFO << "do loop" << doTimes;
waitForReadyRead(100);
tempPacket = read(packSize);
readerAppendingLocker.lock();
packetSizeRecieved += packSize;
packet.append(tempPacket);
packet.append("\0");
readerAppendingLocker.unlock();
2014-10-12 22:14:26 +00:00
emit statusBar->progressHasPacket(10);
2014-10-10 15:20:33 +00:00
if (tempPacket.contains("Go_To_system_After_Login.htm") || tempPacket.contains("</html>"))
2014-10-04 00:54:27 +00:00
{
2014-10-10 15:20:33 +00:00
//we have the last packet. (uses only in login first step
recieveLastPacket = true;
timer.setInterval(200);
}
else
{
//just a packet with data
2014-10-04 00:54:27 +00:00
}
2014-10-10 15:20:33 +00:00
}while ((packSize = bytesAvailable()) > 0);
}
void jceSSLClient::setOnlineState(bool isOnline)
{
2014-10-04 00:54:27 +00:00
qWarning() << Q_FUNC_INFO << "isOnline status change: " << isOnline;
if (isOnline) //to be added later
{
2014-10-04 00:54:27 +00:00
qDebug() << Q_FUNC_INFO << "Online Statue has been changed. we are online";
//we can add here auto reconnect if wifi\ethernet link has appear
//will be added next version
}
2014-10-04 00:54:27 +00:00
else
{
2014-10-04 00:54:27 +00:00
qWarning() << Q_FUNC_INFO << "Online State has been changed. emitting NoInternetLink";
this->makeDiconnect();
emit noInternetLink();
}
2014-09-08 15:54:52 +00:00
}
/**
* @brief jceSSLClient::setConnected called when signaled with connected, calling the encryption function
*/
2014-09-08 15:54:52 +00:00
void jceSSLClient::setConnected()
{
2014-10-04 00:54:27 +00:00
waitForEncrypted();
2014-09-08 15:54:52 +00:00
}
/**
* @brief jceSSLClient::setDisconnected closing socket, updating state and setting flag to false
*/
void jceSSLClient::setDisconnected()
{
2014-10-04 00:54:27 +00:00
qDebug() << Q_FUNC_INFO << "connection has been DISCONNECTED";
this->setSocketState(QAbstractSocket::SocketState::UnconnectedState);
packet.clear();
2014-10-10 15:20:33 +00:00
loggedIAndConnectedFlag = false;
if (reConnectionFlag)
2014-10-04 00:54:27 +00:00
makeConnect();
}
/**
* @brief jceSSLClient::setEncrypted called when signaled with encrypted. setting the buffer size and keeping alive.
*/
2014-09-08 15:54:52 +00:00
void jceSSLClient::setEncrypted()
{
2014-10-04 00:54:27 +00:00
qDebug() << Q_FUNC_INFO << "connection has been ENCRYPTED";
2014-10-09 18:17:51 +00:00
setReadBufferSize(packetSize);
2014-10-04 00:54:27 +00:00
setSocketOption(QAbstractSocket::KeepAliveOption,true);
2014-10-10 15:20:33 +00:00
loggedIAndConnectedFlag = true;
2014-10-04 00:54:27 +00:00
if (!isConnected())
{
2014-10-04 00:54:27 +00:00
qWarning() << Q_FUNC_INFO << "Connection status didnt change! reseting flag to false";
2014-10-10 15:20:33 +00:00
loggedIAndConnectedFlag = false;
}
2014-09-08 15:54:52 +00:00
}
/**
* @brief jceSSLClient::showIfErrorMsg message box to show the error occured according to socket
* if relevant, we will prompt a message box to informate the user
* otherwise, we will handle the error or ignore it.
*/
void jceSSLClient::showIfErrorMsg()
2014-09-08 15:54:52 +00:00
{
2014-10-04 00:54:27 +00:00
QMessageBox msgBox;
SocketError enumError = error();
QString errorString;
bool relevantError = false;
switch (enumError)
{
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::ConnectionRefusedError: /**/
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("ConnectionRefusedError");
//The connection was refused by the peer (or timed out).
relevantError = true;
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::RemoteHostClosedError: /**/
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("RemoteHostClosedError");
//The remote host closed the connection
if (isConnectedToNetwork()) //we can reconnect
2014-09-18 02:18:33 +00:00
{
2014-10-10 15:20:33 +00:00
reConnectionFlag = true;
2014-09-18 02:18:33 +00:00
}
2014-10-04 00:54:27 +00:00
else
relevantError = true;
break;
case QAbstractSocket::SocketError::HostNotFoundError: /**/
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("HostNotFoundError");
//The host address was not found.
relevantError = true;
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::SocketAccessError: /**/
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("SocketAccessError");
//The socket operation failed because the application lacked the required privileges.
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::SocketTimeoutError: /**/
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("SocketTimeoutError");
//The socket operation timed out.
if (isConnected()); //ignore it if connected.
else
relevantError = true;
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::NetworkError: /**/
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("NetworkError");
//An error occurred with the network (e.g., the network cable was accidentally plugged out).
if (isConnectedToNetwork()) //we can reconnect
2014-09-18 02:18:33 +00:00
{
}
2014-10-04 00:54:27 +00:00
else
relevantError = true;
break;
case QAbstractSocket::SocketError::SslHandshakeFailedError: /**/
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("SslHandshakeFailedError");
relevantError = true;
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::SslInternalError: /**/
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("SslInternalError");
relevantError = true;
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::SslInvalidUserDataError: /**/
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("SslInvalidUserDataError");
relevantError = true;
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::DatagramTooLargeError: //not relevant to us
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("DatagramTooLargeError");
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::SocketResourceError: //not relevant to us
2014-10-04 00:54:27 +00:00
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::OperationError: //not relevant, except for debug
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("OperationError");
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::AddressInUseError: //not relevant to us
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("AddressInUseError");
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::SocketAddressNotAvailableError: //not relevant to us
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("SocketAddressNotAvailableError");
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::UnsupportedSocketOperationError: //for very old computers, not relevant to us
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("UnsupportedSocketOperationError");
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::ProxyAuthenticationRequiredError: //not relevant to us
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("ProxyAuthenticationRequiredError");
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::ProxyConnectionRefusedError: //not relevant to us
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("ProxyConnectionRefusedError");
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::UnfinishedSocketOperationError: //not relevant to us
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("UnfinishedSocketOperationError");
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::ProxyConnectionClosedError: //not relevant to us
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("ProxyConnectionClosedError");
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::ProxyConnectionTimeoutError: //not relevant to us
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("ProxyConnectionTimeoutError");
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::ProxyNotFoundError: //not relevant to us
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("ProxyNotFoundError");
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::ProxyProtocolError: //not relevant to us
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("ProxyProtocolError");
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::TemporaryError: //not relevant to us
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("TemporaryError");
break;
2014-09-18 02:18:33 +00:00
case QAbstractSocket::SocketError::UnknownSocketError: //not relevant, except for debug
2014-10-04 00:54:27 +00:00
errorString = QObject::tr("UnknownSocketError");
relevantError = true;
break;
}
2014-10-04 00:54:27 +00:00
if (relevantError) //informative string to be shown
{
2014-10-04 00:54:27 +00:00
qDebug() << Q_FUNC_INFO << "relevant error.";
msgBox.setIcon(QMessageBox::Warning);
msgBox.setText(errorString);
msgBox.exec();
}
}
/**
* @brief jceSSLClient::checkErrors this function exctuing when socket error has occured
* @param a includes the error enum from QAbstractSocket::SocketError enum list
*/
void jceSSLClient::checkErrors(QAbstractSocket::SocketError a)
2014-09-08 15:54:52 +00:00
{
2014-10-04 00:54:27 +00:00
//ignore this stupid error
bool timeout = (a == QAbstractSocket::SocketError::SocketTimeoutError);
if (!((isConnected()) && (timeout)))
{
2014-10-04 00:54:27 +00:00
qWarning() << Q_FUNC_INFO << "isOnline?: " << isConnectedToNetwork();
qWarning() << Q_FUNC_INFO << "state is: " << state();
qWarning() << Q_FUNC_INFO << "Var Error: " << a;
qWarning() << Q_FUNC_INFO << "Error: " << errorString();
}
2014-10-10 15:20:33 +00:00
else if (!readingFlag)
{
2014-10-10 15:20:33 +00:00
qWarning() << Q_FUNC_INFO << "isConnected?: " << isConnected() << "is timeout?" << timeout;
qWarning() << Q_FUNC_INFO << "isOnline?: " << isConnectedToNetwork() << "state is: " << state();
2014-10-04 00:54:27 +00:00
qWarning() << Q_FUNC_INFO << "Error: " << errorString();
2014-10-10 15:20:33 +00:00
}
else
{
//timeout when reading
}
2014-10-04 00:54:27 +00:00
showIfErrorMsg();
}
/** written by KARAN BALKAR
* @brief jceSSLClient::isConnectedToNetwork
2014-10-10 15:20:33 +00:00
*
* @return
*/
bool jceSSLClient::isConnectedToNetwork(){
2014-10-04 00:54:27 +00:00
QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
bool result = false;
2014-10-04 00:54:27 +00:00
for (int i = 0; i < ifaces.count(); ++i)
2014-09-18 02:18:33 +00:00
{
2014-10-04 00:54:27 +00:00
QNetworkInterface iface = ifaces.at(i);
2014-10-04 00:54:27 +00:00
if ( iface.flags().testFlag(QNetworkInterface::IsUp) && !iface.flags().testFlag(QNetworkInterface::IsLoopBack))
for (int j=0; j < iface.addressEntries().count(); ++j)
// got an interface which is up, and has an ip address
if (result == false)
result = true;
2014-09-18 02:18:33 +00:00
}
2014-10-04 00:54:27 +00:00
return result;
2014-09-08 15:54:52 +00:00
}