Merge pull request #155 from amnezia-vpn/feature/android_bandwidth_counter

Fix of bandwidth counter for Android
This commit is contained in:
pokamest 2023-01-19 12:38:55 +00:00 committed by GitHub
commit 623c8ca6b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 139 additions and 32 deletions

View file

@ -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()

View file

@ -41,6 +41,7 @@ import java.io.Closeable
import java.io.File
import java.io.FileDescriptor
import java.io.IOException
import java.lang.Exception
import android.net.VpnService as BaseVpnService
@ -274,9 +275,16 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
return mConnectionTime
}
var isUp: Boolean
var isUp: Boolean = false
get() {
return currentTunnelHandle >= 0
return when (mProtocol) {
"openvpn" -> {
field
}
else -> {
currentTunnelHandle >= 0
}
}
}
set(value) {
if (value) {
@ -287,17 +295,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"),
if (mConfig!!.has("server")) { mConfig?.getJSONObject("server")?.getString("ipv4Gateway") } else {""},
if (mConfig!!.has("server")) {mConfig?.getJSONObject("device")?.getString("ipv4Address") } else {""}
)
}
}
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
@ -645,6 +688,7 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
private fun startOpenVpn() {
mOpenVPNThreadv3 = OpenVPNThreadv3(this)
Thread({
mOpenVPNThreadv3?.run()
}).start()

View file

@ -25,8 +25,10 @@ constexpr auto PERMISSIONHELPER_CLASS =
"org/amnezia/vpn/qt/VPNPermissionHelper";
} // namespace
AndroidController::AndroidController()
AndroidController::AndroidController() : QObject()
{
connect(this, &AndroidController::scheduleStatusCheckSignal, this, &AndroidController::scheduleStatusCheckSlot);
s_instance = this;
auto activity = AndroidVPNActivity::instance();
@ -50,8 +52,11 @@ AndroidController::AndroidController()
auto doc = QJsonDocument::fromJson(parcelBody.toUtf8());
qlonglong time = doc.object()["time"].toVariant().toLongLong();
isConnected = doc.object()["connected"].toBool();
emit initialized(
true, doc.object()["connected"].toBool(),
true, isConnected,
time > 0 ? QDateTime::fromMSecsSinceEpoch(time) : QDateTime());
setFallbackConnectedNotification();
@ -61,27 +66,35 @@ AndroidController::AndroidController()
[this](const QString& parcelBody) {
Q_UNUSED(parcelBody);
qDebug() << "Transact: connected";
isConnected = true;
emit scheduleStatusCheckSignal();
emit connectionStateChanged(VpnProtocol::Connected);
}, Qt::QueuedConnection);
connect(activity, &AndroidVPNActivity::eventDisconnected, this,
[this]() {
qDebug() << "Transact: disconnected";
isConnected = false;
emit connectionStateChanged(VpnProtocol::Disconnected);
}, Qt::QueuedConnection);
connect(activity, &AndroidVPNActivity::eventStatisticUpdate, this,
[](const QString& parcelBody) {
qDebug() << "Transact:: update";
[this](const QString& parcelBody) {
qDebug() << "Transact: update";
auto doc = QJsonDocument::fromJson(parcelBody.toUtf8());
// TODO: merge with "Android bandwidth" branch
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 statusUpdated(doc.object()["endpoint"].toString(),
// doc.object()["deviceIpv4"].toString(),
// doc.object()["tx_bytes"].toInt(),
// doc.object()["rx_bytes"].toInt());
emit statusUpdated(rx, tx, endpoint, deviceIPv4);
}, Qt::QueuedConnection);
connect(activity, &AndroidVPNActivity::eventBackendLogs, this,
@ -249,6 +262,16 @@ void AndroidController::setVpnConfig(const QJsonObject &newVpnConfig)
m_vpnConfig = newVpnConfig;
}
void AndroidController::scheduleStatusCheckSlot()
{
QTimer::singleShot(1000, [this]() {
if (isConnected) {
checkStatus();
emit scheduleStatusCheckSignal();
}
});
}
const int ACTIVITY_RESULT_OK = 0xffffffff;
/**
* @brief Starts the Given intent in Context of the QTActivity

View file

@ -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:
@ -69,6 +73,10 @@ private:
std::function<void(const QString&)> m_logCallback;
static void startActivityForResult(JNIEnv* env, jobject /*thiz*/, jobject intent);
bool isConnected = false;
void scheduleStatusCheck();
};
#endif // ANDROID_CONTROLLER_H

