xref: /aosp_15_r20/external/aws-crt-java/src/native/http_connection_manager.c (revision 3c7ae9de214676c52d19f01067dc1a404272dc11)
1*3c7ae9deSAndroid Build Coastguard Worker /**
2*3c7ae9deSAndroid Build Coastguard Worker  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3*3c7ae9deSAndroid Build Coastguard Worker  * SPDX-License-Identifier: Apache-2.0.
4*3c7ae9deSAndroid Build Coastguard Worker  */
5*3c7ae9deSAndroid Build Coastguard Worker 
6*3c7ae9deSAndroid Build Coastguard Worker #include "crt.h"
7*3c7ae9deSAndroid Build Coastguard Worker #include "java_class_ids.h"
8*3c7ae9deSAndroid Build Coastguard Worker 
9*3c7ae9deSAndroid Build Coastguard Worker #include <http_proxy_options.h>
10*3c7ae9deSAndroid Build Coastguard Worker #include <jni.h>
11*3c7ae9deSAndroid Build Coastguard Worker #include <string.h>
12*3c7ae9deSAndroid Build Coastguard Worker 
13*3c7ae9deSAndroid Build Coastguard Worker #include <aws/common/condition_variable.h>
14*3c7ae9deSAndroid Build Coastguard Worker #include <aws/common/string.h>
15*3c7ae9deSAndroid Build Coastguard Worker 
16*3c7ae9deSAndroid Build Coastguard Worker #include <aws/io/channel_bootstrap.h>
17*3c7ae9deSAndroid Build Coastguard Worker #include <aws/io/event_loop.h>
18*3c7ae9deSAndroid Build Coastguard Worker #include <aws/io/logging.h>
19*3c7ae9deSAndroid Build Coastguard Worker #include <aws/io/socket.h>
20*3c7ae9deSAndroid Build Coastguard Worker #include <aws/io/tls_channel_handler.h>
21*3c7ae9deSAndroid Build Coastguard Worker 
22*3c7ae9deSAndroid Build Coastguard Worker #include <aws/http/connection.h>
23*3c7ae9deSAndroid Build Coastguard Worker #include <aws/http/connection_manager.h>
24*3c7ae9deSAndroid Build Coastguard Worker #include <aws/http/http.h>
25*3c7ae9deSAndroid Build Coastguard Worker #include <aws/http/proxy.h>
26*3c7ae9deSAndroid Build Coastguard Worker #include <http_proxy_options_environment_variable.h>
27*3c7ae9deSAndroid Build Coastguard Worker 
28*3c7ae9deSAndroid Build Coastguard Worker #include "http_connection_manager.h"
29*3c7ae9deSAndroid Build Coastguard Worker 
30*3c7ae9deSAndroid Build Coastguard Worker /* on 32-bit platforms, casting pointers to longs throws a warning we don't need */
31*3c7ae9deSAndroid Build Coastguard Worker #if UINTPTR_MAX == 0xffffffff
32*3c7ae9deSAndroid Build Coastguard Worker #    if defined(_MSC_VER)
33*3c7ae9deSAndroid Build Coastguard Worker #        pragma warning(push)
34*3c7ae9deSAndroid Build Coastguard Worker #        pragma warning(disable : 4305) /* 'type cast': truncation from 'jlong' to 'jni_tls_ctx_options *' */
35*3c7ae9deSAndroid Build Coastguard Worker #    else
36*3c7ae9deSAndroid Build Coastguard Worker #        pragma GCC diagnostic push
37*3c7ae9deSAndroid Build Coastguard Worker #        pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
38*3c7ae9deSAndroid Build Coastguard Worker #        pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
39*3c7ae9deSAndroid Build Coastguard Worker #    endif
40*3c7ae9deSAndroid Build Coastguard Worker #endif
41*3c7ae9deSAndroid Build Coastguard Worker 
42*3c7ae9deSAndroid Build Coastguard Worker /*
43*3c7ae9deSAndroid Build Coastguard Worker  * Connection manager binding, persists across the lifetime of the native object.
44*3c7ae9deSAndroid Build Coastguard Worker  */
45*3c7ae9deSAndroid Build Coastguard Worker struct http_connection_manager_binding {
46*3c7ae9deSAndroid Build Coastguard Worker     JavaVM *jvm;
47*3c7ae9deSAndroid Build Coastguard Worker     jweak java_http_conn_manager;
48*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_connection_manager *manager;
49*3c7ae9deSAndroid Build Coastguard Worker };
50*3c7ae9deSAndroid Build Coastguard Worker 
s_destroy_manager_binding(struct http_connection_manager_binding * binding,JNIEnv * env)51*3c7ae9deSAndroid Build Coastguard Worker static void s_destroy_manager_binding(struct http_connection_manager_binding *binding, JNIEnv *env) {
52*3c7ae9deSAndroid Build Coastguard Worker     if (binding == NULL || env == NULL) {
53*3c7ae9deSAndroid Build Coastguard Worker         return;
54*3c7ae9deSAndroid Build Coastguard Worker     }
55*3c7ae9deSAndroid Build Coastguard Worker 
56*3c7ae9deSAndroid Build Coastguard Worker     if (binding->java_http_conn_manager != NULL) {
57*3c7ae9deSAndroid Build Coastguard Worker         (*env)->DeleteWeakGlobalRef(env, binding->java_http_conn_manager);
58*3c7ae9deSAndroid Build Coastguard Worker     }
59*3c7ae9deSAndroid Build Coastguard Worker 
60*3c7ae9deSAndroid Build Coastguard Worker     aws_mem_release(aws_jni_get_allocator(), binding);
61*3c7ae9deSAndroid Build Coastguard Worker }
62*3c7ae9deSAndroid Build Coastguard Worker 
s_on_http_conn_manager_shutdown_complete_callback(void * user_data)63*3c7ae9deSAndroid Build Coastguard Worker static void s_on_http_conn_manager_shutdown_complete_callback(void *user_data) {
64*3c7ae9deSAndroid Build Coastguard Worker 
65*3c7ae9deSAndroid Build Coastguard Worker     struct http_connection_manager_binding *binding = (struct http_connection_manager_binding *)user_data;
66*3c7ae9deSAndroid Build Coastguard Worker 
67*3c7ae9deSAndroid Build Coastguard Worker     /********** JNI ENV ACQUIRE **********/
68*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env = aws_jni_acquire_thread_env(binding->jvm);
69*3c7ae9deSAndroid Build Coastguard Worker     if (env == NULL) {
70*3c7ae9deSAndroid Build Coastguard Worker         /* If we can't get an environment, then the JVM is probably shutting down.  Don't crash. */
71*3c7ae9deSAndroid Build Coastguard Worker         return;
72*3c7ae9deSAndroid Build Coastguard Worker     }
73*3c7ae9deSAndroid Build Coastguard Worker 
74*3c7ae9deSAndroid Build Coastguard Worker     AWS_LOGF_DEBUG(AWS_LS_HTTP_CONNECTION_MANAGER, "ConnManager Shutdown Complete");
75*3c7ae9deSAndroid Build Coastguard Worker     jobject java_http_conn_manager = (*env)->NewLocalRef(env, binding->java_http_conn_manager);
76*3c7ae9deSAndroid Build Coastguard Worker     if (java_http_conn_manager != NULL) {
77*3c7ae9deSAndroid Build Coastguard Worker         (*env)->CallVoidMethod(
78*3c7ae9deSAndroid Build Coastguard Worker             env, java_http_conn_manager, http_client_connection_manager_properties.onShutdownComplete);
79*3c7ae9deSAndroid Build Coastguard Worker 
80*3c7ae9deSAndroid Build Coastguard Worker         AWS_FATAL_ASSERT(!aws_jni_check_and_clear_exception(env));
81*3c7ae9deSAndroid Build Coastguard Worker         (*env)->DeleteLocalRef(env, java_http_conn_manager);
82*3c7ae9deSAndroid Build Coastguard Worker     }
83*3c7ae9deSAndroid Build Coastguard Worker 
84*3c7ae9deSAndroid Build Coastguard Worker     // We're done with this wrapper, free it.
85*3c7ae9deSAndroid Build Coastguard Worker     JavaVM *jvm = binding->jvm;
86*3c7ae9deSAndroid Build Coastguard Worker     s_destroy_manager_binding(binding, env);
87*3c7ae9deSAndroid Build Coastguard Worker 
88*3c7ae9deSAndroid Build Coastguard Worker     aws_jni_release_thread_env(jvm, env);
89*3c7ae9deSAndroid Build Coastguard Worker     /********** JNI ENV RELEASE **********/
90*3c7ae9deSAndroid Build Coastguard Worker }
91*3c7ae9deSAndroid Build Coastguard Worker 
Java_software_amazon_awssdk_crt_http_HttpClientConnectionManager_httpClientConnectionManagerNew(JNIEnv * env,jclass jni_class,jobject conn_manager_jobject,jlong jni_client_bootstrap,jlong jni_socket_options,jlong jni_tls_ctx,jlong jni_tls_connection_options,jlong jni_window_size,jbyteArray jni_endpoint,jint jni_port,jint jni_max_conns,jint jni_proxy_connection_type,jbyteArray jni_proxy_host,jint jni_proxy_port,jlong jni_proxy_tls_context,jint jni_proxy_authorization_type,jbyteArray jni_proxy_authorization_username,jbyteArray jni_proxy_authorization_password,jint jni_environment_variable_proxy_connection_type,jlong jni_environment_variable_proxy_tls_connection_options,jint jni_environment_variable_type,jboolean jni_manual_window_management,jlong jni_max_connection_idle_in_milliseconds,jlong jni_monitoring_throughput_threshold_in_bytes_per_second,jint jni_monitoring_failure_interval_in_seconds,jint jni_expected_protocol_version)92*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT jlong JNICALL Java_software_amazon_awssdk_crt_http_HttpClientConnectionManager_httpClientConnectionManagerNew(
93*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
94*3c7ae9deSAndroid Build Coastguard Worker     jclass jni_class,
95*3c7ae9deSAndroid Build Coastguard Worker     jobject conn_manager_jobject,
96*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_client_bootstrap,
97*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_socket_options,
98*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_tls_ctx,
99*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_tls_connection_options,
100*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_window_size,
101*3c7ae9deSAndroid Build Coastguard Worker     jbyteArray jni_endpoint,
102*3c7ae9deSAndroid Build Coastguard Worker     jint jni_port,
103*3c7ae9deSAndroid Build Coastguard Worker     jint jni_max_conns,
104*3c7ae9deSAndroid Build Coastguard Worker     jint jni_proxy_connection_type,
105*3c7ae9deSAndroid Build Coastguard Worker     jbyteArray jni_proxy_host,
106*3c7ae9deSAndroid Build Coastguard Worker     jint jni_proxy_port,
107*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_proxy_tls_context,
108*3c7ae9deSAndroid Build Coastguard Worker     jint jni_proxy_authorization_type,
109*3c7ae9deSAndroid Build Coastguard Worker     jbyteArray jni_proxy_authorization_username,
110*3c7ae9deSAndroid Build Coastguard Worker     jbyteArray jni_proxy_authorization_password,
111*3c7ae9deSAndroid Build Coastguard Worker     jint jni_environment_variable_proxy_connection_type,
112*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_environment_variable_proxy_tls_connection_options,
113*3c7ae9deSAndroid Build Coastguard Worker     jint jni_environment_variable_type,
114*3c7ae9deSAndroid Build Coastguard Worker     jboolean jni_manual_window_management,
115*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_max_connection_idle_in_milliseconds,
116*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_monitoring_throughput_threshold_in_bytes_per_second,
117*3c7ae9deSAndroid Build Coastguard Worker     jint jni_monitoring_failure_interval_in_seconds,
118*3c7ae9deSAndroid Build Coastguard Worker     jint jni_expected_protocol_version) {
119*3c7ae9deSAndroid Build Coastguard Worker 
120*3c7ae9deSAndroid Build Coastguard Worker     (void)jni_class;
121*3c7ae9deSAndroid Build Coastguard Worker     (void)jni_expected_protocol_version;
122*3c7ae9deSAndroid Build Coastguard Worker     aws_cache_jni_ids(env);
123*3c7ae9deSAndroid Build Coastguard Worker 
124*3c7ae9deSAndroid Build Coastguard Worker     struct aws_client_bootstrap *client_bootstrap = (struct aws_client_bootstrap *)jni_client_bootstrap;
125*3c7ae9deSAndroid Build Coastguard Worker     struct aws_socket_options *socket_options = (struct aws_socket_options *)jni_socket_options;
126*3c7ae9deSAndroid Build Coastguard Worker     struct aws_tls_ctx *tls_ctx = (struct aws_tls_ctx *)jni_tls_ctx;
127*3c7ae9deSAndroid Build Coastguard Worker     struct aws_tls_connection_options *tls_connection_options =
128*3c7ae9deSAndroid Build Coastguard Worker         (struct aws_tls_connection_options *)jni_tls_connection_options;
129*3c7ae9deSAndroid Build Coastguard Worker     struct http_connection_manager_binding *binding = NULL;
130*3c7ae9deSAndroid Build Coastguard Worker 
131*3c7ae9deSAndroid Build Coastguard Worker     if (!client_bootstrap) {
132*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_throw_runtime_exception(env, "ClientBootstrap can't be null");
133*3c7ae9deSAndroid Build Coastguard Worker         return (jlong)NULL;
134*3c7ae9deSAndroid Build Coastguard Worker     }
135*3c7ae9deSAndroid Build Coastguard Worker 
136*3c7ae9deSAndroid Build Coastguard Worker     if (!socket_options) {
137*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_throw_runtime_exception(env, "SocketOptions can't be null");
138*3c7ae9deSAndroid Build Coastguard Worker         return (jlong)NULL;
139*3c7ae9deSAndroid Build Coastguard Worker     }
140*3c7ae9deSAndroid Build Coastguard Worker 
141*3c7ae9deSAndroid Build Coastguard Worker     struct aws_allocator *allocator = aws_jni_get_allocator();
142*3c7ae9deSAndroid Build Coastguard Worker     struct aws_byte_cursor endpoint = aws_jni_byte_cursor_from_jbyteArray_acquire(env, jni_endpoint);
143*3c7ae9deSAndroid Build Coastguard Worker 
144*3c7ae9deSAndroid Build Coastguard Worker     size_t window_size;
145*3c7ae9deSAndroid Build Coastguard Worker     if (aws_size_t_from_java(env, &window_size, jni_window_size, "Initial window size")) {
146*3c7ae9deSAndroid Build Coastguard Worker         goto cleanup;
147*3c7ae9deSAndroid Build Coastguard Worker     }
148*3c7ae9deSAndroid Build Coastguard Worker 
149*3c7ae9deSAndroid Build Coastguard Worker     if (jni_max_conns <= 0) {
150*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_throw_runtime_exception(env, "Max Connections must be > 0");
151*3c7ae9deSAndroid Build Coastguard Worker         goto cleanup;
152*3c7ae9deSAndroid Build Coastguard Worker     }
153*3c7ae9deSAndroid Build Coastguard Worker 
154*3c7ae9deSAndroid Build Coastguard Worker     uint32_t port = (uint32_t)jni_port;
155*3c7ae9deSAndroid Build Coastguard Worker 
156*3c7ae9deSAndroid Build Coastguard Worker     bool new_tls_conn_opts = (jni_tls_ctx != 0 && !tls_connection_options);
157*3c7ae9deSAndroid Build Coastguard Worker 
158*3c7ae9deSAndroid Build Coastguard Worker     struct aws_tls_connection_options tls_conn_options;
159*3c7ae9deSAndroid Build Coastguard Worker     AWS_ZERO_STRUCT(tls_conn_options);
160*3c7ae9deSAndroid Build Coastguard Worker     if (new_tls_conn_opts) {
161*3c7ae9deSAndroid Build Coastguard Worker         aws_tls_connection_options_init_from_ctx(&tls_conn_options, tls_ctx);
162*3c7ae9deSAndroid Build Coastguard Worker         aws_tls_connection_options_set_server_name(&tls_conn_options, allocator, &endpoint);
163*3c7ae9deSAndroid Build Coastguard Worker         tls_connection_options = &tls_conn_options;
164*3c7ae9deSAndroid Build Coastguard Worker     }
165*3c7ae9deSAndroid Build Coastguard Worker 
166*3c7ae9deSAndroid Build Coastguard Worker     binding = aws_mem_calloc(allocator, 1, sizeof(struct http_connection_manager_binding));
167*3c7ae9deSAndroid Build Coastguard Worker     AWS_FATAL_ASSERT(binding);
168*3c7ae9deSAndroid Build Coastguard Worker     binding->java_http_conn_manager = (*env)->NewWeakGlobalRef(env, conn_manager_jobject);
169*3c7ae9deSAndroid Build Coastguard Worker 
170*3c7ae9deSAndroid Build Coastguard Worker     jint jvmresult = (*env)->GetJavaVM(env, &binding->jvm);
171*3c7ae9deSAndroid Build Coastguard Worker     (void)jvmresult;
172*3c7ae9deSAndroid Build Coastguard Worker     AWS_FATAL_ASSERT(jvmresult == 0);
173*3c7ae9deSAndroid Build Coastguard Worker 
174*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_connection_manager_options manager_options;
175*3c7ae9deSAndroid Build Coastguard Worker     AWS_ZERO_STRUCT(manager_options);
176*3c7ae9deSAndroid Build Coastguard Worker 
177*3c7ae9deSAndroid Build Coastguard Worker     manager_options.bootstrap = client_bootstrap;
178*3c7ae9deSAndroid Build Coastguard Worker     manager_options.initial_window_size = window_size;
179*3c7ae9deSAndroid Build Coastguard Worker     manager_options.socket_options = socket_options;
180*3c7ae9deSAndroid Build Coastguard Worker     manager_options.tls_connection_options = tls_connection_options;
181*3c7ae9deSAndroid Build Coastguard Worker     manager_options.host = endpoint;
182*3c7ae9deSAndroid Build Coastguard Worker     manager_options.port = port;
183*3c7ae9deSAndroid Build Coastguard Worker     manager_options.max_connections = (size_t)jni_max_conns;
184*3c7ae9deSAndroid Build Coastguard Worker     manager_options.shutdown_complete_callback = &s_on_http_conn_manager_shutdown_complete_callback;
185*3c7ae9deSAndroid Build Coastguard Worker     manager_options.shutdown_complete_user_data = binding;
186*3c7ae9deSAndroid Build Coastguard Worker     manager_options.monitoring_options = NULL;
187*3c7ae9deSAndroid Build Coastguard Worker     /* TODO: this variable needs to be renamed in aws-c-http. Come back and change it next revision. */
188*3c7ae9deSAndroid Build Coastguard Worker     manager_options.enable_read_back_pressure = jni_manual_window_management;
189*3c7ae9deSAndroid Build Coastguard Worker     manager_options.max_connection_idle_in_milliseconds = jni_max_connection_idle_in_milliseconds;
190*3c7ae9deSAndroid Build Coastguard Worker 
191*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_connection_monitoring_options monitoring_options;
192*3c7ae9deSAndroid Build Coastguard Worker     AWS_ZERO_STRUCT(monitoring_options);
193*3c7ae9deSAndroid Build Coastguard Worker     if (jni_monitoring_throughput_threshold_in_bytes_per_second >= 0 &&
194*3c7ae9deSAndroid Build Coastguard Worker         jni_monitoring_failure_interval_in_seconds >= 2) {
195*3c7ae9deSAndroid Build Coastguard Worker         monitoring_options.minimum_throughput_bytes_per_second =
196*3c7ae9deSAndroid Build Coastguard Worker             jni_monitoring_throughput_threshold_in_bytes_per_second;
197*3c7ae9deSAndroid Build Coastguard Worker         monitoring_options.allowable_throughput_failure_interval_seconds = jni_monitoring_failure_interval_in_seconds;
198*3c7ae9deSAndroid Build Coastguard Worker 
199*3c7ae9deSAndroid Build Coastguard Worker         manager_options.monitoring_options = &monitoring_options;
200*3c7ae9deSAndroid Build Coastguard Worker     }
201*3c7ae9deSAndroid Build Coastguard Worker 
202*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_proxy_options proxy_options;
203*3c7ae9deSAndroid Build Coastguard Worker     AWS_ZERO_STRUCT(proxy_options);
204*3c7ae9deSAndroid Build Coastguard Worker 
205*3c7ae9deSAndroid Build Coastguard Worker     struct aws_tls_connection_options proxy_tls_conn_options;
206*3c7ae9deSAndroid Build Coastguard Worker     AWS_ZERO_STRUCT(proxy_tls_conn_options);
207*3c7ae9deSAndroid Build Coastguard Worker 
208*3c7ae9deSAndroid Build Coastguard Worker     aws_http_proxy_options_jni_init(
209*3c7ae9deSAndroid Build Coastguard Worker         env,
210*3c7ae9deSAndroid Build Coastguard Worker         &proxy_options,
211*3c7ae9deSAndroid Build Coastguard Worker         jni_proxy_connection_type,
212*3c7ae9deSAndroid Build Coastguard Worker         &proxy_tls_conn_options,
213*3c7ae9deSAndroid Build Coastguard Worker         jni_proxy_host,
214*3c7ae9deSAndroid Build Coastguard Worker         jni_proxy_port,
215*3c7ae9deSAndroid Build Coastguard Worker         jni_proxy_authorization_username,
216*3c7ae9deSAndroid Build Coastguard Worker         jni_proxy_authorization_password,
217*3c7ae9deSAndroid Build Coastguard Worker         jni_proxy_authorization_type,
218*3c7ae9deSAndroid Build Coastguard Worker         (struct aws_tls_ctx *)jni_proxy_tls_context);
219*3c7ae9deSAndroid Build Coastguard Worker 
220*3c7ae9deSAndroid Build Coastguard Worker     if (jni_proxy_host != NULL) {
221*3c7ae9deSAndroid Build Coastguard Worker         manager_options.proxy_options = &proxy_options;
222*3c7ae9deSAndroid Build Coastguard Worker     }
223*3c7ae9deSAndroid Build Coastguard Worker 
224*3c7ae9deSAndroid Build Coastguard Worker     struct proxy_env_var_settings proxy_ev_settings;
225*3c7ae9deSAndroid Build Coastguard Worker     AWS_ZERO_STRUCT(proxy_ev_settings);
226*3c7ae9deSAndroid Build Coastguard Worker 
227*3c7ae9deSAndroid Build Coastguard Worker     aws_http_proxy_environment_variable_setting_jni_init(
228*3c7ae9deSAndroid Build Coastguard Worker         &proxy_ev_settings,
229*3c7ae9deSAndroid Build Coastguard Worker         jni_environment_variable_proxy_connection_type,
230*3c7ae9deSAndroid Build Coastguard Worker         jni_environment_variable_type,
231*3c7ae9deSAndroid Build Coastguard Worker         (struct aws_tls_connection_options *)jni_environment_variable_proxy_tls_connection_options);
232*3c7ae9deSAndroid Build Coastguard Worker 
233*3c7ae9deSAndroid Build Coastguard Worker     manager_options.proxy_ev_settings = &proxy_ev_settings;
234*3c7ae9deSAndroid Build Coastguard Worker 
235*3c7ae9deSAndroid Build Coastguard Worker     binding->manager = aws_http_connection_manager_new(allocator, &manager_options);
236*3c7ae9deSAndroid Build Coastguard Worker     if (binding->manager == NULL) {
237*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_throw_runtime_exception(
238*3c7ae9deSAndroid Build Coastguard Worker             env, "Failed to create connection manager: %s", aws_error_str(aws_last_error()));
239*3c7ae9deSAndroid Build Coastguard Worker     }
240*3c7ae9deSAndroid Build Coastguard Worker 
241*3c7ae9deSAndroid Build Coastguard Worker     aws_http_proxy_options_jni_clean_up(
242*3c7ae9deSAndroid Build Coastguard Worker         env, &proxy_options, jni_proxy_host, jni_proxy_authorization_username, jni_proxy_authorization_password);
243*3c7ae9deSAndroid Build Coastguard Worker 
244*3c7ae9deSAndroid Build Coastguard Worker     if (new_tls_conn_opts) {
245*3c7ae9deSAndroid Build Coastguard Worker         aws_tls_connection_options_clean_up(&tls_conn_options);
246*3c7ae9deSAndroid Build Coastguard Worker     }
247*3c7ae9deSAndroid Build Coastguard Worker 
248*3c7ae9deSAndroid Build Coastguard Worker cleanup:
249*3c7ae9deSAndroid Build Coastguard Worker     aws_jni_byte_cursor_from_jbyteArray_release(env, jni_endpoint, endpoint);
250*3c7ae9deSAndroid Build Coastguard Worker 
251*3c7ae9deSAndroid Build Coastguard Worker     if (binding->manager == NULL) {
252*3c7ae9deSAndroid Build Coastguard Worker         s_destroy_manager_binding(binding, env);
253*3c7ae9deSAndroid Build Coastguard Worker         binding = NULL;
254*3c7ae9deSAndroid Build Coastguard Worker     }
255*3c7ae9deSAndroid Build Coastguard Worker 
256*3c7ae9deSAndroid Build Coastguard Worker     return (jlong)binding;
257*3c7ae9deSAndroid Build Coastguard Worker }
258*3c7ae9deSAndroid Build Coastguard Worker 
259*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT void JNICALL
Java_software_amazon_awssdk_crt_http_HttpClientConnectionManager_httpClientConnectionManagerRelease(JNIEnv * env,jclass jni_class,jlong jni_conn_manager_binding)260*3c7ae9deSAndroid Build Coastguard Worker     Java_software_amazon_awssdk_crt_http_HttpClientConnectionManager_httpClientConnectionManagerRelease(
261*3c7ae9deSAndroid Build Coastguard Worker         JNIEnv *env,
262*3c7ae9deSAndroid Build Coastguard Worker         jclass jni_class,
263*3c7ae9deSAndroid Build Coastguard Worker         jlong jni_conn_manager_binding) {
264*3c7ae9deSAndroid Build Coastguard Worker 
265*3c7ae9deSAndroid Build Coastguard Worker     (void)jni_class;
266*3c7ae9deSAndroid Build Coastguard Worker     aws_cache_jni_ids(env);
267*3c7ae9deSAndroid Build Coastguard Worker 
268*3c7ae9deSAndroid Build Coastguard Worker     struct http_connection_manager_binding *binding =
269*3c7ae9deSAndroid Build Coastguard Worker         (struct http_connection_manager_binding *)jni_conn_manager_binding;
270*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_connection_manager *conn_manager = binding->manager;
271*3c7ae9deSAndroid Build Coastguard Worker 
272*3c7ae9deSAndroid Build Coastguard Worker     if (!conn_manager) {
273*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_throw_runtime_exception(env, "Connection Manager can't be null");
274*3c7ae9deSAndroid Build Coastguard Worker         return;
275*3c7ae9deSAndroid Build Coastguard Worker     }
276*3c7ae9deSAndroid Build Coastguard Worker 
277*3c7ae9deSAndroid Build Coastguard Worker     AWS_LOGF_DEBUG(AWS_LS_HTTP_CONNECTION, "Releasing ConnManager: id: %p", (void *)conn_manager);
278*3c7ae9deSAndroid Build Coastguard Worker     aws_http_connection_manager_release(conn_manager);
279*3c7ae9deSAndroid Build Coastguard Worker }
280*3c7ae9deSAndroid Build Coastguard Worker 
281*3c7ae9deSAndroid Build Coastguard Worker /********************************************************************************************************************/
282*3c7ae9deSAndroid Build Coastguard Worker 
s_destroy_connection_binding(struct aws_http_connection_binding * binding,JNIEnv * env)283*3c7ae9deSAndroid Build Coastguard Worker static void s_destroy_connection_binding(struct aws_http_connection_binding *binding, JNIEnv *env) {
284*3c7ae9deSAndroid Build Coastguard Worker     if (binding == NULL || env == NULL) {
285*3c7ae9deSAndroid Build Coastguard Worker         return;
286*3c7ae9deSAndroid Build Coastguard Worker     }
287*3c7ae9deSAndroid Build Coastguard Worker 
288*3c7ae9deSAndroid Build Coastguard Worker     if (binding->java_acquire_connection_future != NULL) {
289*3c7ae9deSAndroid Build Coastguard Worker         (*env)->DeleteGlobalRef(env, binding->java_acquire_connection_future);
290*3c7ae9deSAndroid Build Coastguard Worker     }
291*3c7ae9deSAndroid Build Coastguard Worker 
292*3c7ae9deSAndroid Build Coastguard Worker     if (binding->manager != NULL && binding->connection != NULL) {
293*3c7ae9deSAndroid Build Coastguard Worker         aws_http_connection_manager_release_connection(binding->manager, binding->connection);
294*3c7ae9deSAndroid Build Coastguard Worker     }
295*3c7ae9deSAndroid Build Coastguard Worker 
296*3c7ae9deSAndroid Build Coastguard Worker     aws_mem_release(aws_jni_get_allocator(), binding);
297*3c7ae9deSAndroid Build Coastguard Worker }
298*3c7ae9deSAndroid Build Coastguard Worker 
s_on_http_conn_acquisition_callback(struct aws_http_connection * connection,int error_code,void * user_data)299*3c7ae9deSAndroid Build Coastguard Worker static void s_on_http_conn_acquisition_callback(
300*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_connection *connection,
301*3c7ae9deSAndroid Build Coastguard Worker     int error_code,
302*3c7ae9deSAndroid Build Coastguard Worker     void *user_data) {
303*3c7ae9deSAndroid Build Coastguard Worker 
304*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_connection_binding *binding = (struct aws_http_connection_binding *)user_data;
305*3c7ae9deSAndroid Build Coastguard Worker     binding->connection = connection;
306*3c7ae9deSAndroid Build Coastguard Worker 
307*3c7ae9deSAndroid Build Coastguard Worker     /********** JNI ENV ACQUIRE **********/
308*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env = aws_jni_acquire_thread_env(binding->jvm);
309*3c7ae9deSAndroid Build Coastguard Worker     if (env == NULL) {
310*3c7ae9deSAndroid Build Coastguard Worker         /* If we can't get an environment, then the JVM is probably shutting down.  Don't crash. */
311*3c7ae9deSAndroid Build Coastguard Worker         return;
312*3c7ae9deSAndroid Build Coastguard Worker     }
313*3c7ae9deSAndroid Build Coastguard Worker 
314*3c7ae9deSAndroid Build Coastguard Worker     jint jni_error_code = (jint)error_code;
315*3c7ae9deSAndroid Build Coastguard Worker 
316*3c7ae9deSAndroid Build Coastguard Worker     AWS_LOGF_DEBUG(
317*3c7ae9deSAndroid Build Coastguard Worker         AWS_LS_HTTP_CONNECTION,
318*3c7ae9deSAndroid Build Coastguard Worker         "ConnManager Acquired Conn: conn: %p, manager: %p, err_code: %d,  err_str: %s",
319*3c7ae9deSAndroid Build Coastguard Worker         (void *)connection,
320*3c7ae9deSAndroid Build Coastguard Worker         (void *)binding->manager,
321*3c7ae9deSAndroid Build Coastguard Worker         error_code,
322*3c7ae9deSAndroid Build Coastguard Worker         aws_error_str(error_code));
323*3c7ae9deSAndroid Build Coastguard Worker 
324*3c7ae9deSAndroid Build Coastguard Worker     (*env)->CallStaticVoidMethod(
325*3c7ae9deSAndroid Build Coastguard Worker         env,
326*3c7ae9deSAndroid Build Coastguard Worker         http_client_connection_properties.http_client_connection_class,
327*3c7ae9deSAndroid Build Coastguard Worker         http_client_connection_properties.on_connection_acquired_method_id,
328*3c7ae9deSAndroid Build Coastguard Worker         binding->java_acquire_connection_future,
329*3c7ae9deSAndroid Build Coastguard Worker         (jlong)binding,
330*3c7ae9deSAndroid Build Coastguard Worker         jni_error_code);
331*3c7ae9deSAndroid Build Coastguard Worker 
332*3c7ae9deSAndroid Build Coastguard Worker     AWS_FATAL_ASSERT(!aws_jni_check_and_clear_exception(env));
333*3c7ae9deSAndroid Build Coastguard Worker 
334*3c7ae9deSAndroid Build Coastguard Worker     JavaVM *jvm = binding->jvm;
335*3c7ae9deSAndroid Build Coastguard Worker     if (error_code) {
336*3c7ae9deSAndroid Build Coastguard Worker         s_destroy_connection_binding(binding, env);
337*3c7ae9deSAndroid Build Coastguard Worker     }
338*3c7ae9deSAndroid Build Coastguard Worker 
339*3c7ae9deSAndroid Build Coastguard Worker     aws_jni_release_thread_env(jvm, env);
340*3c7ae9deSAndroid Build Coastguard Worker     /********** JNI ENV RELEASE **********/
341*3c7ae9deSAndroid Build Coastguard Worker }
342*3c7ae9deSAndroid Build Coastguard Worker 
343*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT void JNICALL
Java_software_amazon_awssdk_crt_http_HttpClientConnectionManager_httpClientConnectionManagerAcquireConnection(JNIEnv * env,jclass jni_class,jlong jni_conn_manager_binding,jobject acquire_future)344*3c7ae9deSAndroid Build Coastguard Worker     Java_software_amazon_awssdk_crt_http_HttpClientConnectionManager_httpClientConnectionManagerAcquireConnection(
345*3c7ae9deSAndroid Build Coastguard Worker         JNIEnv *env,
346*3c7ae9deSAndroid Build Coastguard Worker         jclass jni_class,
347*3c7ae9deSAndroid Build Coastguard Worker         jlong jni_conn_manager_binding,
348*3c7ae9deSAndroid Build Coastguard Worker         jobject acquire_future) {
349*3c7ae9deSAndroid Build Coastguard Worker 
350*3c7ae9deSAndroid Build Coastguard Worker     (void)jni_class;
351*3c7ae9deSAndroid Build Coastguard Worker     aws_cache_jni_ids(env);
352*3c7ae9deSAndroid Build Coastguard Worker 
353*3c7ae9deSAndroid Build Coastguard Worker     struct http_connection_manager_binding *manager_binding =
354*3c7ae9deSAndroid Build Coastguard Worker         (struct http_connection_manager_binding *)jni_conn_manager_binding;
355*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_connection_manager *conn_manager = manager_binding->manager;
356*3c7ae9deSAndroid Build Coastguard Worker 
357*3c7ae9deSAndroid Build Coastguard Worker     if (!conn_manager) {
358*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_throw_runtime_exception(env, "Connection Manager can't be null");
359*3c7ae9deSAndroid Build Coastguard Worker         return;
360*3c7ae9deSAndroid Build Coastguard Worker     }
361*3c7ae9deSAndroid Build Coastguard Worker 
362*3c7ae9deSAndroid Build Coastguard Worker     jobject future_ref = (*env)->NewGlobalRef(env, acquire_future);
363*3c7ae9deSAndroid Build Coastguard Worker     if (future_ref == NULL) {
364*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_throw_runtime_exception(
365*3c7ae9deSAndroid Build Coastguard Worker             env, "httpClientConnectionManagerAcquireConnection: failed to obtain ref to future");
366*3c7ae9deSAndroid Build Coastguard Worker         return;
367*3c7ae9deSAndroid Build Coastguard Worker     }
368*3c7ae9deSAndroid Build Coastguard Worker 
369*3c7ae9deSAndroid Build Coastguard Worker     AWS_LOGF_DEBUG(AWS_LS_HTTP_CONNECTION, "Requesting a new connection from conn_manager: %p", (void *)conn_manager);
370*3c7ae9deSAndroid Build Coastguard Worker 
371*3c7ae9deSAndroid Build Coastguard Worker     struct aws_allocator *allocator = aws_jni_get_allocator();
372*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_connection_binding *connection_binding =
373*3c7ae9deSAndroid Build Coastguard Worker         aws_mem_calloc(allocator, 1, sizeof(struct aws_http_connection_binding));
374*3c7ae9deSAndroid Build Coastguard Worker     connection_binding->java_acquire_connection_future = future_ref;
375*3c7ae9deSAndroid Build Coastguard Worker     connection_binding->manager = conn_manager;
376*3c7ae9deSAndroid Build Coastguard Worker 
377*3c7ae9deSAndroid Build Coastguard Worker     jint jvmresult = (*env)->GetJavaVM(env, &connection_binding->jvm);
378*3c7ae9deSAndroid Build Coastguard Worker     (void)jvmresult;
379*3c7ae9deSAndroid Build Coastguard Worker     AWS_FATAL_ASSERT(jvmresult == 0);
380*3c7ae9deSAndroid Build Coastguard Worker 
381*3c7ae9deSAndroid Build Coastguard Worker     aws_http_connection_manager_acquire_connection(
382*3c7ae9deSAndroid Build Coastguard Worker         conn_manager, &s_on_http_conn_acquisition_callback, (void *)connection_binding);
383*3c7ae9deSAndroid Build Coastguard Worker }
384*3c7ae9deSAndroid Build Coastguard Worker 
Java_software_amazon_awssdk_crt_http_HttpClientConnection_httpClientConnectionReleaseManaged(JNIEnv * env,jclass jni_class,jlong jni_connection_binding)385*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT void JNICALL Java_software_amazon_awssdk_crt_http_HttpClientConnection_httpClientConnectionReleaseManaged(
386*3c7ae9deSAndroid Build Coastguard Worker     JNIEnv *env,
387*3c7ae9deSAndroid Build Coastguard Worker     jclass jni_class,
388*3c7ae9deSAndroid Build Coastguard Worker     jlong jni_connection_binding) {
389*3c7ae9deSAndroid Build Coastguard Worker 
390*3c7ae9deSAndroid Build Coastguard Worker     (void)jni_class;
391*3c7ae9deSAndroid Build Coastguard Worker     aws_cache_jni_ids(env);
392*3c7ae9deSAndroid Build Coastguard Worker 
393*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_connection_binding *binding = (struct aws_http_connection_binding *)jni_connection_binding;
394*3c7ae9deSAndroid Build Coastguard Worker 
395*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_connection_manager *conn_manager = binding->manager;
396*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_connection *conn = binding->connection;
397*3c7ae9deSAndroid Build Coastguard Worker 
398*3c7ae9deSAndroid Build Coastguard Worker     if (!conn_manager) {
399*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_throw_runtime_exception(env, "Connection Manager can't be null");
400*3c7ae9deSAndroid Build Coastguard Worker         return;
401*3c7ae9deSAndroid Build Coastguard Worker     }
402*3c7ae9deSAndroid Build Coastguard Worker 
403*3c7ae9deSAndroid Build Coastguard Worker     if (!conn) {
404*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_throw_runtime_exception(env, "Connection can't be null");
405*3c7ae9deSAndroid Build Coastguard Worker         return;
406*3c7ae9deSAndroid Build Coastguard Worker     }
407*3c7ae9deSAndroid Build Coastguard Worker 
408*3c7ae9deSAndroid Build Coastguard Worker     AWS_LOGF_DEBUG(
409*3c7ae9deSAndroid Build Coastguard Worker         AWS_LS_HTTP_CONNECTION,
410*3c7ae9deSAndroid Build Coastguard Worker         "ConnManager Releasing Conn: manager: %p, conn: %p",
411*3c7ae9deSAndroid Build Coastguard Worker         (void *)conn_manager,
412*3c7ae9deSAndroid Build Coastguard Worker         (void *)conn);
413*3c7ae9deSAndroid Build Coastguard Worker 
414*3c7ae9deSAndroid Build Coastguard Worker     s_destroy_connection_binding(binding, env);
415*3c7ae9deSAndroid Build Coastguard Worker }
416*3c7ae9deSAndroid Build Coastguard Worker 
417*3c7ae9deSAndroid Build Coastguard Worker JNIEXPORT jobject JNICALL
Java_software_amazon_awssdk_crt_http_HttpClientConnectionManager_httpConnectionManagerFetchMetrics(JNIEnv * env,jclass jni_class,jlong jni_conn_manager_binding)418*3c7ae9deSAndroid Build Coastguard Worker     Java_software_amazon_awssdk_crt_http_HttpClientConnectionManager_httpConnectionManagerFetchMetrics(
419*3c7ae9deSAndroid Build Coastguard Worker         JNIEnv *env,
420*3c7ae9deSAndroid Build Coastguard Worker         jclass jni_class,
421*3c7ae9deSAndroid Build Coastguard Worker         jlong jni_conn_manager_binding) {
422*3c7ae9deSAndroid Build Coastguard Worker     (void)jni_class;
423*3c7ae9deSAndroid Build Coastguard Worker     aws_cache_jni_ids(env);
424*3c7ae9deSAndroid Build Coastguard Worker 
425*3c7ae9deSAndroid Build Coastguard Worker     struct http_connection_manager_binding *manager_binding =
426*3c7ae9deSAndroid Build Coastguard Worker         (struct http_connection_manager_binding *)jni_conn_manager_binding;
427*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_connection_manager *conn_manager = manager_binding->manager;
428*3c7ae9deSAndroid Build Coastguard Worker 
429*3c7ae9deSAndroid Build Coastguard Worker     if (!conn_manager) {
430*3c7ae9deSAndroid Build Coastguard Worker         aws_jni_throw_runtime_exception(env, "Connection Manager can't be null");
431*3c7ae9deSAndroid Build Coastguard Worker         return NULL;
432*3c7ae9deSAndroid Build Coastguard Worker     }
433*3c7ae9deSAndroid Build Coastguard Worker 
434*3c7ae9deSAndroid Build Coastguard Worker     struct aws_http_manager_metrics metrics;
435*3c7ae9deSAndroid Build Coastguard Worker     aws_http_connection_manager_fetch_metrics(conn_manager, &metrics);
436*3c7ae9deSAndroid Build Coastguard Worker 
437*3c7ae9deSAndroid Build Coastguard Worker     return (*env)->NewObject(
438*3c7ae9deSAndroid Build Coastguard Worker         env,
439*3c7ae9deSAndroid Build Coastguard Worker         http_manager_metrics_properties.http_manager_metrics_class,
440*3c7ae9deSAndroid Build Coastguard Worker         http_manager_metrics_properties.constructor_method_id,
441*3c7ae9deSAndroid Build Coastguard Worker         (jlong)metrics.available_concurrency,
442*3c7ae9deSAndroid Build Coastguard Worker         (jlong)metrics.pending_concurrency_acquires,
443*3c7ae9deSAndroid Build Coastguard Worker         (jlong)metrics.leased_concurrency);
444*3c7ae9deSAndroid Build Coastguard Worker }
445*3c7ae9deSAndroid Build Coastguard Worker 
446*3c7ae9deSAndroid Build Coastguard Worker #if UINTPTR_MAX == 0xffffffff
447*3c7ae9deSAndroid Build Coastguard Worker #    if defined(_MSC_VER)
448*3c7ae9deSAndroid Build Coastguard Worker #        pragma warning(pop)
449*3c7ae9deSAndroid Build Coastguard Worker #    else
450*3c7ae9deSAndroid Build Coastguard Worker #        pragma GCC diagnostic pop
451*3c7ae9deSAndroid Build Coastguard Worker #    endif
452*3c7ae9deSAndroid Build Coastguard Worker #endif
453