diff --git a/client/android/src/org/amnezia/vpn/OpenVPNThreadv3.kt b/client/android/src/org/amnezia/vpn/OpenVPNThreadv3.kt index f40f9536..39e077dd 100644 --- a/client/android/src/org/amnezia/vpn/OpenVPNThreadv3.kt +++ b/client/android/src/org/amnezia/vpn/OpenVPNThreadv3.kt @@ -31,6 +31,31 @@ class OpenVPNThreadv3(var service: VPNService): ClientAPI_OpenVPNClient(), Runna private var mAlreadyInitialised = false private var mService: VPNService = service + private var bytesInIndex = -1 + private var bytesOutIndex = -1 + + init { + findConfigIndicies() + } + + private fun findConfigIndicies() { + val n: Int = stats_n() + + for (i in 0 until n) { + val name: String = stats_name(i) + if (name == "BYTES_IN") bytesInIndex = i + if (name == "BYTES_OUT") bytesOutIndex = i + } + } + + fun getTotalRxBytes(): Long { + return stats_value(bytesInIndex) + } + + fun getTotalTxBytes(): Long { + return stats_value(bytesOutIndex) + } + override fun run() { val config: ClientAPI_Config = ClientAPI_Config() diff --git a/client/android/src/org/amnezia/vpn/VPNService.kt b/client/android/src/org/amnezia/vpn/VPNService.kt index 23e9ff0c..1d0adb42 100644 --- a/client/android/src/org/amnezia/vpn/VPNService.kt +++ b/client/android/src/org/amnezia/vpn/VPNService.kt @@ -319,17 +319,52 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface { mBinder.dispatchEvent(VPNServiceBinder.EVENTS.disconnected, "") mConnectionTime = 0 } + val status: JSONObject get() { val deviceIpv4: String = "" + + val status = when (mProtocol) { + "openvpn" -> { + if (mOpenVPNThreadv3 == null) { + Status(null, null, null, null) + } else { + val rx = mOpenVPNThreadv3?.getTotalRxBytes() ?: "" + val tx = mOpenVPNThreadv3?.getTotalTxBytes() ?: "" + + Status( + rx.toString(), + tx.toString(), + if (mConfig!!.has("server")) { mConfig?.getJSONObject("server")?.getString("ipv4Gateway") } else {""}, + if (mConfig!!.has("device")) { mConfig?.getJSONObject("device")?.getString("ipv4Address") } else {""} + ) + } + } + else -> { + Status( + getConfigValue("rx_bytes"), + getConfigValue("tx_bytes"), + mConfig?.getJSONObject("server")?.getString("ipv4Gateway"), + mConfig?.getJSONObject("device")?.getString("ipv4Address") + ) + } + } + return JSONObject().apply { - putOpt("rx_bytes", getConfigValue("rx_bytes")) - putOpt("tx_bytes", getConfigValue("tx_bytes")) - putOpt("endpoint", mConfig?.getJSONObject("server")?.getString("ipv4Gateway")) - putOpt("deviceIpv4", mConfig?.getJSONObject("device")?.getString("ipv4Address")) + putOpt("rx_bytes", status.rxBytes) + putOpt("tx_bytes", status.txBytes) + putOpt("endpoint", status.endpoint) + putOpt("deviceIpv4", status.device) } } + data class Status( + var rxBytes: String?, + var txBytes: String?, + var endpoint: String?, + var device: String? + ) + /* * Checks if the VPN Permission is given. * If the permission is given, returns true diff --git a/client/platforms/android/android_controller.cpp b/client/platforms/android/android_controller.cpp index af30fe05..0a055673 100644 --- a/client/platforms/android/android_controller.cpp +++ b/client/platforms/android/android_controller.cpp @@ -52,7 +52,7 @@ constexpr auto PERMISSIONHELPER_CLASS = AndroidController::AndroidController(): m_binder(this) { - + connect(this, &AndroidController::scheduleStatusCheckSignal, this, &AndroidController::scheduleStatusCheckSlot); } AndroidController* AndroidController::instance() { @@ -237,6 +237,14 @@ void AndroidController::setVpnConfig(const QJsonObject &newVpnConfig) m_vpnConfig = newVpnConfig; } +void AndroidController::scheduleStatusCheckSlot() +{ + QTimer::singleShot(1000, [this]() { + if (isConnected) { + checkStatus(); + } + }); +} /** * @brief AndroidController::VPNBinder::onTransact @@ -271,22 +279,30 @@ bool AndroidController::VPNBinder::onTransact(int code, case EVENT_CONNECTED: qDebug() << "Transact: connected"; emit m_controller->connectionStateChanged(VpnProtocol::Connected); + m_controller->isConnected = true; + emit m_controller->scheduleStatusCheckSignal(); break; case EVENT_DISCONNECTED: qDebug() << "Transact: disconnected"; emit m_controller->connectionStateChanged(VpnProtocol::Disconnected); + m_controller->isConnected = false; break; case EVENT_STATISTIC_UPDATE: + { qDebug() << "Transact:: update"; - // Data is here a JSON String doc = QJsonDocument::fromJson(data.readData()); - // TODO update counters -// emit m_controller->statusUpdated(doc.object()["endpoint"].toString(), -// doc.object()["deviceIpv4"].toString(), -// doc.object()["totalTX"].toInt(), -// doc.object()["totalRX"].toInt()); + + QString rx = doc.object()["rx_bytes"].toString(); + QString tx = doc.object()["tx_bytes"].toString(); + QString endpoint = doc.object()["endpoint"].toString(); + QString deviceIPv4 = doc.object()["deviceIpv4"].toString(); + + emit m_controller->statusUpdated(rx, tx, endpoint, deviceIPv4); + emit m_controller->scheduleStatusCheckSignal(); + break; + } case EVENT_BACKEND_LOGS: qDebug() << "Transact: backend logs"; diff --git a/client/platforms/android/android_controller.h b/client/platforms/android/android_controller.h index c2a65381..27ec2e12 100644 --- a/client/platforms/android/android_controller.h +++ b/client/platforms/android/android_controller.h @@ -53,7 +53,11 @@ signals: void initialized(bool status, bool connected, const QDateTime& connectionDate); + void statusUpdated(QString totalRx, QString totalTx, QString endpoint, QString deviceIPv4); + void scheduleStatusCheckSignal(); + protected slots: + void scheduleStatusCheckSlot(); protected: @@ -84,6 +88,10 @@ private: VPNBinder m_binder; + bool isConnected = false; + + void scheduleStatusCheck(); + static void startActivityForResult(JNIEnv* env, jobject /*thiz*/, jobject intent); }; diff --git a/client/protocols/android_vpnprotocol.cpp b/client/protocols/android_vpnprotocol.cpp index 66e2eaf5..f6ae75a5 100644 --- a/client/protocols/android_vpnprotocol.cpp +++ b/client/protocols/android_vpnprotocol.cpp @@ -23,9 +23,7 @@ AndroidVpnProtocol::AndroidVpnProtocol(Proto protocol, const QJsonObject &configuration, QObject* parent) : VpnProtocol(configuration, parent), m_protocol(protocol) -{ - -} +{ } ErrorCode AndroidVpnProtocol::start() { @@ -39,3 +37,11 @@ void AndroidVpnProtocol::stop() AndroidController::instance()->stop(); } +void AndroidVpnProtocol::connectionDataUpdated(QString totalRx, QString totalTx, QString endpoint, QString deviceIPv4) +{ + quint64 rxBytes = totalRx.toLongLong(); + quint64 txBytes = totalTx.toLongLong(); + + setBytesChanged(rxBytes, txBytes); +} + diff --git a/client/protocols/android_vpnprotocol.h b/client/protocols/android_vpnprotocol.h index cdcff2c6..c9599f5d 100644 --- a/client/protocols/android_vpnprotocol.h +++ b/client/protocols/android_vpnprotocol.h @@ -25,6 +25,9 @@ public: signals: +public slots: + void connectionDataUpdated(QString totalRx, QString totalTx, QString endpoint, QString deviceIPv4); + protected slots: protected: diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index 286ffc8c..38e0b740 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -362,6 +362,7 @@ void VpnConnection::connectToVpn(int serverIndex, Proto proto = ContainerProps::defaultProtocol(container); AndroidVpnProtocol *androidVpnProtocol = new AndroidVpnProtocol(proto, m_vpnConfiguration); connect(AndroidController::instance(), &AndroidController::connectionStateChanged, androidVpnProtocol, &AndroidVpnProtocol::setConnectionState); + connect(AndroidController::instance(), &AndroidController::statusUpdated, androidVpnProtocol, &AndroidVpnProtocol::connectionDataUpdated); m_vpnProtocol.reset(androidVpnProtocol); #elif defined Q_OS_IOS