View file

@ -15,9 +15,7 @@
AndroidVpnProtocol::AndroidVpnProtocol(Proto protocol, const QJsonObject &configuration, QObject* parent)
: VpnProtocol(configuration, parent),
m_protocol(protocol)
{
}
{ }
ErrorCode AndroidVpnProtocol::start()
{
@ -31,3 +29,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);
}

View file

@ -20,6 +20,9 @@ public:
signals:
public slots:
void connectionDataUpdated(QString totalRx, QString totalTx, QString endpoint, QString deviceIPv4);
protected slots:
protected:

View file

@ -36,6 +36,7 @@ public:
void cleanupBackendLogs();
signals:
void newTransmitedDataCount(quint64 rxBytes, quint64 txBytes);
protected slots:

View file

@ -25,8 +25,10 @@ Proto currentProto = amnezia::Proto::Any;
}
IOSVpnProtocol::IOSVpnProtocol(Proto proto, const QJsonObject &configuration, QObject* parent)
: VpnProtocol(configuration, parent),
m_protocol(proto) {}
: VpnProtocol(configuration, parent), m_protocol(proto)
{
connect(this, &IOSVpnProtocol::newTransmitedDataCount, this, &IOSVpnProtocol::setBytesChanged);
}
IOSVpnProtocol* IOSVpnProtocol::instance() {
return s_instance;
@ -207,8 +209,7 @@ void IOSVpnProtocol::checkStatus()
qDebug() << "ServerIpv4Gateway:" << QString::fromNSString(serverIpv4Gateway)
<< "DeviceIpv4Address:" << QString::fromNSString(deviceIpv4Address)
<< "RxBytes:" << rxBytes << "TxBytes:" << txBytes;
emit bytesChanged(rxBytes, txBytes);
emit newTransmitedDataCount(rxBytes, txBytes);
}];
}

View file

@ -67,7 +67,10 @@ VpnProtocol::VpnConnectionState VpnProtocol::connectionState() const
void VpnProtocol::setBytesChanged(quint64 receivedBytes, quint64 sentBytes)
{
emit bytesChanged(receivedBytes - m_receivedBytes, sentBytes - m_sentBytes);
quint64 rxDiff = receivedBytes - m_receivedBytes;
quint64 txDiff = sentBytes - m_sentBytes;
emit bytesChanged(rxDiff, txDiff);
m_receivedBytes = receivedBytes;
m_sentBytes = sentBytes;

View file

@ -36,8 +36,6 @@ VpnConnection::VpnConnection(std::shared_ptr<Settings> settings,
m_settings(settings),
m_configurator(configurator),
m_serverController(serverController),
m_receivedBytes(0),
m_sentBytes(0),
m_isIOSConnected(false)
{
}
@ -52,11 +50,7 @@ VpnConnection::~VpnConnection()
void VpnConnection::onBytesChanged(quint64 receivedBytes, quint64 sentBytes)
{
emit bytesChanged(receivedBytes - m_receivedBytes, sentBytes - m_sentBytes);
m_receivedBytes = receivedBytes;
m_sentBytes = sentBytes;
emit bytesChanged(receivedBytes, sentBytes);
}
void VpnConnection::onConnectionStateChanged(VpnProtocol::VpnConnectionState state)
@ -362,6 +356,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

View file

@ -93,8 +93,6 @@ private:
QJsonObject m_vpnConfiguration;
QJsonObject m_routeMode;
QString m_remoteAddress;
quint64 m_receivedBytes;
quint64 m_sentBytes;
bool m_isIOSConnected; //remove later move to isConnected,
#ifdef AMNEZIA_DESKTOP