Index: sources/wifi/WifiInterface.cpp =================================================================== diff -u -r60db0ce19666f04ea58992a7670497d83f9bf7c4 -r13ac42cf8bdc5038dedd3302ba79dc387e5704b4 --- sources/wifi/WifiInterface.cpp (.../WifiInterface.cpp) (revision 60db0ce19666f04ea58992a7670497d83f9bf7c4) +++ sources/wifi/WifiInterface.cpp (.../WifiInterface.cpp) (revision 13ac42cf8bdc5038dedd3302ba79dc387e5704b4) @@ -4,6 +4,7 @@ #include #include #include +#include // Project #include "main.h" @@ -15,18 +16,26 @@ WifiInterface::WifiInterface(QObject *parent) : QObject(parent) { _processScan.setParent(this); + _processDisconnectNetwork.setParent(this); _processReadIPSettings.setParent(this); _processReadGateway.setParent(this); _processReadDNS.setParent(this); _processGenerateWPASupplicant.setParent(this); _processStartWPASupplicant.setParent(this); - _processRequestAutoAssignedIP.setParent(this); + _processRequestAutoAssignedIP.setParent(this); + _processSetStaticIPAddress.setParent(this); + _processSetStaticGateway.setParent(this); + _processSetStaticSubnetMask.setParent(this); + _processSetStaticDNS.setParent(this); } void WifiInterface::initConnections() { + connect(this, SIGNAL(didStatusChanged(const QString)), + this, SLOT(onStatusChanged(const QString))); + connect(this, SIGNAL(didError(const QString)), - this, SLOT(onLogFailure(const QString))); + this, SLOT(onStatusChanged(const QString))); connect(&_processScan, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onProcessFinishedScan(int,QProcess::ExitStatus))); @@ -48,6 +57,25 @@ connect(&_processRequestAutoAssignedIP, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onProcessFinishedRequestAutoAssignedIP(int,QProcess::ExitStatus))); + + connect(&_processDisconnectNetwork, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(onProcessFinishedDisconnectNetwork(int,QProcess::ExitStatus))); + + connect(this, SIGNAL(didRequestAutoAssignedIP()), + this, SLOT(onRequestAutoAssignedIP())); + + // static ip address connections + connect(&_processSetStaticIPAddress, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(onProcessFinishedSetIPAddress(int,QProcess::ExitStatus))); + + connect(&_processSetStaticGateway, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(onProcessFinishedSetGateway(int,QProcess::ExitStatus))); + + connect(&_processSetStaticSubnetMask, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(onProcessFinishedSetSubnetMask(int,QProcess::ExitStatus))); + + connect(&_processSetStaticDNS, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(onProcessFinishedSetDNS(int,QProcess::ExitStatus))); } /*! @@ -93,8 +121,9 @@ { // coco begin validated: Application termination is not correctly done in coco!!! // it has been tested and works perfectly fine in normal run. - quitThread(); // validated + quitThread(); } +// coco end /*! * \brief MessageAcknowModel::quitThread @@ -109,7 +138,7 @@ if (!_thread) return; // runs in thread - moveToThread(qApp->thread()); // validated + moveToThread(qApp->thread()); } // coco end @@ -206,7 +235,7 @@ * \param vRightDelim - (QString) the right delimiter * \return (QString) the text between the delimiters if found, "" otherwise */ -QString getTextBetweenDelimiters(const QString &vText, const QString &vLeftDelim, const QString &vRightDelim) +QString WifiInterface::getTextBetweenDelimiters(const QString &vText, const QString &vLeftDelim, const QString &vRightDelim) { QString result = ""; QString rightHalf = ""; @@ -226,50 +255,71 @@ * * \param vOutput - (QString) output collected from QProcess execution */ -void WifiInterface::parseWifiScan(const QString &vOutput) +QList WifiInterface::parseWifiScan(const QString &vOutput) { LOG_DEBUG(QString("WifiInterface::%1 %2").arg(__FUNCTION__).arg(QThread::currentThread()->objectName())); QList networks; - QStringList temp = vOutput.split("Cell"); - const QString signalLevelSearchTerm = "Signal level="; - const QString macAddressSearchTerm = "Address:"; - const QString ssidSearchTerm = "ESSID:"; - const QString groupCipherSearchTerm = "Group Cipher"; - const QString authSuitesSearchTerm = "Authentication Suites"; + QString outputNoReturns = vOutput; + outputNoReturns = outputNoReturns.replace("\r", ""); + QStringList temp = outputNoReturns.split("Cell"); + const QString searchTermSignalLevel = "Signal level="; + const QString searchTermMacAddress = "Address:"; + const QString searchTermSSID = "ESSID:"; - for (const QString &line : temp) + for (const QString &cell : temp) { - if (line.contains(ssidSearchTerm) && line.contains(macAddressSearchTerm) && line.contains(signalLevelSearchTerm)) + if (cell.contains(searchTermSSID) && cell.contains(searchTermMacAddress) && cell.contains(searchTermSignalLevel)) { - QString ssid = getTextBetweenDelimiters(line, ssidSearchTerm, "\n").replace("\"", "").trimmed(); - QString macAddress = getTextBetweenDelimiters(line, macAddressSearchTerm, "\n").trimmed(); - int signalLevel = getTextBetweenDelimiters(line, signalLevelSearchTerm, "dBm").trimmed().toInt(); + QString ssid = getTextBetweenDelimiters(cell, searchTermSSID, "\n").replace("\"", "").trimmed(); + if (ssid == "") + continue; + QString macAddress = getTextBetweenDelimiters(cell, searchTermMacAddress, "\n").trimmed(); + int signalLevel = getTextBetweenDelimiters(cell, searchTermSignalLevel, "dBm").trimmed().toInt(); + QList securityTypes; + bool requiresKey = QRegularExpression("Encryption key:on").match(cell).hasMatch(); - bool isCCMP = getTextBetweenDelimiters(line, groupCipherSearchTerm, "\n").contains("CCMP"); - bool isEnterprise = getTextBetweenDelimiters(line, authSuitesSearchTerm, "\n").contains("802.1x"); - bool isPersonal = getTextBetweenDelimiters(line, authSuitesSearchTerm, "\n").contains("PSK"); + QStringList infoElement = cell.split("IE: "); + if (infoElement.length() > 1) + { + QString element = infoElement[1]; + bool isWPA2 = QRegularExpression(".*WPA2 ").match(element).hasMatch(); + bool isWPA = QRegularExpression(".*WPA ").match(element).hasMatch(); + bool supportsAES = QRegularExpression("Pairwise Ciphers.*CCMP").match(element).hasMatch(); + bool requiresPSK = QRegularExpression("Authentication Suites.*PSK").match(element).hasMatch(); + bool supportsTKIP = QRegularExpression("Pairwise Ciphers.*TKIP").match(element).hasMatch(); - Network::SECURITY_LEVEL securityLevel = Network::SECURITY_LEVEL::UNSUPPORTED; + Network::SECURITY_TYPE securityType = Network::SECURITY_TYPE::UNSUPPORTED; - if (isPersonal && isCCMP) - securityLevel = Network::SECURITY_LEVEL::WPA2_AES_PERSONAL; - else if (isEnterprise && isCCMP) - securityLevel = Network::SECURITY_LEVEL::WPA2_AES_ENTERPRISE; - // TODO: Add support for the other security levels + if (isWPA2 && requiresPSK && supportsAES && !supportsTKIP) + securityType = Network::SECURITY_TYPE::WPA2_AES; + else if (isWPA && requiresPSK && supportsAES && supportsTKIP) + securityType = Network::SECURITY_TYPE::WPA_TKIP_AES; + else if (isWPA && requiresPSK && supportsTKIP) + securityType = Network::SECURITY_TYPE::WPA_TKIP; + else if (isWPA && requiresPSK && supportsAES) + securityType = Network::SECURITY_TYPE::WPA_AES; + else if (!isWPA && !isWPA2 && !requiresPSK && !supportsAES && !supportsTKIP && requiresKey) + securityType = Network::SECURITY_TYPE::WEP; - Network network(macAddress,ssid, securityLevel, Network::STATUS::NOT_CONNECTED, signalLevel); + if (securityType != Network::SECURITY_TYPE::UNSUPPORTED) + securityTypes.append(securityType); + } + + Network network(macAddress, ssid, securityTypes, Network::STATUS::NOT_CONNECTED, signalLevel); + networks.append(network); emit didAddNetwork(network); } } LOG_DEBUG(QString("WifiInterface::%1 Finished").arg(__FUNCTION__)); + return networks; } /*! - * \brief WifiInterface::onLogFailure - * Ensures any failures reported are logged - * \param vMessage (QString) the message detail of the failure + * \brief WifiInterface::onStatusChanged + * Ensures any status changes are logged + * \param vMessage (QString) the message detail */ -void WifiInterface::onError(const QString &vMessage) +void WifiInterface::onStatusChanged(const QString &vMessage) { LOG_DEBUG(vMessage); } @@ -292,10 +342,26 @@ .arg(_processGenerateWPASupplicant.objectName())); return; } + QString securityType; + if (vNetwork.securityTypes().contains(Network::SECURITY_TYPE::WPA2_AES)) + securityType = "wpa2"; + else if (vNetwork.securityTypes().contains(Network::SECURITY_TYPE::WPA_TKIP_AES) + || vNetwork.securityTypes().contains(Network::SECURITY_TYPE::WPA_AES) + || vNetwork.securityTypes().contains(Network::SECURITY_TYPE::WPA_TKIP)) + securityType = "wpa"; + else if (vNetwork.securityTypes().contains(Network::SECURITY_TYPE::WEP)) + securityType = "wep"; + else + { + LOG_DEBUG(QString("Network %1 has an unsupported security type.").arg(vNetwork.ssid())); + emit didError(QString("Network %1 has an unsupported security type.").arg(vNetwork.ssid())); + } + _processGenerateWPASupplicant.start(Wifi_Generate_WPA_Supplicant, QStringList() << vNetwork.ssid() << vPassword - << _wpaSupplicantConfPath); + << _wpaSupplicantConfPath + << securityType); } /*! @@ -306,6 +372,7 @@ */ void WifiInterface::onProcessFinishedGenerateWPASupplicant(int vExitCode, QProcess::ExitStatus vExitStatus) { + LOG_DEBUG(QString("WifiInterface::%1 %2").arg(__FUNCTION__).arg(QThread::currentThread()->objectName())); Q_UNUSED(vExitStatus) if (vExitCode != 0) { @@ -333,19 +400,31 @@ */ void WifiInterface::onProcessFinishedStartWPASupplicant(int vExitCode, QProcess::ExitStatus vExitStatus) { + LOG_DEBUG(QString("WifiInterface::%1 %2").arg(__FUNCTION__).arg(QThread::currentThread()->objectName())); Q_UNUSED(vExitStatus) if (vExitCode != 0) { emit didError("Could not configure network."); return; } + emit didRequestAutoAssignedIP(); +} + +/*! + * \brief WifiInterface::onRequestAutoAssignedIP + * Handles the request for an auto assigned IP address + */ +void WifiInterface::onRequestAutoAssignedIP() +{ + LOG_DEBUG(QString("WifiInterface::%1 %2").arg(__FUNCTION__).arg(QThread::currentThread()->objectName())); if (_processRequestAutoAssignedIP.state() != QProcess::NotRunning) { LOG_DEBUG(QString("Rejecting request for %1. %2 is already running.") .arg(__FUNCTION__) .arg(_processRequestAutoAssignedIP.objectName())); return; } + emit didStatusChanged(tr("Obtaining IP Address...")); _processRequestAutoAssignedIP.start(Wifi_Get_Auto_Assigned_IP, QStringList() << _iface); } @@ -358,12 +437,22 @@ */ void WifiInterface::onProcessFinishedRequestAutoAssignedIP(int vExitCode, QProcess::ExitStatus vExitStatus) { + LOG_DEBUG(QString("WifiInterface::%1 %2").arg(__FUNCTION__).arg(QThread::currentThread()->objectName())); Q_UNUSED(vExitStatus) if (vExitCode != 0) { - emit didError(QString("Could not connect to %1").arg(_network.ssid())); + if (_dhcpAttemptsLeft > 0) + { + _dhcpAttemptsLeft--; + emit didRequestAutoAssignedIP(); + } else + { + emit didError(QString("Could not connect to %1").arg(_network.ssid())); + _dhcpAttemptsLeft = 5; + } return; } + _dhcpAttemptsLeft = 5; doRequestIPSettings(); } @@ -394,6 +483,7 @@ */ void WifiInterface::onProcessFinishedReadIP(int vExitCode, QProcess::ExitStatus vExitStatus) { + LOG_DEBUG(QString("WifiInterface::%1 %2").arg(__FUNCTION__).arg(QThread::currentThread()->objectName())); Q_UNUSED(vExitCode); Q_UNUSED(vExitStatus); QString output = _processReadIPSettings.readAllStandardOutput(); @@ -419,6 +509,7 @@ */ void WifiInterface::onProcessFinishedReadGateway(int vExitCode, QProcess::ExitStatus vExitStatus) { + LOG_DEBUG(QString("WifiInterface::%1 %2").arg(__FUNCTION__).arg(QThread::currentThread()->objectName())); Q_UNUSED(vExitCode); Q_UNUSED(vExitStatus); _network.mIPSettings.mGateway = parseGateway(_processReadGateway.readAllStandardOutput()); @@ -456,13 +547,15 @@ { LOG_DEBUG(QString("WifiInterface::%1 %2").arg(__FUNCTION__).arg(QThread::currentThread()->objectName())); LOG_DEBUG(QString("Disconnecting from Network %1").arg(vNetwork.ssid())); - QProcess process; - process.start(Wifi_Disconnect_Network, + if (_processDisconnectNetwork.state() != QProcess::NotRunning) + { + LOG_DEBUG(QString("Rejecting request for %1. %2 is already running.") + .arg(__FUNCTION__) + .arg(_processDisconnectNetwork.objectName())); + return; + } + _processDisconnectNetwork.start(Wifi_Disconnect_Network, QStringList() << _iface); - if (process.waitForFinished(_defaultTimeout)) - emit didDisconnectNetwork(vNetwork); - process.kill(); - emit didError(tr("Failed to disconnect from %1").arg(vNetwork.ssid())); } /*! @@ -491,9 +584,9 @@ */ QString WifiInterface::parseIP(const QString &vOutput) { - if (vOutput.contains("inet addr:") && vOutput.contains("Bcast:")) - return vOutput.split("inet addr:")[1].split("Bcast:")[0].trimmed(); - return ""; + const QString leftDelim = "inet addr:"; + const QString rightDelim = "Bcast:"; + return getTextBetweenDelimiters(vOutput, leftDelim, rightDelim); } /*! @@ -504,9 +597,9 @@ */ QString WifiInterface::parseBroadcast(const QString &vOutput) { - if (vOutput.contains("Bcast:") && vOutput.contains("Mask:")) - return vOutput.split("Bcast:")[1].split("Mask:")[0].trimmed(); - return ""; + const QString leftDelim = "Bcast:"; + const QString rightDelim = "Mask:"; + return getTextBetweenDelimiters(vOutput, leftDelim, rightDelim); } /*! @@ -517,9 +610,9 @@ */ QString WifiInterface::parseSubnetMask(const QString &vOutput) { - if (vOutput.contains("Mask:")) - return vOutput.split("Mask:")[1].trimmed(); - return ""; + const QString leftDelim = "Mask:"; + const QString rightDelim = "\n"; + return getTextBetweenDelimiters(vOutput, leftDelim, rightDelim); } /*! @@ -530,9 +623,9 @@ */ QString WifiInterface::parseGateway(const QString &vOutput) { - if (vOutput.contains("default via")) - return vOutput.split("default via")[1].split("dev")[0].trimmed(); - return ""; + const QString leftDelim = "default via"; + const QString rightDelim = "dev"; + return getTextBetweenDelimiters(vOutput, leftDelim, rightDelim); } /*! @@ -543,7 +636,103 @@ */ QString WifiInterface::parseDNS(const QString &vOutput) { - if (vOutput.contains("nameserver")) - return vOutput.split("nameserver")[1].split("\n")[0].trimmed(); - return ""; + const QString leftDelim = "nameserver"; + const QString rightDelim = "\n"; + return getTextBetweenDelimiters(vOutput, leftDelim, rightDelim); } + +/*! + * \brief WifiInterface::doRequestSetIPAddress + * Issues command to set a static IP address + * \param vIPAddress - (QString) the IP address + */ +void WifiInterface::doRequestSetIPAddress(const QString &vIPAddress) +{ + Q_UNUSED(vIPAddress) + // TODO +} + +/*! + * \brief WifiInterface::onProcessFinishedSetIPAddress + * Called when settings a static IP address finishes + * \param vExitCode - (int) the exit code + * \param vExitStatus - (QProcess::ExitStatus) the exit status + */ +void WifiInterface::onProcessFinishedSetIPAddress(int vExitCode, QProcess::ExitStatus vExitStatus) +{ + Q_UNUSED(vExitCode) + Q_UNUSED(vExitStatus) + // TODO +} + +/*! + * \brief WifiInterface::doRequestSetGateway + * Issues command to set a static gateway + * \param vGateway - (QString) the gateway + */ +void WifiInterface::doRequestSetGateway(const QString &vGateway) +{ + Q_UNUSED(vGateway) + // TODO +} + +/*! + * \brief WifiInterface::onProcessFinishedSetGateway + * Called when the the process to set the gateway has finished + * \param vExitCode - (int) the exit code + * \param vExitStatus - (QProcess::ExitStatus) the exit status + */ +void WifiInterface::onProcessFinishedSetGateway(int vExitCode, QProcess::ExitStatus vExitStatus) +{ + Q_UNUSED(vExitCode) + Q_UNUSED(vExitStatus) + // TODO +} + +/*! + * \brief WifiInterface::doRequestSetSubnetMask + * Issues command to set the subnet mask + * \param vSubnetMask - (QString) the subnet mask + */ +void WifiInterface::doRequestSetSubnetMask(const QString &vSubnetMask) +{ + Q_UNUSED(vSubnetMask) + // TODO +} + +/*! + * \brief WifiInterface::onProcessFinishedSetSubnetMask + * Called when the process to set the subnet mask finishes + * \param vExitCode - (int) the exit code + * \param vExitStatus - (QProcess::ExitStatus) the exit status + */ +void WifiInterface::onProcessFinishedSetSubnetMask(int vExitCode, QProcess::ExitStatus vExitStatus) +{ + Q_UNUSED(vExitCode) + Q_UNUSED(vExitStatus) + // TODO +} + +/*! + * \brief WifiInterface::doRequestSetDNS + * Issues a command to set the DNS + * \param vDNS - (QString) the DNS + */ +void WifiInterface::doRequestSetDNS(const QString &vDNS) +{ + Q_UNUSED(vDNS) + // TODO +} + +/*! + * \brief WifiInterface::onProcessFinishedSetDNS + * Called when the process that finishes setting the DNS completes + * \param vExitCode - (int) the exit code + * \param vExitStatus - (QProcess::ExitStatus) the exit status + */ +void WifiInterface::onProcessFinishedSetDNS(int vExitCode, QProcess::ExitStatus vExitStatus) +{ + Q_UNUSED(vExitCode) + Q_UNUSED(vExitStatus) + // TODO +}