From a9cc6785a9be9857bf004160cdf7aa2535b69a6b Mon Sep 17 00:00:00 2001 From: evgeny Date: Wed, 28 Oct 2026 11:04:56 +0100 Subject: [PATCH] Expose authorized server addition to Android JNI --- tests/test_invite_codec.c | 2 +- .../jni_bridge/android_jni_bridge.c | 16 ++++++++++++++-- .../chatgui-android/libutun_lite/instance_lite.c | 6 ++++++ .../chatgui-android/libutun_lite/instance_lite.h | 3 +++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/tests/test_invite_codec.c b/tests/test_invite_codec.c index e8fbfdedc..503befa8c 100644 --- a/tests/test_invite_codec.c +++ b/tests/test_invite_codec.c @@ -103,7 +103,7 @@ int main(void) { CHECK(!invite_link_decode(link, strlen(link), &decoded_server, NULL, 0)); CHECK(decoded_server.kind == INVITE_KIND_SERVER && !decoded_server.channelId && !decoded_server.join_key); CHECK(!memcmp(server.add_key, decoded_server.add_key, sizeof(server.add_key)) && decoded_server.addrCount == server.addrCount); - for (size_t cut = 0; cut < 34; cut++) { + for (size_t cut = 1; cut < 34; cut++) { uint8_t server_raw[34] = {INVITE_LINK_VERSION, INVITE_KIND_SERVER}; rejected_raw(server_raw, cut); } diff --git a/tools/chatgui-android/jni_bridge/android_jni_bridge.c b/tools/chatgui-android/jni_bridge/android_jni_bridge.c index de2c126b0..25cd95d9e 100644 --- a/tools/chatgui-android/jni_bridge/android_jni_bridge.c +++ b/tools/chatgui-android/jni_bridge/android_jni_bridge.c @@ -1942,6 +1942,18 @@ JNIEXPORT jint JNICALL Java_com_utun_chat_data_NativeLib_nativeJoinChannel( (*env)->ReleaseStringUTFChars(env, link, text); return result; } +JNIEXPORT jint JNICALL Java_com_utun_chat_data_NativeLib_nativeAddServer( + JNIEnv* env, jobject thiz, jlong channel, jstring link, jlong request) { + (void)thiz; + if (!link || channel <= 0) { + DEBUG_WARN(DEBUG_CATEGORY_CHAT_SYNC, "Android server addition requires channel and link"); return CHAT_CONNECT_INVALID; + } + const char* text = (*env)->GetStringUTFChars(env, link, NULL); + if (!text) { DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "Android server link UTF-8 allocation failed"); return CHAT_CONNECT_ERROR; } + int result = instance_lite_add_server((uint64_t)request, (uint64_t)channel, text, strlen(text)); + (*env)->ReleaseStringUTFChars(env, link, text); return result; +} + /* Представление результата общего C-кодека для предпросмотра Kotlin. * uint64 key/node передаются десятичными строками: числовой JSON может потерять биты при преобразовании в Double/Long. */ static int invite_hex_json(struct strbuf* out, const uint8_t* bytes, size_t len) { @@ -1961,8 +1973,8 @@ JNIEXPORT jstring JNICALL Java_com_utun_chat_data_NativeLib_nativeDecodeInvite( (*env)->ReleaseStringUTFChars(env, link, text); if (result) return NULL; struct strbuf out = strbuf_new(); - if (strbuf_addf(&out, "{\"channel\":%llu,\"key\":\"%llu\",\"node\":\"%llu\",\"pubkey\":", - (unsigned long long)data.channelId, (unsigned long long)data.join_key, (unsigned long long)data.nodeId) < 0 || + if (strbuf_addf(&out, "{\"kind\":%u,\"channel\":%llu,\"key\":\"%llu\",\"node\":\"%llu\",\"pubkey\":", + data.kind, (unsigned long long)data.channelId, (unsigned long long)data.join_key, (unsigned long long)data.nodeId) < 0 || invite_hex_json(&out, data.pubkey, 32) < 0 || strbuf_addf(&out, ",\"password\":") < 0 || invite_hex_json(&out, (const uint8_t*)data.password, data.password_len) < 0) goto failed; if (data.reality.has) { diff --git a/tools/chatgui-android/libutun_lite/instance_lite.c b/tools/chatgui-android/libutun_lite/instance_lite.c index 986827e77..cccffe8d8 100644 --- a/tools/chatgui-android/libutun_lite/instance_lite.c +++ b/tools/chatgui-android/libutun_lite/instance_lite.c @@ -86,6 +86,12 @@ int instance_lite_join_link(uint64_t request, const char* link, size_t len) { pthread_mutex_unlock(&join_port_lock); return result; } +int instance_lite_add_server(uint64_t request, uint64_t channel, const char* link, size_t len) { + pthread_mutex_lock(&join_port_lock); + int result = chat_join_port_offer(join_port, request, channel, link, len); + pthread_mutex_unlock(&join_port_lock); return result; +} + static volatile int g_stop = 0; /* Kotlin-write, C-read (poll loop) */ struct restart_request { char* config_text; /* Копия INI, принадлежит запросу до завершения подготовки. */ diff --git a/tools/chatgui-android/libutun_lite/instance_lite.h b/tools/chatgui-android/libutun_lite/instance_lite.h index e6c05d875..20dd46264 100644 --- a/tools/chatgui-android/libutun_lite/instance_lite.h +++ b/tools/chatgui-android/libutun_lite/instance_lite.h @@ -47,6 +47,9 @@ struct UTUN_INSTANCE* instance_lite_get_instance(void); * 0 — принят, результат CHAT_EVT_CONNECT_RESULT с тем же request; <0 — отказ без события. * Не требует от caller удерживать inst/ua; при stop/restart port закрывается. */ int instance_lite_join_link(uint64_t request, const char* link, size_t len); +/* Любой поток: добавить выбранный локальный channel на сервер по SERVER-ссылке. + * 0 — команда принята, результат CONNECT_RESULT с request; <0 — отказ без события. */ +int instance_lite_add_server(uint64_t request, uint64_t channel, const char* link, size_t len); /* События CHAT_EVT_* из native-потока; data заимствован только на вызов, формат зависит от type (не всегда JSON). * Установить до start; callback и его окружение должны жить до завершения worker. NULL отключает доставку. */