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