VPN Status
This commit is contained in:
commit
73cbd92121
8 changed files with 348 additions and 0 deletions
78
Ping.cpp
Normal file
78
Ping.cpp
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
#include <QAbstractSocket>
|
||||||
|
#include <QHostAddress>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QHostInfo>
|
||||||
|
#include <QList>
|
||||||
|
#include "Ping.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "oping.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
double Ping::ping(const QString &host, int tries, double timeout)
|
||||||
|
{
|
||||||
|
double latency;
|
||||||
|
pingobj_t *pingObj;
|
||||||
|
pingobj_iter_t *pingIter;
|
||||||
|
if ((pingObj = ping_construct()) == NULL) {
|
||||||
|
QTextStream(stderr) << "Ping construction failed " << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ping_setopt(pingObj, PING_OPT_TIMEOUT, (void*)(&timeout)) < 0) {
|
||||||
|
QTextStream(stderr) << "Setting timeout to" << timeout << " have failed" << endl;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (QAbstractSocket::IPv6Protocol == hostAddress.protocol()) {
|
||||||
|
if (ping_host_add(pingObj, hostAddress.toString().toStdString().c_str()) < 0) {
|
||||||
|
ping_destroy(pingObj);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QList<QHostAddress> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ping_destroy(pingObj);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool hostUp = false;
|
||||||
|
int curTry = 0;
|
||||||
|
while (!hostUp && curTry != tries) {
|
||||||
|
if (ping_send(pingObj) < 0) {
|
||||||
|
QTextStream(stderr) << "Pinging host " << host << " has failed" << endl;
|
||||||
|
ping_destroy(pingObj);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bool pingSuccess = false;
|
||||||
|
for (pingIter = ping_iterator_get(pingObj); pingIter != NULL; pingIter =
|
||||||
|
ping_iterator_next(pingIter)) {
|
||||||
|
size_t len;
|
||||||
|
len = sizeof(double);
|
||||||
|
ping_iterator_get_info(pingIter, PING_INFO_LATENCY, &latency, &len);
|
||||||
|
pingSuccess = !(latency < 0);
|
||||||
|
}
|
||||||
|
if (pingSuccess) {
|
||||||
|
hostUp = true;
|
||||||
|
}
|
||||||
|
curTry++;
|
||||||
|
}
|
||||||
|
ping_destroy(pingObj);
|
||||||
|
if (hostUp)
|
||||||
|
return latency;
|
||||||
|
return -1;
|
||||||
|
}
|
12
Ping.h
Normal file
12
Ping.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef PING_H
|
||||||
|
#define PING_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class Ping
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static double ping(const QString &host, int tries, double timeout = 2.5);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PING_H
|
69
Runner.cpp
Normal file
69
Runner.cpp
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#include <QDateTime>
|
||||||
|
#include "Runner.h"
|
||||||
|
#include "Ping.h"
|
||||||
|
|
||||||
|
Runner::Runner(QList<QString> pingHosts) :
|
||||||
|
pingHosts_p(pingHosts)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Runner::refresh()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
refreshed_p = QDateTime::currentDateTimeUtc().toTime_t();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint Runner::refreshed()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
return refreshed_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString Runner::currentHost()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
return currentHost_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QMap<QString, double> Runner::pingData()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
return pingData_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Runner::setCurrentHost(const QString ¤tHost)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
currentHost_p = currentHost;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Runner::setPingData(const QMap<QString, double> &pingData)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
pingData_p = pingData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Runner::run()
|
||||||
|
{
|
||||||
|
// Ping data initialisation
|
||||||
|
QMap<QString, double> pingData_l;
|
||||||
|
for (const QString &host : pingHosts_p) {
|
||||||
|
pingData_l.insert(host, -1);
|
||||||
|
}
|
||||||
|
setPingData(pingData_l);
|
||||||
|
refresh();
|
||||||
|
|
||||||
|
forever {
|
||||||
|
if (QThread::currentThread()->isInterruptionRequested()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const QString &host : pingHosts_p) {
|
||||||
|
setCurrentHost(host);
|
||||||
|
refresh();
|
||||||
|
double ping = Ping::ping(host, 3);
|
||||||
|
pingData_l[host] = ping;
|
||||||
|
setPingData(pingData_l);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
Runner.h
Normal file
33
Runner.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef RUNNER_H
|
||||||
|
#define RUNNER_H
|
||||||
|
|
||||||
|
#include <QMutexLocker>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QThread>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
class Runner : public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Runner(QList<QString> pingHosts);
|
||||||
|
void refresh();
|
||||||
|
uint refreshed();
|
||||||
|
const QString currentHost();
|
||||||
|
const QMap<QString, double> pingData();
|
||||||
|
void setCurrentHost(const QString ¤tHost);
|
||||||
|
void setPingData(const QMap<QString, double> &pingData);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QMap<QString, double> pingData_p;
|
||||||
|
QList<QString> pingHosts_p;
|
||||||
|
QString currentHost_p;
|
||||||
|
uint refreshed_p;
|
||||||
|
mutable QMutex mutex;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void run();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // RUNNER_H
|
42
Socket.cpp
Normal file
42
Socket.cpp
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QLocalSocket>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include "Socket.h"
|
||||||
|
|
||||||
|
Socket::Socket(Runner *runner) :
|
||||||
|
runner(runner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Socket::incomingConnection(quintptr socketDescriptor)
|
||||||
|
{
|
||||||
|
QLocalSocket *socket = new QLocalSocket;
|
||||||
|
if (!socket->setSocketDescriptor(socketDescriptor, QLocalSocket::ConnectedState, QLocalSocket::WriteOnly)) {
|
||||||
|
QTextStream(stderr) << "Socket failed to initialise." << endl;
|
||||||
|
delete socket;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject::connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
|
||||||
|
|
||||||
|
QJsonObject pingObject;
|
||||||
|
QMap<QString, double> pingData_l = runner->pingData();
|
||||||
|
QMap<QString, double>::const_iterator it = pingData_l.constBegin();
|
||||||
|
QMap<QString, double>::const_iterator end = pingData_l.constEnd();
|
||||||
|
while (it != end) {
|
||||||
|
pingObject.insert(it.key(), it.value());
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject object;
|
||||||
|
object.insert("Current", runner->currentHost());
|
||||||
|
object.insert("Ping", pingObject);
|
||||||
|
object.insert("Refreshed", QString::number(runner->refreshed(), 16));
|
||||||
|
|
||||||
|
QJsonDocument document;
|
||||||
|
document.setObject(object);
|
||||||
|
|
||||||
|
QByteArray jsonData = document.toJson(QJsonDocument::Compact);
|
||||||
|
socket->write(jsonData + "\n");
|
||||||
|
socket->disconnectFromServer();
|
||||||
|
}
|
19
Socket.h
Normal file
19
Socket.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef SOCKET_H
|
||||||
|
#define SOCKET_H
|
||||||
|
|
||||||
|
#include "Runner.h"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QLocalServer>
|
||||||
|
|
||||||
|
class Socket : public QLocalServer
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Socket(Runner *runner);
|
||||||
|
void incomingConnection(quintptr socketDescriptor);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Runner *runner;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SOCKET_H
|
76
main.cpp
Normal file
76
main.cpp
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QFile>
|
||||||
|
#include "Runner.h"
|
||||||
|
#include "Socket.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QCoreApplication::setSetuidAllowed(true);
|
||||||
|
QCoreApplication a(argc, argv);
|
||||||
|
|
||||||
|
QCommandLineParser parser;
|
||||||
|
parser.addPositionalArgument("config", "Ping configuration");
|
||||||
|
parser.addPositionalArgument("socket", "Unix socket");
|
||||||
|
parser.process(a);
|
||||||
|
|
||||||
|
const QStringList args = parser.positionalArguments();
|
||||||
|
if (args.length() != 2) {
|
||||||
|
QTextStream(stderr) << "Not enough or too many arguments was given!" << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
const QString pingConfig = args.at(0);
|
||||||
|
const QString unixSocket = args.at(1);
|
||||||
|
|
||||||
|
QByteArray jsonContent;
|
||||||
|
QFile jsonFile(pingConfig);
|
||||||
|
if (jsonFile.open(QFile::ReadOnly)) {
|
||||||
|
jsonContent = jsonFile.readAll();
|
||||||
|
jsonFile.close();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QTextStream(stderr) << "Failed to read Ping configuration!" << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QString> pingHosts;
|
||||||
|
QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonContent);
|
||||||
|
QJsonObject jsonObject = jsonDocument.object();
|
||||||
|
QJsonObject::const_iterator it = jsonObject.constBegin();
|
||||||
|
QJsonObject::const_iterator end = jsonObject.constEnd();
|
||||||
|
while (it != end) {
|
||||||
|
if (it.value().isArray()) {
|
||||||
|
QJsonArray array = it.value().toArray();
|
||||||
|
QJsonArray::const_iterator it = array.constBegin();
|
||||||
|
QJsonArray::const_iterator end = array.constEnd();
|
||||||
|
while (it != end) {
|
||||||
|
const QString host = array.at(it.i).toString();
|
||||||
|
if (!host.isEmpty() && host != "none" && !pingHosts.contains(host))
|
||||||
|
pingHosts << host;
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (it.value().isString()) {
|
||||||
|
const QString host = it.value().toString();
|
||||||
|
if (!host.isEmpty() && host != "none" && !pingHosts.contains(host))
|
||||||
|
pingHosts << host;
|
||||||
|
}
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Runner runner(pingHosts);
|
||||||
|
Socket socket(&runner);
|
||||||
|
socket.setSocketOptions(QLocalServer::WorldAccessOption);
|
||||||
|
if (!socket.listen(unixSocket)) {
|
||||||
|
QTextStream(stderr) << "Failed to initialise Unix socket!" << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
runner.start();
|
||||||
|
|
||||||
|
return a.exec();
|
||||||
|
}
|
19
vpnstatus.pro
Normal file
19
vpnstatus.pro
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
QT -= gui
|
||||||
|
QT += network
|
||||||
|
|
||||||
|
CONFIG += c++11 console
|
||||||
|
CONFIG -= app_bundle
|
||||||
|
|
||||||
|
unix: DEFINES += PRIVILEGE_DROP_REQUIRED
|
||||||
|
unix: LIBS += -loping
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
main.cpp \
|
||||||
|
Ping.cpp \
|
||||||
|
Runner.cpp \
|
||||||
|
Socket.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
Ping.h \
|
||||||
|
Runner.h \
|
||||||
|
Socket.h
|
Loading…
Reference in a new issue