From 0216e9aadb7e794037d3cf553b05474de8322a74 Mon Sep 17 00:00:00 2001 From: Niklas Date: Fri, 23 Sep 2011 14:08:55 +0200 Subject: renamed the logreceiver to networkdiscovery and deleted the abortbootdialog and chooseinterfacedialog since this is now implemented via html/css/jquery --- LogReceiver/networkdiscovery.cpp | 518 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 518 insertions(+) create mode 100644 LogReceiver/networkdiscovery.cpp (limited to 'LogReceiver/networkdiscovery.cpp') diff --git a/LogReceiver/networkdiscovery.cpp b/LogReceiver/networkdiscovery.cpp new file mode 100644 index 0000000..cd77ee1 --- /dev/null +++ b/LogReceiver/networkdiscovery.cpp @@ -0,0 +1,518 @@ +#include "networkdiscovery.h" + +#include "../common/fbgui.h" + +NetworkDiscovery::NetworkDiscovery(QObject *parent) { + + server = new QLocalServer(this); +} + +NetworkDiscovery::~NetworkDiscovery() { + +} + +void NetworkDiscovery::initAndRun(QString serverPath, QString pathToExe, + QStringList* args) { + + _userChoice = false; + _blocked = false; + + if (serverPath != DEFAULT_QTSOCKETADDRESS) { + dhcpcdArguments.append("-q"); + dhcpcdArguments.append(serverPath); + } + if (!server->listen(serverPath)) { + /* + QMessageBox::critical(this, tr("NetworkDiscovery"), tr( + "Unable to start the server: %1.") .arg(server->errorString())); + close(); + */ + // emit signal to the gui that a critial error occoured + QString errorInfo("Unable to start server: "); + qDebug() << "--- \t [NetworkDiscovery::initAndRun] " + errorInfo + << server->errorString(); + emit + abortBoot(errorInfo + server->errorString()); + return; + } + + connect(server, SIGNAL(newConnection()), this, SLOT(handleNewConnection())); + + pathToDhcpcdExe = pathToExe; + // check if the path to the customdhcpcd file is correct + QFileInfo fInfo(pathToDhcpcdExe); + if (!fInfo.exists()) { + qDebug() + << "couldn't find customdhcpcd exe. Please check the path to this file."; + emit + abortBoot( + "couldn't find customdhcpcd exe. Please check the path to this file."); + return; + } + + if (args != NULL && !args->isEmpty()) { + qDebug() << "--- \t [NetworkDiscovery::initAndRun] added additional args"; + dhcpcdArguments.append(*args); + } + + numberOfProcesses = 0; + + // start the main work: + + QList list = getListOfNetworkInterfaces(); + + if (list.size() > 0) { + + //list = checkCarrierState(list); + + + //dhcpcdArguments.append("-d"); + QString ifName("eth0"); + numberOfProcesses = list.size(); + runDHCPCD(list); + } else { + qDebug() << "list is empty. Haven't found usable interface."; + emit + abortBoot("Haven't found usable interface"); + return; + } + +} + +int NetworkDiscovery::replaceDefaultRoute(QString &ifName, QString &gateway, int af, int mss) { + rm.replaceDefaultRoute(ifName, gateway, mss, AF_INET); +} + +QList NetworkDiscovery::getListOfNetworkInterfaces() { + QList nIList = QNetworkInterface::allInterfaces(); + QList result; + + if (nIList.size() > 0) { + foreach(QNetworkInterface nI, nIList) + { + if (((!(nI.flags() & QNetworkInterface::CanBroadcast) + || nI.flags() & QNetworkInterface::IsLoopBack) + || nI.flags() & QNetworkInterface::IsPointToPoint) + || checkBlackList(nI.humanReadableName())) { + continue; + } + if (!checkCarrierState(nI.humanReadableName())) { + continue; + } + result.append(nI.humanReadableName()); + emit addInterface(nI.humanReadableName()); + } + } else { + qDebug() << "no interfaces found!"; + } + return result; +} + +QList NetworkDiscovery::checkCarrierState(QList &interfaces) { + QList result; + foreach(QString nI, interfaces) + { + if (checkCarrierState(nI)) { + // everything is fine, cable is plugged, + // go on with the next interface + //continue; + result.append(nI); + } + } + return result; +} + +bool NetworkDiscovery::checkCarrierState(QString interface) { + + qDebug() << "check carrier state for interface " << interface; + QByteArray ba = interface.toAscii(); + const char * iface = ba.data(); + + struct sysfs_class_device *class_device = sysfs_open_class_device("net", + iface); + struct dlist *attrlist = sysfs_get_classdev_attributes(class_device); + if (attrlist != NULL) { + struct sysfs_attribute *attr = NULL; + dlist_for_each_data(attrlist, attr, struct sysfs_attribute) { + if (strcmp("carrier", attr->name) == 0) { + QString value(attr->value); + bool ok = false; + bool * pok = &ok; + int v = value.toInt(pok); + if (*pok) { + if (v == 1) { + qDebug() + << "carrier is 1. Cable is plugged. return true"; + return true; + } else { + qDebug() + << "carrier is 0. Cable is unplugged. return false"; + return false; + } + } else { + qDebug() << "conversion error"; + } + } + } + } else { + qDebug() << "attrlist is Null"; + } + sysfs_close_class_device(class_device); + + return true; +} + +void NetworkDiscovery::runDHCPCD(QList &interfaces) { + foreach(QString nI, interfaces) + { + runDHCPCD(nI); + } +} + +void NetworkDiscovery::runDHCPCD(QString interface) { + emit updateStatusLabel(interface, "start DHCP"); + dhcpcdArguments.append(interface); + QProcess * p = new QProcess(this); + + qDebug() << dhcpcdArguments; + + clientProcessToIfNameMap.insert(p, interface); + qDebug() << clientProcessToIfNameMap; + p->start(pathToDhcpcdExe, dhcpcdArguments); + connect(p, SIGNAL(started()), this, SLOT(handleProcessStarted())); + connect(p, SIGNAL(finished(int, QProcess::ExitStatus)), this, + SLOT(handleProcessFinished(int, QProcess::ExitStatus))); + dhcpcdArguments.removeLast(); +} + +bool NetworkDiscovery::checkConnectivity(QString ifName) { + int metric = 0; + + // get gateway address + QString pathToGatewayFile(DEFAULT_GATEWAY_INFO_LOCATION); + pathToGatewayFile += ifName; + interfaceconfiguration ifConf; + ifConf.readConfigOutOfFile(pathToGatewayFile); + + // replace default route + qDebug() << rm.replaceDefaultRoute(ifName, ifConf.getGateway(), 0, AF_INET); + + // check connectivity via tcp connection + QTcpSocket *tcpSocket = new QTcpSocket(this); + tcpSocket->connectToHost(QString("209.85.148.105"), 80); + if (!tcpSocket->waitForConnected(500)) { + qDebug() << "no internet connection with interface" << ifName; + qDebug() << tcpSocket->errorString(); + emit + updateStatusLabel(ifName, "connection not possible"); + return false; + } else { + qDebug() << "internet: check passed! for interface" << ifName; + emit updateStatusLabel(ifName, "connection possible"); + if (!_userChoice) { + // blockiere jeden weiteren check + // emite continueBoot + _blocked = true; + emit continueBoot(ifName, _userChoice); + } else { + emit connectionEstablished(&ifConf); + } + return true; + } +} + +/** + * + */ +void NetworkDiscovery::handleNewConnection() { + qDebug() << "New Connection arrived"; + + /*QLocalSocket **/ + client = server ->nextPendingConnection(); + clients.insert(client, client); + connect(client, SIGNAL(disconnected()), this, + SLOT(handleClientDisconnect())); + connect(client, SIGNAL(readyRead()), this, SLOT(handleNewInput())); +} + +/** + * + */ +void NetworkDiscovery::handleClientDisconnect() { + QLocalSocket* socket = qobject_cast (QObject::sender()); + + QLocalSocket * client = clients.value(socket); + + qDebug() << "disconnect client"; + handleNewInput(client); + client->deleteLater(); +} + +/** + * + */ +void NetworkDiscovery::handleNewInput(QLocalSocket * client) { + qDebug() << "last read before exit"; + while (client->canReadLine()) { + QString data(client->readLine()); + + data = data.trimmed(); + qDebug() << data; + QStringList lines = data.split("\n"); + + for (int i = 0; i < lines.length(); i++) { + handleNewInputLine(client, lines.at(i)); + } + } +} + +/** + * + * This method is connected to the readyRead Signal of the QLocalSocket + * client. + * send an ACK to the client with every received message. + */ +void NetworkDiscovery::handleNewInput() { + QLocalSocket* socket = qobject_cast (QObject::sender()); + + QLocalSocket * client = clients.value(socket); + QString data(client->read(DHCP_MESSAGE_SIZE)); + client->write("ACK", ACK_SIZE); + client->waitForBytesWritten(); + data = data.trimmed(); + //qDebug() << data; + QStringList lines = data.split("\n"); + + for (int i = 0; i < lines.length(); i++) { + handleNewInputLine(client, lines.at(i)); + } +} + +/** + * This Method processes the send messages. + * + * This Method processes the send messages. It splits the line + * into several components. Those components are: + * interface: interface name ==> indicates the process who send the message + * s_state: is the number representation of syslog.h LOG levels + * s_subState: is the number representation of the dhcp.c DHCP states (1 - 8) plus + * the status. h states (9 - ..) + * msg: is a message which can contain additional informations + * + * According to the s_state and s_subState we emit the changeProgressBarValue() signal + * with different values. + * + * @param client + * the client who send the message + * + * @param data + * the message. (format ;;; ) + */ +void NetworkDiscovery::handleNewInputLine(QLocalSocket * client, QString data) { + + QString logMsg(data); + QString interface = logMsg.section(";", 0, 0); + QString s_state = logMsg.section(";", 1, 1); + QString s_subState = logMsg.section(";", 2, 2); + QString msg = logMsg.section(";", 3, 3); + int st = s_state.trimmed().toInt(); + int sst = s_subState.trimmed().toInt(); + //qDebug() << logMsg; + + if (ifNameToClient.size() < numberOfProcesses && !ifNameToClient.contains( + interface)) { + ifNameToClient.insert(interface, client); + } + + switch (st) { + case LOG_INFO: + switch (sst) { + case DHCP_DISCOVER: + emit changeProgressBarValue(interface, 10); + break; + case DHCP_OFFER: + emit changeProgressBarValue(interface, 20); + break; + case DHCP_REQUEST: + emit changeProgressBarValue(interface, 30); + break; + case DHCP_ACK: + emit changeProgressBarValue(interface, 40); + break; + case DHCP_NAK: + emit changeProgressBarValue(interface, 40); + break; + case DHCPCD_ARP_TEST: + emit changeProgressBarValue(interface, 50); + break; + case DHCP_DECLINE: + emit changeProgressBarValue(interface, 60); + break; + case DHCP_RELEASE: + + break; + case DHCP_INFORM: + break; + case DHCPCD_CONFIGURE: + emit changeProgressBarValue(interface, 70); + break; + case DHCPCD_WRITE: + emit changeProgressBarValue(interface, 80); + break; + case DHCPCD_EXIT: + emit changeProgressBarValue(interface, 100); + break; + case DHCPCD_LOG: + + default: + break; + } + break; + case LOG_ERR: + qDebug() << "received error:" << msg; + break; + default: + //qDebug() << logMsg; + break; + } +} + +/** + * This Method is called when a process is finished. + * + * This Method is called when a process is finished. This slot is connected + * with the signal finished() of the QProcess class. + * If the process finishes, it will be checked if the process exited normal + * or if an unexpected error occurred. For this, we determine the sender (which is a + * QProcess), get the corresponding interface (which is stored in a map), and check + * the exitCode. Further actions are taken according to the exitCode check. + * Normal exit: + * emit changeProgressBar() to 100% + * emit updateStatusLabel() to check connection + * checkConnectivity() @see NetworkDiscovery::checkConnectivity() + * Unexpected exit: + * emit updateStatusLabel() to process exited unexpected + * TODO:: the reason for the unexpected exit should be presented in the logfile. + * + * @param exitCode + * + * @param exitStatus + * + * @return bool + * returns true: if the interface name i starts with a letter in the blacklist. + * + * returns false: else + * + * @see NetworkDiscovery::getListOfNetworkInterfaces() + */ +/* +void NetworkDiscovery::handleProcessFinished(int exitCode, + QProcess::ExitStatus exitStatus) { + QProcess* p = qobject_cast (QObject::sender()); + QString ifName = clientProcessToIfNameMap.value(p, "ifName"); + + if (ifName.compare("ifName") == 0) { + qDebug() + << "--- \t [NetworkDiscovery::handleProcessFinished] haven't found process!"; + } else { + qDebug() << "process for interface" << ifName << "finished" << exitCode + << exitStatus; + if (exitCode > 0) { + qDebug() << "process exited unexpected"; + emit updateStatusLabel(ifName, "process exited unexpected"); + } else { + qDebug() << "process normal exit"; + qDebug() << "check internet connection"; + emit + changeProgressBarValue(ifName, 100); + emit + updateStatusLabel(ifName, "check connectivity"); + checkConnectivity(ifName); + } + } + QLocalSocket *client = ifNameToClient.value(ifName, 0); + if (client != 0) { + handleNewInput(client); + } + numberOfProcesses = numberOfProcesses - 1; + if (numberOfProcesses <= 0) { + emit allProcessesFinished(); + } +} +*/ +void NetworkDiscovery::handleProcessFinished(int exitCode, + QProcess::ExitStatus exitStatus) { + + QProcess* p = qobject_cast (QObject::sender()); + QString ifName = clientProcessToIfNameMap.value(p, "ifName"); + if (!_blocked) { //_blocked becomes true, if _userChoice is false and we found a usable interface + if (ifName.compare("ifName") == 0) { + qDebug() + << "--- \t [NetworkDiscovery::handleProcessFinished] haven't found process!"; + } else { + qDebug() << "process for interface" << ifName << "finished" + << exitCode << exitStatus; + if (exitCode > 0) { + qDebug() << "process exited unexpected"; + emit updateStatusLabel(ifName, "process exited unexpected"); + } else { + qDebug() << "process normal exit"; + emit changeProgressBarValue(ifName, 100); + emit updateStatusLabel(ifName, "check connectivity"); + checkConnectivity(ifName); + } + } + if (!_blocked) { //_blocked becomes true, if _userChoice is false and we found a usable interface + QLocalSocket *client = ifNameToClient.value(ifName, 0); + if (client != 0) { + handleNewInput(client); + } + numberOfProcesses = numberOfProcesses - 1; + if (numberOfProcesses <= 0 && _userChoice) { + emit allProcessesFinished(); + } + } + } else { + qDebug() << "already blocked"; + emit updateStatusLabel(ifName, "finished DHCP"); + } +} +/** + * This Method is called when a process is started. + * + * This Method is called when a process is started. + * It prints the message: "process started for interface: ". + */ +void NetworkDiscovery::handleProcessStarted() { + QProcess* p = qobject_cast (QObject::sender()); + QString ifName = clientProcessToIfNameMap.value(p, "ifName"); + qDebug() << "process started for interface:" << ifName; +} + +/** + * This Method implements a blacklist. + * + * This Method implements a blacklist. We check the fist character + * of the interface name. if this letter is in the list, we return true. + * True means, that this interface won't be put into the result list of + * getListOfNetworkInterfaces(). + * + * @param i + * is a interface name. + * + * @return bool + * returns true: if the interface name i starts with a letter in the blacklist. + * + * returns false: else + * + * @see NetworkDiscovery::getListOfNetworkInterfaces() + */ +bool NetworkDiscovery::checkBlackList(QString i) { + if (i.startsWith("v", Qt::CaseInsensitive)) { + return true; + } else if (i.startsWith("d", Qt::CaseInsensitive)) { + return true; + } else { + return false; + } +} -- cgit v1.2.3-55-g7522