#include "vpnmanager.h" VpnManager::VpnManager(SqlConnection *sqlConnection, QObject *parent) : QObject(parent) { this->sqlConnection = sqlConnection; } VpnManager::~VpnManager() { } void VpnManager::startVpnService() { QString vpnEntry_q = "SELECT * FROM `vpn` WHERE `sys_enabled` = 1;"; QSqlQuery vpnEntry_r = sqlConnection->db.exec(vpnEntry_q); qDebug() << "Number of VPN for start: " << vpnEntry_r.size() << endl; while (vpnEntry_r.next()) { QString name = vpnEntry_r.value("name").toString(); QString ovpnConfigPath = vpnEntry_r.value("ovpn_config_path").toString(); QString device = vpnEntry_r.value("device").toString(); QString routeUpScriptPath = vpnEntry_r.value("route_up_script_path").toString(); int liveTime = vpnEntry_r.value("live_time").toInt(); QString port = vpnEntry_r.value("port").toString(); QString table = vpnEntry_r.value("table").toString(); qDebug() << "Starting " << name << " on device " << device << " using " << ovpnConfigPath << endl; QString openVpnProcName = "/usr/sbin/openvpn"; QStringList openVpnProcArguments; routeUpScriptPath = routeUpScriptPath .append(" ") .append(port) .append(" ") .append(device) .append(" ") .append(table); openVpnProcArguments << "--route-nopull"; openVpnProcArguments << "--ping-exit" << "360"; openVpnProcArguments << "--script-security" << "2"; openVpnProcArguments << "--route-up" << routeUpScriptPath; openVpnProcArguments << "--config" << ovpnConfigPath; QProcess* openVpnProc = new QProcess(); openVpnProc->setProperty("name", QVariant(name)); openVpnProc->setProperty("ovpn_config_path", QVariant(ovpnConfigPath)); openVpnProc->setProperty("device", QVariant(device)); openVpnProc->setProperty("route_up_script_path", QVariant(routeUpScriptPath)); openVpnProc->setProperty("live_time", QVariant(liveTime)); openVpnProc->setProperty("isTimedOut", QVariant(false)); openVpnProc->setProperty("port", QVariant(port)); openVpnProc->setProperty("table", QVariant(table)); QObject::connect(openVpnProc, SIGNAL(finished(int)), this, SLOT(vpnStopHandler(int))); QObject::connect(openVpnProc, SIGNAL(started()), this, SLOT(vpnStartHandler())); procList.append(openVpnProc); openVpnProc->start(openVpnProcName, openVpnProcArguments); } } void VpnManager::stopVpnService() { } void VpnManager::vpnStartHandler() { QObject *obj = QObject::sender(); QProcess* openVpnProc = qobject_cast(obj); QString name = openVpnProc->property("name").toString(); int liveTime = openVpnProc->property("live_time").toInt(); /* Delay */ sleep(2); QString vpnEntry_q = QString("UPDATE `vpn` SET `status` = 1, `in_use_counter` = 0,`started_at` = NOW() WHERE `name` = '"). append(name). append("';"); sqlConnection->db.exec(vpnEntry_q); /* Start reconnect timer */ QTimer *timer = new QTimer(); timer->setProperty("name", openVpnProc->property("name")); QObject::connect(timer, SIGNAL(timeout()), this, SLOT(restartVpn())); timerList.append(timer); qWarning() << "openvpn client (" << name << ") started" << endl; timer->start(1000*60*liveTime); } void VpnManager::vpnStopHandler(int exitCode) { QObject *obj = QObject::sender(); QProcess *openVpnProc = qobject_cast(obj); QString name = openVpnProc->property("name").toString(); QString ovpnConfigPath = openVpnProc->property("ovpn_config_path").toString(); QString device = openVpnProc->property("device").toString(); QString routeUpScriptPath = openVpnProc->property("route_up_script_path").toString(); QString port = openVpnProc->property("port").toString(); QString table = openVpnProc->property("table").toString(); QString vpnEntry_q = QString("UPDATE `vpn` SET `status` = 0 WHERE `name` = '"). append(name). append("';"); sqlConnection->db.exec(vpnEntry_q); QString openVpnProcName = "/usr/sbin/openvpn"; QStringList openVpnProcArguments; routeUpScriptPath = routeUpScriptPath .append(" ") .append(port) .append(" ") .append(device) .append(" ") .append(table); openVpnProcArguments << "--route-nopull"; openVpnProcArguments << "--ping-exit" << "360"; openVpnProcArguments << "--script-security" << "2"; openVpnProcArguments << "--route-up" << routeUpScriptPath; openVpnProcArguments << "--config" << ovpnConfigPath; if (true == openVpnProc->property("isTimedOut").toBool()) { qDebug() << "openvpn client (" << name << ") stoped by timeout" << endl; openVpnProc->setProperty("isTimedOut", QVariant(false)); } else { qCritical() << "openvpn client (" << name << ") stopped with " << exitCode << "stderr: " << QString(openVpnProc->readAllStandardError()) << endl; /* Release timer */ for (int i = 0; i < timerList.size(); i++) { if (timerList.at(i)->property("name") == openVpnProc->property("name")) { timerList.at(i)->stop(); delete timerList.takeAt(i); break; } } } /* Start again! */ openVpnProc->start(openVpnProcName, openVpnProcArguments); } void VpnManager::restartVpn() { QObject *obj = QObject::sender(); QTimer *timer = qobject_cast(obj); QProcess *proc = NULL; bool found = false; for (int i = 0; i < procList.size(); i++) { if (procList.at(i)->property("name") == timer->property("name")) { proc = procList.at(i); found = true; break; } } if (false == found) { qCritical() << "Timer expired. Unable to find process by name " << timer->property("name") << endl; return; } QString vpnEntry_q = QString("SELECT * FROM `vpn` WHERE `name` = '") .append(timer->property("name").toString()) .append("';"); QSqlQuery vpnEntry_r = sqlConnection->db.exec(vpnEntry_q); if (vpnEntry_r.size() == 0) { qCritical() << "Timer expired. Unable to find vpn entry in MySql " << timer->property("name") << endl; return; } if (vpnEntry_r.size() > 1) { qCritical() << "Timer expired. Duplicated vpn entyes in MySql " << timer->property("name") << endl; return; } /* Check in_use_counter */ if (vpnEntry_r.next()) { if (vpnEntry_r.value("in_use_counter").toInt() > 0) { int liveTime = proc->property("live_time").toInt(); timer->setInterval((1000*60*liveTime)/2); qDebug() << "Timer expired. vpn (" << timer->property("name").toString() << ") is used by " << vpnEntry_r.value("in_use_counter").toInt() << " apps" << endl; return; } /* Restart vpn now! */ qDebug() << "Restart vpn " << timer->property("name").toString() << endl; vpnEntry_q = QString("UPDATE `vpn` SET `status` = 0 WHERE `name` = '"). append(timer->property("name").toString()). append("';"); sqlConnection->db.exec(vpnEntry_q); proc->setProperty("isTimedOut", QVariant(true)); /* Stop timer */ timer->stop(); /* Remove timer from list */ for (int i = 0; i < timerList.size(); i++) { if (timerList.at(i) == timer) { delete timerList.takeAt(i); break; } } proc->terminate(); } else { qCritical() << "Timer expired. 2 Unable to find vpn entry in MySql " << timer->property("name") << endl; return; } }