mirror of
https://github.com/TrustTunnel/TrustTunnelClient.git
synced 2026-05-22 19:41:36 +00:00
7e2ce27f21
Squashed commit of the following:
commit 3e269033f16e4672860c0fe24cbe8df4b09065f4
Author: Sergey Fionov <sfionov@adguard.com>
Date: Wed Dec 24 20:09:14 2025 +0300
Applied suggestion
commit 14468d33f3ae87accce3a2f2a5c31744a13ac70c
Merge: e359993e 305f5b9a
Author: Andrey Meshkov <am@adguard.com>
Date: Wed Dec 24 20:06:20 2025 +0300
Merge with master
commit e359993e58219942ed5515e54177a8c0250d5efe
Author: Andrey Meshkov <am@adguard.com>
Date: Wed Dec 24 19:59:48 2025 +0300
Fixed python issue
commit 652c8481c7707cf8f8ef7743009fafd7597b280c
Author: Andrey Meshkov <am@adguard.com>
Date: Wed Dec 24 19:47:57 2025 +0300
clang-format
commit d43bf98b664a1136eb28c93304c0fe6b6bf1f247
Author: Andrey Meshkov <am@adguard.com>
Date: Wed Dec 24 19:47:47 2025 +0300
Added lint targets
217 lines
4.7 KiB
C++
217 lines
4.7 KiB
C++
#pragma once
|
|
|
|
#include <cassert>
|
|
#include <memory>
|
|
|
|
#include <jni.h>
|
|
#include <openssl/x509.h>
|
|
#include <pthread.h>
|
|
|
|
/**
|
|
* Attaches the current thread, if necessary, and pushes a local reference frame. Reverses that in dtor.
|
|
*/
|
|
class ScopedJniEnv {
|
|
private:
|
|
JavaVM *m_vm{};
|
|
JNIEnv *m_env{};
|
|
|
|
public:
|
|
ScopedJniEnv(JavaVM *vm, jint max_local_refs) {
|
|
m_vm = vm;
|
|
|
|
int64_t ret = m_vm->GetEnv((void **) &m_env, JNI_VERSION_1_2);
|
|
assert(JNI_EDETACHED == ret || JNI_OK == ret);
|
|
if (JNI_EDETACHED == ret) {
|
|
#if __ANDROID__
|
|
ret = m_vm->AttachCurrentThread(&m_env, nullptr);
|
|
#else
|
|
ret = m_vm->AttachCurrentThread((void **) &m_env, nullptr);
|
|
#endif
|
|
assert(JNI_OK == ret);
|
|
|
|
static pthread_key_t tls_key{};
|
|
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
|
|
ret = pthread_once(&once_control, [] {
|
|
[[maybe_unused]] auto ret = pthread_key_create(&tls_key, [](void *arg) {
|
|
auto vm = (JavaVM *) arg;
|
|
vm->DetachCurrentThread();
|
|
});
|
|
assert(0 == ret);
|
|
});
|
|
assert(0 == ret);
|
|
|
|
ret = pthread_setspecific(tls_key, vm);
|
|
assert(0 == ret);
|
|
}
|
|
|
|
ret = m_env->PushLocalFrame(max_local_refs);
|
|
assert(0 == ret);
|
|
}
|
|
|
|
~ScopedJniEnv() {
|
|
m_env->PopLocalFrame(nullptr);
|
|
}
|
|
|
|
JNIEnv *get() const {
|
|
return m_env;
|
|
}
|
|
|
|
JNIEnv *operator->() const {
|
|
return get();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* NewGlobalRef in ctor, DeleteGlobalRef in dtor.
|
|
*/
|
|
template <typename T>
|
|
class GlobalRef {
|
|
private:
|
|
JavaVM *vm{};
|
|
T ref{};
|
|
|
|
void delete_global_ref() const {
|
|
if (this->vm) {
|
|
ScopedJniEnv env(this->vm, 1);
|
|
env->DeleteGlobalRef(this->ref);
|
|
}
|
|
}
|
|
|
|
public:
|
|
GlobalRef() = default;
|
|
|
|
GlobalRef(JavaVM *vm, T ref)
|
|
: vm{vm} {
|
|
ScopedJniEnv env(vm, 1);
|
|
this->ref = (T) env->NewGlobalRef(ref);
|
|
}
|
|
|
|
GlobalRef(const GlobalRef &other) {
|
|
*this = other;
|
|
}
|
|
|
|
GlobalRef &operator=(const GlobalRef &other) {
|
|
if (&other != this) {
|
|
delete_global_ref();
|
|
this->vm = other.vm;
|
|
ScopedJniEnv env(this->vm, 1);
|
|
this->ref = (T) env->NewGlobalRef(other.ref);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
GlobalRef(GlobalRef &&other) noexcept {
|
|
*this = std::move(other);
|
|
}
|
|
|
|
GlobalRef &operator=(GlobalRef &&other) noexcept {
|
|
if (&other != this) {
|
|
delete_global_ref();
|
|
this->vm = other.vm;
|
|
this->ref = other.ref;
|
|
other.vm = {};
|
|
other.ref = {};
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
~GlobalRef() {
|
|
delete_global_ref();
|
|
}
|
|
|
|
T get() const {
|
|
return this->ref;
|
|
}
|
|
|
|
explicit operator bool() {
|
|
return this->ref;
|
|
}
|
|
|
|
inline bool operator==(std::nullptr_t) {
|
|
return this->ref == nullptr;
|
|
}
|
|
|
|
inline bool operator!=(std::nullptr_t) {
|
|
return this->ref != nullptr;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* DeleteLocalRef in dtor.
|
|
*/
|
|
template <typename T>
|
|
class LocalRef {
|
|
private:
|
|
JNIEnv *env{};
|
|
T ref{};
|
|
|
|
void delete_local_ref() {
|
|
if (this->env) {
|
|
this->env->DeleteLocalRef(this->ref);
|
|
}
|
|
}
|
|
|
|
public:
|
|
LocalRef() = default;
|
|
|
|
LocalRef(JNIEnv *env, T ref)
|
|
: env{env}
|
|
, ref{ref} {
|
|
}
|
|
|
|
LocalRef(JNIEnv *env, const GlobalRef<T> &global)
|
|
: env{env}
|
|
, ref{env->NewLocalRef(global.get())} {
|
|
}
|
|
|
|
LocalRef(const LocalRef &) = delete;
|
|
|
|
LocalRef &operator=(const LocalRef &) = delete;
|
|
|
|
LocalRef(LocalRef &&other) noexcept {
|
|
*this = std::move(other);
|
|
}
|
|
|
|
LocalRef &operator=(LocalRef &&other) noexcept {
|
|
if (&other != this) {
|
|
delete_local_ref();
|
|
this->env = other.env;
|
|
this->ref = other.ref;
|
|
other.env = {};
|
|
other.ref = {};
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
~LocalRef() {
|
|
delete_local_ref();
|
|
}
|
|
|
|
T get() const {
|
|
return this->ref;
|
|
}
|
|
|
|
T release() {
|
|
return std::exchange(this->ref, nullptr);
|
|
}
|
|
|
|
explicit operator bool() {
|
|
return this->ref;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Serialize X509 certificate and put it in java byte array
|
|
* @param env JNI environment
|
|
* @param cert certificate to convert
|
|
* @return java array with serialized certificate
|
|
*/
|
|
LocalRef<jbyteArray> jni_cert_to_java_array(JNIEnv *env, X509 *cert);
|
|
|
|
/**
|
|
* Convert c-string to java string (converting it to cesu-8)
|
|
* @param env JNI environment
|
|
* @param utf8 string to convert
|
|
* @return java string
|
|
*/
|
|
LocalRef<jstring> jni_safe_new_string_utf(JNIEnv *env, std::string_view utf8); |