#include <QMap>
#include <QtNetwork>
#include <QProcess>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
#include <sysfs/libsysfs.h>
#include "logreceiver.h"
#include <qlocalserver.h>
#include <qlocalsocket.h>
#include "status.h"
#include "dhcp.h"
LogReceiver::LogReceiver() {
server = new QLocalServer(this);
}
LogReceiver::~LogReceiver() {
}
void LogReceiver::initAndRun(QString serverPath, QString pathToExe,
QStringList* args) {
if (serverPath != DEFAULT_QTSOCKETADDRESS) {
dhcpcdArguments.append("-q");
dhcpcdArguments.append(serverPath);
}
if (!server->listen(serverPath)) {
/*
QMessageBox::critical(this, tr("LogReceiver"), tr(
"Unable to start the server: %1.") .arg(server->errorString()));
close();
*/
// emit signal to the gui that a critial error occoured
qDebug() << "--- \t [LogReceiver::initAndRun] Unable to start server:"
<< server->errorString();
return;
}
connect(server, SIGNAL(newConnection()), this, SLOT(handleNewConnection()));
pathToDhcpcdExe = pathToExe;
if (args != NULL && !args->isEmpty()) {
qDebug() << "--- \t [LogReceiver::initAndRun] added additional args";
dhcpcdArguments.append(*args);
}
numberOfProcesses = 0;
// start the main work:
QList<QString> 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;
}
}
QList<QString> LogReceiver::getListOfNetworkInterfaces() {
QList<QNetworkInterface> nIList = QNetworkInterface::allInterfaces();
QList<QString> 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 addNewInterface(nI.humanReadableName());
}
} else {
qDebug() << "no interfaces found!";
}
return result;
}
QList<QString> LogReceiver::checkCarrierState(QList<QString> &interfaces) {
QList<QString> 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 LogReceiver::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 LogReceiver::runDHCPCD(QList<QString> &interfaces) {
foreach(QString nI, interfaces) {
runDHCPCD(nI);
}
}
void LogReceiver::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();
}
void LogReceiver::checkInternetConnection(QString ifName) {
QString command("ping");
QStringList argList;
QString timeout("1");
QString total("2");
int exitCode = -1;
QString destination("www.google.de");
argList << "-I" << "ifName" << "-W" << timeout << "-c" << total
<< destination;
argList.replace(1, ifName);
QProcess * p = new QProcess(this);
p->start(command, argList);
p->waitForFinished();
exitCode = p->exitCode();
if (exitCode > 0) {
qDebug() << "no internet connection with interface" << ifName;
//remove interface from list and inform user via debug console
emit updateStatusLabel(ifName, "connection not possible");
} else if (exitCode == 0) {
qDebug() << "internet: check passed! for interface" << ifName;
emit updateStatusLabel(ifName, "connection possible");
emit connectionEstablished(ifName);
}
}
void LogReceiver::checkInternetConnection(QList<QString> &interfaces) {
foreach(QString nI, interfaces)
{
checkInternetConnection(nI);
}
}
void LogReceiver::checkInternetConnectionViaTCP(QString ifName) {
const bool canStartIAP = (configurationManager.capabilities()
& QNetworkConfigurationManager::CanStartAndStopInterfaces);
QList<QNetworkConfiguration> configs =
configurationManager.allConfigurations();
QNetworkConfiguration cfg;
foreach(QNetworkConfiguration nC, configs)
{
if (nC.name() == ifName) {
qDebug() << "found config" << nC.name();
cfg = nC;
break;
}
}
if (!cfg.isValid() || (!canStartIAP && cfg.state()
!= QNetworkConfiguration::Active)) {
qDebug() << "config is not valid" << cfg.name();
return;
}
QNetworkSession *session = new QNetworkSession(cfg, this);
session->open();
if (session->waitForOpened(-1)) {
QTcpSocket *tcpSocket = new QTcpSocket(this);
tcpSocket->connectToHost(QString("209.85.148.105"), 80);
if (!tcpSocket->waitForConnected()) {
qDebug() << tcpSocket->errorString();
emit updateStatusLabel(ifName, "connection not possible");
} else {
emit updateStatusLabel(ifName, "connection possible");
emit connectionEstablished(ifName);
}
}
else {
qDebug() << "couldn't open session";
}
session->close();
}
void LogReceiver::handleNewConnection() {
qDebug() << "New Connection arrived";
QLocalSocket * client = server ->nextPendingConnection();
clients.insert(client, client);
connect(client, SIGNAL(disconnected()), client, SLOT(deleteLater()));
connect(client, SIGNAL(readyRead()), this, SLOT(handleNewInput()));
}
void LogReceiver::handleNewInput() {
QObject* sender = const_cast<QObject*> (QObject::sender());
QLocalSocket* socket = static_cast<QLocalSocket*> (sender);
QLocalSocket * client = clients.value(socket);
QString data(client->readAll());
data = data.trimmed();
QStringList lines = data.split("\n");
for (int i=0; i < lines.length(); i++) {
handleNewInputLine(lines.at(i));
}
}
void LogReceiver::handleNewInputLine(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;
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 stat_error";
break;
default:
qDebug() << logMsg;
}
}
void LogReceiver::handleProcessFinished(int exitCode,
QProcess::ExitStatus exitStatus) {
QProcess* p = qobject_cast<QProcess * >(QObject::sender());
QString ifName = clientProcessToIfNameMap.value(p,"ifName");
if(ifName.compare("ifName") == 0) {
qDebug() << "--- \t [LogReceiver::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 connction";
emit updateStatusLabel(ifName, "check connectivity");
//checkInternetConnection(ifName);
checkInternetConnectionViaTCP(ifName);
}
}
numberOfProcesses = numberOfProcesses -1;
if (numberOfProcesses <= 0) {
emit allProcessesFinished();
}
}
void LogReceiver::handleProcessStarted() {
QProcess* p = qobject_cast<QProcess * >(QObject::sender());
QString ifName = clientProcessToIfNameMap.value(p,"ifName");
qDebug() << "process started for interface:" << ifName;
}
bool LogReceiver::checkBlackList(QString i) {
if (i.startsWith("v", Qt::CaseInsensitive)) {
return true;
}
else if(i.startsWith("d", Qt::CaseInsensitive)) {
return true;
}
else {
return false;
}
}