diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..98016b2 --- /dev/null +++ b/main.cpp @@ -0,0 +1,39 @@ +/***************************************************************************** +* mayu Mate Are You Up +* Copyright (C) 2018 Syping +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*****************************************************************************/ + +#include +#include +#include "mayu.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + a.setApplicationName("mayu"); + + QStringList arguments = a.arguments(); + arguments.removeAt(0); + + if (arguments.length() >= 2) { + mayu a_mayu; + a_mayu.setHostsFile(arguments.at(0)); + a_mayu.setJsonFile(arguments.at(1)); + a_mayu.work(); + return a_mayu.getResult(); + } + + return 0; +} diff --git a/mayu.cpp b/mayu.cpp new file mode 100644 index 0000000..4f34da1 --- /dev/null +++ b/mayu.cpp @@ -0,0 +1,233 @@ +/***************************************************************************** +* mayu Mate Are You Up +* Copyright (C) 2018 Syping +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "mayu.h" + +#include +using namespace std; + +extern "C" { +#include "oping.h" +} + +mayu::mayu(QObject *parent) : QObject(parent) +{ + p_return = -1; + p_tries = 4; +} + +void mayu::setHostsFile(const QString &fileName) +{ + p_hostsFile = fileName; + p_hostsParsed = false; +} + +void mayu::setHosts(const QStringList &hostsList) +{ + p_hostsList = hostsList; + p_hostsParsed = true; +} + +void mayu::setJsonFile(const QString &fileName) +{ + p_jsonFile = fileName; +} + +const QString mayu::getHostsFile() +{ + return p_hostsFile; +} + +const QStringList mayu::getHosts() +{ + return p_hostsList; +} + +const QString mayu::getJsonFile() +{ + return p_jsonFile; +} + +int mayu::getResult() +{ + return p_return; +} + +double mayu::ping(const QString &host, int tries, double timeout) +{ + double latency; + pingobj_t *pingObj; + pingobj_iter_t *pingIter; + if ((pingObj = ping_construct()) == NULL) { +#ifdef E_DEBUG + qDebug() << "Ping construction failed"; +#endif + return -1; + } + if (ping_setopt(pingObj, PING_OPT_TIMEOUT, (void*)(&timeout)) < 0) { +#ifdef E_DEBUG + qDebug() << "Setting timeout to" << timeout << "have failed"; +#endif + ping_destroy(pingObj); + return -1; + } + QHostAddress hostAddress(host); + if (QAbstractSocket::IPv4Protocol == hostAddress.protocol()) { + if (ping_host_add(pingObj, hostAddress.toString().toStdString().c_str()) < 0) { + ping_destroy(pingObj); + return -1; + } +#ifdef E_DEBUG + qDebug() << "IPv4 Address" << hostAddress.toString() << "found"; +#endif + } + else if (QAbstractSocket::IPv6Protocol == hostAddress.protocol()) { + if (ping_host_add(pingObj, hostAddress.toString().toStdString().c_str()) < 0) { + ping_destroy(pingObj); + return -1; + } +#ifdef E_DEBUG + qDebug() << "IPv6 Address" << hostAddress.toString() << "found"; +#endif + } + else { + QList hostAddresses = QHostInfo::fromName(host).addresses(); + if (hostAddresses.length() >= 1) { + QString ipStr = hostAddresses.at(0).toString(); + if (ping_host_add(pingObj, ipStr.toStdString().c_str()) < 0) { + ping_destroy(pingObj); + return -1; + } +#ifdef E_DEBUG + qDebug() << "Hostname" << host << "found and resolved" << ipStr; +#endif + } + else { +#ifdef E_DEBUG + qDebug() << "Hostname" << host << "not found"; +#endif + ping_destroy(pingObj); + return -1; + } + } + bool hostUp = false; + int curTry = 0; + while (!hostUp && curTry != tries) { + if (ping_send(pingObj) < 0) { +#ifdef E_DEBUG + qDebug() << "Pinging host" << host << " has failed"; +#endif + ping_destroy(pingObj); + return -1; + } + bool pingSuccess = false; + for (pingIter = ping_iterator_get(pingObj); pingIter != NULL; pingIter = + ping_iterator_next(pingIter)) { + char hostname[100]; + size_t len; + len = sizeof(double); + ping_iterator_get_info(pingIter, PING_INFO_LATENCY, &latency, &len); + pingSuccess = !(latency < 0); +#ifdef E_DEBUG + len = 100; + ping_iterator_get_info(pingIter, PING_INFO_HOSTNAME, hostname, &len); + qDebug() << hostname << latency << pingSuccess; +#endif + } + if (pingSuccess) { + hostUp = true; + } + curTry++; + } + ping_destroy(pingObj); + if (hostUp) + return latency; + return -1; +} + +void mayu::parse_hosts() +{ + p_hostsList.clear(); + /** + Drop here + **/ + QFile hostsFile(p_hostsFile); + if (hostsFile.open(QFile::ReadOnly)) { + const QList hostsArray = hostsFile.readAll().split('\n'); + for (const QByteArray &lineArray : hostsArray) { + QString lineStr = QString::fromUtf8(lineArray).trimmed(); + if (!lineStr.isEmpty()) { + QStringList lineStrList = lineStr.split(','); + QString hostStr; + QString alternativeStr; + if (lineStrList.length() >= 1) { + hostStr = lineStrList.at(0); + lineStrList.removeAt(0); + if (lineStrList.length() >= 1) { + alternativeStr = lineStrList.join(','); // Alternative Name in Future Version + } + p_hostsList += hostStr; + } + } + } + hostsFile.close(); + p_hostsParsed = true; + } + else + { + cerr << "Failed read hosts from " << p_hostsFile.toStdString().c_str(); + } + /** + Regain here + **/ +} + +void mayu::work() +{ + if (!p_hostsParsed) + parse_hosts(); + QJsonObject jsonObject; + const QStringList hostsList = getHosts(); + for (const QString &host : hostsList) { + double result = ping(host, p_tries); + jsonObject[host] = result; + } + QJsonDocument jsonDocument; + jsonDocument.setObject(jsonObject); + QByteArray jsonArray = jsonDocument.toJson(); + /** + Drop here + **/ + QSaveFile jsonFile(p_jsonFile); + if (jsonFile.open(QSaveFile::WriteOnly)) { + jsonFile.write(jsonArray); + if (!jsonFile.commit()) { + cerr << "Failed save result to " << p_jsonFile.toStdString().c_str(); + p_return = 1; + } + } + /** + Regain here + **/ + p_return = 0; +} diff --git a/mayu.h b/mayu.h new file mode 100644 index 0000000..e87096d --- /dev/null +++ b/mayu.h @@ -0,0 +1,53 @@ +/***************************************************************************** +* mayu Mate Are You Up +* Copyright (C) 2018 Syping +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*****************************************************************************/ + +#ifndef MAYU_H +#define MAYU_H + +#include +#include +#include +#include + +class mayu : public QObject +{ + Q_OBJECT +public: + explicit mayu(QObject *parent = nullptr); + void setHostsFile(const QString &fileName); + void setHosts(const QStringList &hostsList); + void setJsonFile(const QString &fileName); + const QString getHostsFile(); + const QStringList getHosts(); + const QString getJsonFile(); + int getResult(); + static double ping(const QString &host, int tries, double timeout = 2.5); + +public slots: + void parse_hosts(); + void work(); + +private: + QStringList p_hostsList; + QString p_hostsFile; + QString p_jsonFile; + bool p_hostsParsed; + int p_return; + int p_tries; +}; + +#endif // MAYU_H diff --git a/mayu.pro b/mayu.pro new file mode 100644 index 0000000..1a2a1c4 --- /dev/null +++ b/mayu.pro @@ -0,0 +1,30 @@ +#/***************************************************************************** +#* mayu Mate Are You Up +#* Copyright (C) 2018 Syping +#* +#* Licensed under the Apache License, Version 2.0 (the "License"); +#* you may not use this file except in compliance with the License. +#* You may obtain a copy of the License at +#* +#* http://www.apache.org/licenses/LICENSE-2.0 +#* +#* Unless required by applicable law or agreed to in writing, software +#* distributed under the License is distributed on an "AS IS" BASIS, +#* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#* See the License for the specific language governing permissions and +#* limitations under the License. +#*****************************************************************************/ + +QT -= gui +QT += network + +LIBS += -loping + +CONFIG += c++11 console +CONFIG -= app_bundle + +SOURCES += main.cpp \ + mayu.cpp + +HEADERS += \ + mayu.h