diff options
Diffstat (limited to 'src/lib/ares_android.c')
-rw-r--r-- | src/lib/ares_android.c | 360 |
1 files changed, 199 insertions, 161 deletions
diff --git a/src/lib/ares_android.c b/src/lib/ares_android.c index 5b00b80..778d4d1 100644 --- a/src/lib/ares_android.c +++ b/src/lib/ares_android.c @@ -1,28 +1,39 @@ -/* Copyright (C) 2017 by John Schember <john@nachtimwald.com> +/* MIT License * - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without - * fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting - * documentation, and that the name of M.I.T. not be used in - * advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" - * without express or implied warranty. + * Copyright (c) John Schember + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * SPDX-License-Identifier: MIT */ #if defined(ANDROID) || defined(__ANDROID__) -#include <jni.h> +# include <jni.h> -#include "ares_setup.h" -#include "ares.h" -#include "ares_android.h" -#include "ares_private.h" +# include "ares_setup.h" +# include "ares.h" +# include "ares_android.h" +# include "ares_private.h" -static JavaVM *android_jvm = NULL; -static jobject android_connectivity_manager = NULL; +static JavaVM *android_jvm = NULL; +static jobject android_connectivity_manager = NULL; /* ConnectivityManager.getActiveNetwork */ static jmethodID android_cm_active_net_mid = NULL; @@ -39,12 +50,13 @@ static jmethodID android_list_get_mid = NULL; /* InetAddress.getHostAddress */ static jmethodID android_ia_host_addr_mid = NULL; -static jclass jni_get_class(JNIEnv *env, const char *path) +static jclass jni_get_class(JNIEnv *env, const char *path) { jclass cls = NULL; - if (env == NULL || path == NULL || *path == '\0') + if (env == NULL || path == NULL || *path == '\0') { return NULL; + } cls = (*env)->FindClass(env, path); if ((*env)->ExceptionOccurred(env)) { @@ -60,14 +72,12 @@ static jmethodID jni_get_method_id(JNIEnv *env, jclass cls, jmethodID mid = NULL; if (env == NULL || cls == NULL || func_name == NULL || *func_name == '\0' || - signature == NULL || *signature == '\0') - { + signature == NULL || *signature == '\0') { return NULL; } mid = (*env)->GetMethodID(env, cls, func_name, signature); - if ((*env)->ExceptionOccurred(env)) - { + if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); return NULL; } @@ -82,29 +92,31 @@ void ares_library_init_jvm(JavaVM *jvm) int ares_library_init_android(jobject connectivity_manager) { - JNIEnv *env = NULL; - int need_detatch = 0; - int res; - int ret = ARES_ENOTINITIALIZED; - jclass obj_cls = NULL; + JNIEnv *env = NULL; + int need_detatch = 0; + int res; + ares_status_t ret = ARES_ENOTINITIALIZED; + jclass obj_cls = NULL; - if (android_jvm == NULL) + if (android_jvm == NULL) { goto cleanup; + } res = (*android_jvm)->GetEnv(android_jvm, (void **)&env, JNI_VERSION_1_6); - if (res == JNI_EDETACHED) - { - env = NULL; - res = (*android_jvm)->AttachCurrentThread(android_jvm, &env, NULL); + if (res == JNI_EDETACHED) { + env = NULL; + res = (*android_jvm)->AttachCurrentThread(android_jvm, &env, NULL); need_detatch = 1; } - if (res != JNI_OK || env == NULL) + if (res != JNI_OK || env == NULL) { goto cleanup; + } android_connectivity_manager = - (*env)->NewGlobalRef(env, connectivity_manager); - if (android_connectivity_manager == NULL) + (*env)->NewGlobalRef(env, connectivity_manager); + if (android_connectivity_manager == NULL) { goto cleanup; + } /* Initialization has succeeded. Now attempt to cache the methods that will be * called by ares_get_android_server_list. */ @@ -112,166 +124,178 @@ int ares_library_init_android(jobject connectivity_manager) /* ConnectivityManager in API 1. */ obj_cls = jni_get_class(env, "android/net/ConnectivityManager"); - if (obj_cls == NULL) + if (obj_cls == NULL) { goto cleanup; + } /* ConnectivityManager.getActiveNetwork in API 23. */ - android_cm_active_net_mid = - jni_get_method_id(env, obj_cls, "getActiveNetwork", - "()Landroid/net/Network;"); - if (android_cm_active_net_mid == NULL) + android_cm_active_net_mid = jni_get_method_id( + env, obj_cls, "getActiveNetwork", "()Landroid/net/Network;"); + if (android_cm_active_net_mid == NULL) { goto cleanup; + } /* ConnectivityManager.getLinkProperties in API 21. */ android_cm_link_props_mid = - jni_get_method_id(env, obj_cls, "getLinkProperties", - "(Landroid/net/Network;)Landroid/net/LinkProperties;"); - if (android_cm_link_props_mid == NULL) + jni_get_method_id(env, obj_cls, "getLinkProperties", + "(Landroid/net/Network;)Landroid/net/LinkProperties;"); + if (android_cm_link_props_mid == NULL) { goto cleanup; + } /* LinkProperties in API 21. */ (*env)->DeleteLocalRef(env, obj_cls); obj_cls = jni_get_class(env, "android/net/LinkProperties"); - if (obj_cls == NULL) + if (obj_cls == NULL) { goto cleanup; + } /* getDnsServers in API 21. */ - android_lp_dns_servers_mid = jni_get_method_id(env, obj_cls, "getDnsServers", - "()Ljava/util/List;"); - if (android_lp_dns_servers_mid == NULL) + android_lp_dns_servers_mid = + jni_get_method_id(env, obj_cls, "getDnsServers", "()Ljava/util/List;"); + if (android_lp_dns_servers_mid == NULL) { goto cleanup; + } /* getDomains in API 21. */ - android_lp_domains_mid = jni_get_method_id(env, obj_cls, "getDomains", - "()Ljava/lang/String;"); - if (android_lp_domains_mid == NULL) + android_lp_domains_mid = + jni_get_method_id(env, obj_cls, "getDomains", "()Ljava/lang/String;"); + if (android_lp_domains_mid == NULL) { goto cleanup; + } (*env)->DeleteLocalRef(env, obj_cls); obj_cls = jni_get_class(env, "java/util/List"); - if (obj_cls == NULL) + if (obj_cls == NULL) { goto cleanup; + } android_list_size_mid = jni_get_method_id(env, obj_cls, "size", "()I"); - if (android_list_size_mid == NULL) + if (android_list_size_mid == NULL) { goto cleanup; + } - android_list_get_mid = jni_get_method_id(env, obj_cls, "get", - "(I)Ljava/lang/Object;"); - if (android_list_get_mid == NULL) + android_list_get_mid = + jni_get_method_id(env, obj_cls, "get", "(I)Ljava/lang/Object;"); + if (android_list_get_mid == NULL) { goto cleanup; + } (*env)->DeleteLocalRef(env, obj_cls); obj_cls = jni_get_class(env, "java/net/InetAddress"); - if (obj_cls == NULL) + if (obj_cls == NULL) { goto cleanup; + } - android_ia_host_addr_mid = jni_get_method_id(env, obj_cls, "getHostAddress", - "()Ljava/lang/String;"); - if (android_ia_host_addr_mid == NULL) + android_ia_host_addr_mid = + jni_get_method_id(env, obj_cls, "getHostAddress", "()Ljava/lang/String;"); + if (android_ia_host_addr_mid == NULL) { goto cleanup; + } (*env)->DeleteLocalRef(env, obj_cls); goto done; cleanup: - if (obj_cls != NULL) + if (obj_cls != NULL) { (*env)->DeleteLocalRef(env, obj_cls); + } - android_cm_active_net_mid = NULL; - android_cm_link_props_mid = NULL; + android_cm_active_net_mid = NULL; + android_cm_link_props_mid = NULL; android_lp_dns_servers_mid = NULL; - android_lp_domains_mid = NULL; - android_list_size_mid = NULL; - android_list_get_mid = NULL; - android_ia_host_addr_mid = NULL; + android_lp_domains_mid = NULL; + android_list_size_mid = NULL; + android_list_get_mid = NULL; + android_ia_host_addr_mid = NULL; done: - if (need_detatch) + if (need_detatch) { (*android_jvm)->DetachCurrentThread(android_jvm); + } return ret; } int ares_library_android_initialized(void) { - if (android_jvm == NULL || android_connectivity_manager == NULL) + if (android_jvm == NULL || android_connectivity_manager == NULL) { return ARES_ENOTINITIALIZED; + } return ARES_SUCCESS; } void ares_library_cleanup_android(void) { - JNIEnv *env = NULL; - int need_detatch = 0; - int res; + JNIEnv *env = NULL; + int need_detatch = 0; + int res; - if (android_jvm == NULL || android_connectivity_manager == NULL) + if (android_jvm == NULL || android_connectivity_manager == NULL) { return; + } res = (*android_jvm)->GetEnv(android_jvm, (void **)&env, JNI_VERSION_1_6); - if (res == JNI_EDETACHED) - { - env = NULL; - res = (*android_jvm)->AttachCurrentThread(android_jvm, &env, NULL); + if (res == JNI_EDETACHED) { + env = NULL; + res = (*android_jvm)->AttachCurrentThread(android_jvm, &env, NULL); need_detatch = 1; } - if (res != JNI_OK || env == NULL) + if (res != JNI_OK || env == NULL) { return; + } - android_cm_active_net_mid = NULL; - android_cm_link_props_mid = NULL; + android_cm_active_net_mid = NULL; + android_cm_link_props_mid = NULL; android_lp_dns_servers_mid = NULL; - android_lp_domains_mid = NULL; - android_list_size_mid = NULL; - android_list_get_mid = NULL; - android_ia_host_addr_mid = NULL; + android_lp_domains_mid = NULL; + android_list_size_mid = NULL; + android_list_get_mid = NULL; + android_ia_host_addr_mid = NULL; (*env)->DeleteGlobalRef(env, android_connectivity_manager); android_connectivity_manager = NULL; - if (need_detatch) + if (need_detatch) { (*android_jvm)->DetachCurrentThread(android_jvm); + } } -char **ares_get_android_server_list(size_t max_servers, - size_t *num_servers) +char **ares_get_android_server_list(size_t max_servers, size_t *num_servers) { - JNIEnv *env = NULL; - jobject active_network = NULL; - jobject link_properties = NULL; - jobject server_list = NULL; - jobject server = NULL; - jstring str = NULL; - jint nserv; + JNIEnv *env = NULL; + jobject active_network = NULL; + jobject link_properties = NULL; + jobject server_list = NULL; + jobject server = NULL; + jstring str = NULL; + jint nserv; const char *ch_server_address; - int res; - size_t i; - char **dns_list = NULL; - int need_detatch = 0; + int res; + size_t i; + char **dns_list = NULL; + int need_detatch = 0; if (android_jvm == NULL || android_connectivity_manager == NULL || - max_servers == 0 || num_servers == NULL) - { + max_servers == 0 || num_servers == NULL) { return NULL; } if (android_cm_active_net_mid == NULL || android_cm_link_props_mid == NULL || android_lp_dns_servers_mid == NULL || android_list_size_mid == NULL || - android_list_get_mid == NULL || android_ia_host_addr_mid == NULL) - { + android_list_get_mid == NULL || android_ia_host_addr_mid == NULL) { return NULL; } res = (*android_jvm)->GetEnv(android_jvm, (void **)&env, JNI_VERSION_1_6); - if (res == JNI_EDETACHED) - { - env = NULL; - res = (*android_jvm)->AttachCurrentThread(android_jvm, &env, NULL); + if (res == JNI_EDETACHED) { + env = NULL; + res = (*android_jvm)->AttachCurrentThread(android_jvm, &env, NULL); need_detatch = 1; } - if (res != JNI_OK || env == NULL) + if (res != JNI_OK || env == NULL) { goto done; + } /* JNI below is equivalent to this Java code. import android.content.Context; @@ -296,93 +320,100 @@ char **ares_get_android_server_list(size_t max_servers, active_network = (*env)->CallObjectMethod(env, android_connectivity_manager, android_cm_active_net_mid); - if (active_network == NULL) + if (active_network == NULL) { goto done; + } link_properties = - (*env)->CallObjectMethod(env, android_connectivity_manager, - android_cm_link_props_mid, active_network); - if (link_properties == NULL) + (*env)->CallObjectMethod(env, android_connectivity_manager, + android_cm_link_props_mid, active_network); + if (link_properties == NULL) { goto done; + } - server_list = (*env)->CallObjectMethod(env, link_properties, - android_lp_dns_servers_mid); - if (server_list == NULL) + server_list = + (*env)->CallObjectMethod(env, link_properties, android_lp_dns_servers_mid); + if (server_list == NULL) { goto done; + } nserv = (*env)->CallIntMethod(env, server_list, android_list_size_mid); - if (nserv > (jint)max_servers) + if (nserv > (jint)max_servers) { nserv = (jint)max_servers; - if (nserv <= 0) + } + if (nserv <= 0) { goto done; + } *num_servers = (size_t)nserv; - dns_list = ares_malloc(sizeof(*dns_list)*(*num_servers)); - for (i=0; i<*num_servers; i++) - { - server = (*env)->CallObjectMethod(env, server_list, android_list_get_mid, - (jint)i); - dns_list[i] = ares_malloc(64); + dns_list = ares_malloc(sizeof(*dns_list) * (*num_servers)); + for (i = 0; i < *num_servers; i++) { + size_t len = 64; + server = + (*env)->CallObjectMethod(env, server_list, android_list_get_mid, (jint)i); + dns_list[i] = ares_malloc(len); dns_list[i][0] = 0; - if (server == NULL) - { + if (server == NULL) { continue; } str = (*env)->CallObjectMethod(env, server, android_ia_host_addr_mid); ch_server_address = (*env)->GetStringUTFChars(env, str, 0); - strncpy(dns_list[i], ch_server_address, 64); + ares_strcpy(dns_list[i], ch_server_address, len); (*env)->ReleaseStringUTFChars(env, str, ch_server_address); (*env)->DeleteLocalRef(env, str); (*env)->DeleteLocalRef(env, server); } done: - if ((*env)->ExceptionOccurred(env)) + if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); + } - if (server_list != NULL) + if (server_list != NULL) { (*env)->DeleteLocalRef(env, server_list); - if (link_properties != NULL) + } + if (link_properties != NULL) { (*env)->DeleteLocalRef(env, link_properties); - if (active_network != NULL) + } + if (active_network != NULL) { (*env)->DeleteLocalRef(env, active_network); + } - if (need_detatch) + if (need_detatch) { (*android_jvm)->DetachCurrentThread(android_jvm); + } return dns_list; } char *ares_get_android_search_domains_list(void) { - JNIEnv *env = NULL; - jobject active_network = NULL; - jobject link_properties = NULL; - jstring domains = NULL; + JNIEnv *env = NULL; + jobject active_network = NULL; + jobject link_properties = NULL; + jstring domains = NULL; const char *domain; - int res; - char *domain_list = NULL; - int need_detatch = 0; + int res; + char *domain_list = NULL; + int need_detatch = 0; - if (android_jvm == NULL || android_connectivity_manager == NULL) - { + if (android_jvm == NULL || android_connectivity_manager == NULL) { return NULL; } if (android_cm_active_net_mid == NULL || android_cm_link_props_mid == NULL || - android_lp_domains_mid == NULL) - { + android_lp_domains_mid == NULL) { return NULL; } res = (*android_jvm)->GetEnv(android_jvm, (void **)&env, JNI_VERSION_1_6); - if (res == JNI_EDETACHED) - { - env = NULL; - res = (*android_jvm)->AttachCurrentThread(android_jvm, &env, NULL); + if (res == JNI_EDETACHED) { + env = NULL; + res = (*android_jvm)->AttachCurrentThread(android_jvm, &env, NULL); need_detatch = 1; } - if (res != JNI_OK || env == NULL) + if (res != JNI_OK || env == NULL) { goto done; + } /* JNI below is equivalent to this Java code. import android.content.Context; @@ -393,7 +424,7 @@ char *ares_get_android_search_domains_list(void) .getSystemService(Context.CONNECTIVITY_SERVICE); Network an = cm.getActiveNetwork(); LinkProperties lp = cm.getLinkProperties(an); - String domains = lp.getDomains(); + String domains = lp.getDomains(); for (String domain: domains.split(",")) { String d = domain; } @@ -404,38 +435,45 @@ char *ares_get_android_search_domains_list(void) active_network = (*env)->CallObjectMethod(env, android_connectivity_manager, android_cm_active_net_mid); - if (active_network == NULL) + if (active_network == NULL) { goto done; + } link_properties = - (*env)->CallObjectMethod(env, android_connectivity_manager, - android_cm_link_props_mid, active_network); - if (link_properties == NULL) + (*env)->CallObjectMethod(env, android_connectivity_manager, + android_cm_link_props_mid, active_network); + if (link_properties == NULL) { goto done; + } /* Get the domains. It is a common separated list of domains to search. */ - domains = (*env)->CallObjectMethod(env, link_properties, - android_lp_domains_mid); - if (domains == NULL) + domains = + (*env)->CallObjectMethod(env, link_properties, android_lp_domains_mid); + if (domains == NULL) { goto done; + } /* Split on , */ - domain = (*env)->GetStringUTFChars(env, domains, 0); + domain = (*env)->GetStringUTFChars(env, domains, 0); domain_list = ares_strdup(domain); (*env)->ReleaseStringUTFChars(env, domains, domain); (*env)->DeleteLocalRef(env, domains); done: - if ((*env)->ExceptionOccurred(env)) + if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); + } - if (link_properties != NULL) + if (link_properties != NULL) { (*env)->DeleteLocalRef(env, link_properties); - if (active_network != NULL) + } + if (active_network != NULL) { (*env)->DeleteLocalRef(env, active_network); + } - if (need_detatch) + if (need_detatch) { (*android_jvm)->DetachCurrentThread(android_jvm); + } return domain_list; } #else |