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 "http_request_utils.h"
7*3c7ae9deSAndroid Build Coastguard Worker
8*3c7ae9deSAndroid Build Coastguard Worker #include "crt.h"
9*3c7ae9deSAndroid Build Coastguard Worker #include "java_class_ids.h"
10*3c7ae9deSAndroid Build Coastguard Worker
11*3c7ae9deSAndroid Build Coastguard Worker #include <aws/common/byte_order.h>
12*3c7ae9deSAndroid Build Coastguard Worker #include <aws/http/http.h>
13*3c7ae9deSAndroid Build Coastguard Worker #include <aws/http/request_response.h>
14*3c7ae9deSAndroid Build Coastguard Worker #include <aws/io/stream.h>
15*3c7ae9deSAndroid Build Coastguard Worker
16*3c7ae9deSAndroid Build Coastguard Worker #if _MSC_VER
17*3c7ae9deSAndroid Build Coastguard Worker # pragma warning(disable : 4204) /* non-constant aggregate initializer */
18*3c7ae9deSAndroid Build Coastguard Worker #endif
19*3c7ae9deSAndroid Build Coastguard Worker
20*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_request_body_stream_impl {
21*3c7ae9deSAndroid Build Coastguard Worker struct aws_input_stream base;
22*3c7ae9deSAndroid Build Coastguard Worker struct aws_allocator *allocator;
23*3c7ae9deSAndroid Build Coastguard Worker JavaVM *jvm;
24*3c7ae9deSAndroid Build Coastguard Worker jobject http_request_body_stream;
25*3c7ae9deSAndroid Build Coastguard Worker bool body_done;
26*3c7ae9deSAndroid Build Coastguard Worker bool is_valid;
27*3c7ae9deSAndroid Build Coastguard Worker };
28*3c7ae9deSAndroid Build Coastguard Worker
s_aws_input_stream_seek(struct aws_input_stream * stream,int64_t offset,enum aws_stream_seek_basis basis)29*3c7ae9deSAndroid Build Coastguard Worker static int s_aws_input_stream_seek(struct aws_input_stream *stream, int64_t offset, enum aws_stream_seek_basis basis) {
30*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_request_body_stream_impl *impl =
31*3c7ae9deSAndroid Build Coastguard Worker AWS_CONTAINER_OF(stream, struct aws_http_request_body_stream_impl, base);
32*3c7ae9deSAndroid Build Coastguard Worker
33*3c7ae9deSAndroid Build Coastguard Worker if (!impl->is_valid) {
34*3c7ae9deSAndroid Build Coastguard Worker return aws_raise_error(AWS_ERROR_HTTP_INVALID_BODY_STREAM);
35*3c7ae9deSAndroid Build Coastguard Worker }
36*3c7ae9deSAndroid Build Coastguard Worker
37*3c7ae9deSAndroid Build Coastguard Worker int result = AWS_OP_SUCCESS;
38*3c7ae9deSAndroid Build Coastguard Worker if (impl->http_request_body_stream != NULL) {
39*3c7ae9deSAndroid Build Coastguard Worker if (basis != AWS_SSB_BEGIN || offset != 0) {
40*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_ERR;
41*3c7ae9deSAndroid Build Coastguard Worker }
42*3c7ae9deSAndroid Build Coastguard Worker
43*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV ACQUIRE **********/
44*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env = aws_jni_acquire_thread_env(impl->jvm);
45*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
46*3c7ae9deSAndroid Build Coastguard Worker /* If we can't get an environment, then the JVM is probably shutting down. Don't crash. */
47*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_ERR;
48*3c7ae9deSAndroid Build Coastguard Worker }
49*3c7ae9deSAndroid Build Coastguard Worker
50*3c7ae9deSAndroid Build Coastguard Worker if (!(*env)->CallBooleanMethod(
51*3c7ae9deSAndroid Build Coastguard Worker env, impl->http_request_body_stream, http_request_body_stream_properties.reset_position)) {
52*3c7ae9deSAndroid Build Coastguard Worker result = aws_raise_error(AWS_ERROR_HTTP_CALLBACK_FAILURE);
53*3c7ae9deSAndroid Build Coastguard Worker }
54*3c7ae9deSAndroid Build Coastguard Worker
55*3c7ae9deSAndroid Build Coastguard Worker if (aws_jni_check_and_clear_exception(env)) {
56*3c7ae9deSAndroid Build Coastguard Worker result = aws_raise_error(AWS_ERROR_HTTP_CALLBACK_FAILURE);
57*3c7ae9deSAndroid Build Coastguard Worker }
58*3c7ae9deSAndroid Build Coastguard Worker
59*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(impl->jvm, env);
60*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE **********/
61*3c7ae9deSAndroid Build Coastguard Worker }
62*3c7ae9deSAndroid Build Coastguard Worker
63*3c7ae9deSAndroid Build Coastguard Worker if (result == AWS_OP_SUCCESS) {
64*3c7ae9deSAndroid Build Coastguard Worker impl->body_done = false;
65*3c7ae9deSAndroid Build Coastguard Worker }
66*3c7ae9deSAndroid Build Coastguard Worker
67*3c7ae9deSAndroid Build Coastguard Worker return result;
68*3c7ae9deSAndroid Build Coastguard Worker }
69*3c7ae9deSAndroid Build Coastguard Worker
s_aws_input_stream_read(struct aws_input_stream * stream,struct aws_byte_buf * dest)70*3c7ae9deSAndroid Build Coastguard Worker static int s_aws_input_stream_read(struct aws_input_stream *stream, struct aws_byte_buf *dest) {
71*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_request_body_stream_impl *impl =
72*3c7ae9deSAndroid Build Coastguard Worker AWS_CONTAINER_OF(stream, struct aws_http_request_body_stream_impl, base);
73*3c7ae9deSAndroid Build Coastguard Worker
74*3c7ae9deSAndroid Build Coastguard Worker if (!impl->is_valid) {
75*3c7ae9deSAndroid Build Coastguard Worker return aws_raise_error(AWS_ERROR_HTTP_INVALID_BODY_STREAM);
76*3c7ae9deSAndroid Build Coastguard Worker }
77*3c7ae9deSAndroid Build Coastguard Worker
78*3c7ae9deSAndroid Build Coastguard Worker if (impl->http_request_body_stream == NULL) {
79*3c7ae9deSAndroid Build Coastguard Worker impl->body_done = true;
80*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_SUCCESS;
81*3c7ae9deSAndroid Build Coastguard Worker }
82*3c7ae9deSAndroid Build Coastguard Worker
83*3c7ae9deSAndroid Build Coastguard Worker if (impl->body_done) {
84*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_SUCCESS;
85*3c7ae9deSAndroid Build Coastguard Worker }
86*3c7ae9deSAndroid Build Coastguard Worker
87*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV ACQUIRE **********/
88*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env = aws_jni_acquire_thread_env(impl->jvm);
89*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
90*3c7ae9deSAndroid Build Coastguard Worker /* If we can't get an environment, then the JVM is probably shutting down. Don't crash. */
91*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_ERR;
92*3c7ae9deSAndroid Build Coastguard Worker }
93*3c7ae9deSAndroid Build Coastguard Worker
94*3c7ae9deSAndroid Build Coastguard Worker size_t out_remaining = dest->capacity - dest->len;
95*3c7ae9deSAndroid Build Coastguard Worker
96*3c7ae9deSAndroid Build Coastguard Worker jobject direct_buffer = aws_jni_direct_byte_buffer_from_raw_ptr(env, dest->buffer + dest->len, out_remaining);
97*3c7ae9deSAndroid Build Coastguard Worker
98*3c7ae9deSAndroid Build Coastguard Worker impl->body_done = (*env)->CallBooleanMethod(
99*3c7ae9deSAndroid Build Coastguard Worker env, impl->http_request_body_stream, http_request_body_stream_properties.send_outgoing_body, direct_buffer);
100*3c7ae9deSAndroid Build Coastguard Worker
101*3c7ae9deSAndroid Build Coastguard Worker int result = AWS_OP_SUCCESS;
102*3c7ae9deSAndroid Build Coastguard Worker if (aws_jni_check_and_clear_exception(env)) {
103*3c7ae9deSAndroid Build Coastguard Worker result = aws_raise_error(AWS_ERROR_HTTP_CALLBACK_FAILURE);
104*3c7ae9deSAndroid Build Coastguard Worker } else {
105*3c7ae9deSAndroid Build Coastguard Worker size_t amt_written = aws_jni_byte_buffer_get_position(env, direct_buffer);
106*3c7ae9deSAndroid Build Coastguard Worker dest->len += amt_written;
107*3c7ae9deSAndroid Build Coastguard Worker }
108*3c7ae9deSAndroid Build Coastguard Worker
109*3c7ae9deSAndroid Build Coastguard Worker (*env)->DeleteLocalRef(env, direct_buffer);
110*3c7ae9deSAndroid Build Coastguard Worker
111*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(impl->jvm, env);
112*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE **********/
113*3c7ae9deSAndroid Build Coastguard Worker
114*3c7ae9deSAndroid Build Coastguard Worker return result;
115*3c7ae9deSAndroid Build Coastguard Worker }
116*3c7ae9deSAndroid Build Coastguard Worker
s_aws_input_stream_get_status(struct aws_input_stream * stream,struct aws_stream_status * status)117*3c7ae9deSAndroid Build Coastguard Worker static int s_aws_input_stream_get_status(struct aws_input_stream *stream, struct aws_stream_status *status) {
118*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_request_body_stream_impl *impl =
119*3c7ae9deSAndroid Build Coastguard Worker AWS_CONTAINER_OF(stream, struct aws_http_request_body_stream_impl, base);
120*3c7ae9deSAndroid Build Coastguard Worker
121*3c7ae9deSAndroid Build Coastguard Worker status->is_end_of_stream = impl->body_done;
122*3c7ae9deSAndroid Build Coastguard Worker status->is_valid = impl->is_valid;
123*3c7ae9deSAndroid Build Coastguard Worker
124*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_SUCCESS;
125*3c7ae9deSAndroid Build Coastguard Worker }
126*3c7ae9deSAndroid Build Coastguard Worker
s_aws_input_stream_get_length(struct aws_input_stream * stream,int64_t * length)127*3c7ae9deSAndroid Build Coastguard Worker static int s_aws_input_stream_get_length(struct aws_input_stream *stream, int64_t *length) {
128*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(length && "NULL length out param passed to JNI aws_input_stream_get_length");
129*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_request_body_stream_impl *impl =
130*3c7ae9deSAndroid Build Coastguard Worker AWS_CONTAINER_OF(stream, struct aws_http_request_body_stream_impl, base);
131*3c7ae9deSAndroid Build Coastguard Worker
132*3c7ae9deSAndroid Build Coastguard Worker if (impl->http_request_body_stream != NULL) {
133*3c7ae9deSAndroid Build Coastguard Worker
134*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV ACQUIRE **********/
135*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env = aws_jni_acquire_thread_env(impl->jvm);
136*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
137*3c7ae9deSAndroid Build Coastguard Worker /* If we can't get an environment, then the JVM is probably shutting down. Don't crash. */
138*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_ERR;
139*3c7ae9deSAndroid Build Coastguard Worker }
140*3c7ae9deSAndroid Build Coastguard Worker
141*3c7ae9deSAndroid Build Coastguard Worker *length =
142*3c7ae9deSAndroid Build Coastguard Worker (*env)->CallLongMethod(env, impl->http_request_body_stream, http_request_body_stream_properties.get_length);
143*3c7ae9deSAndroid Build Coastguard Worker
144*3c7ae9deSAndroid Build Coastguard Worker int result = AWS_OP_SUCCESS;
145*3c7ae9deSAndroid Build Coastguard Worker if (aws_jni_check_and_clear_exception(env)) {
146*3c7ae9deSAndroid Build Coastguard Worker result = aws_raise_error(AWS_ERROR_HTTP_CALLBACK_FAILURE);
147*3c7ae9deSAndroid Build Coastguard Worker }
148*3c7ae9deSAndroid Build Coastguard Worker
149*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(impl->jvm, env);
150*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE **********/
151*3c7ae9deSAndroid Build Coastguard Worker
152*3c7ae9deSAndroid Build Coastguard Worker return result;
153*3c7ae9deSAndroid Build Coastguard Worker }
154*3c7ae9deSAndroid Build Coastguard Worker
155*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_ERR;
156*3c7ae9deSAndroid Build Coastguard Worker }
157*3c7ae9deSAndroid Build Coastguard Worker
s_aws_input_stream_destroy(struct aws_http_request_body_stream_impl * impl)158*3c7ae9deSAndroid Build Coastguard Worker static void s_aws_input_stream_destroy(struct aws_http_request_body_stream_impl *impl) {
159*3c7ae9deSAndroid Build Coastguard Worker
160*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV ACQUIRE **********/
161*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env = aws_jni_acquire_thread_env(impl->jvm);
162*3c7ae9deSAndroid Build Coastguard Worker if (env == NULL) {
163*3c7ae9deSAndroid Build Coastguard Worker /* If we can't get an environment, then the JVM is probably shutting down. Don't crash. */
164*3c7ae9deSAndroid Build Coastguard Worker return;
165*3c7ae9deSAndroid Build Coastguard Worker }
166*3c7ae9deSAndroid Build Coastguard Worker
167*3c7ae9deSAndroid Build Coastguard Worker if (impl->http_request_body_stream != NULL) {
168*3c7ae9deSAndroid Build Coastguard Worker (*env)->DeleteGlobalRef(env, impl->http_request_body_stream);
169*3c7ae9deSAndroid Build Coastguard Worker }
170*3c7ae9deSAndroid Build Coastguard Worker
171*3c7ae9deSAndroid Build Coastguard Worker aws_jni_release_thread_env(impl->jvm, env);
172*3c7ae9deSAndroid Build Coastguard Worker /********** JNI ENV RELEASE **********/
173*3c7ae9deSAndroid Build Coastguard Worker
174*3c7ae9deSAndroid Build Coastguard Worker aws_mem_release(impl->allocator, impl);
175*3c7ae9deSAndroid Build Coastguard Worker }
176*3c7ae9deSAndroid Build Coastguard Worker
177*3c7ae9deSAndroid Build Coastguard Worker static struct aws_input_stream_vtable s_aws_input_stream_vtable = {
178*3c7ae9deSAndroid Build Coastguard Worker .seek = s_aws_input_stream_seek,
179*3c7ae9deSAndroid Build Coastguard Worker .read = s_aws_input_stream_read,
180*3c7ae9deSAndroid Build Coastguard Worker .get_status = s_aws_input_stream_get_status,
181*3c7ae9deSAndroid Build Coastguard Worker .get_length = s_aws_input_stream_get_length,
182*3c7ae9deSAndroid Build Coastguard Worker };
183*3c7ae9deSAndroid Build Coastguard Worker
aws_input_stream_new_from_java_http_request_body_stream(struct aws_allocator * allocator,JNIEnv * env,jobject http_request_body_stream)184*3c7ae9deSAndroid Build Coastguard Worker struct aws_input_stream *aws_input_stream_new_from_java_http_request_body_stream(
185*3c7ae9deSAndroid Build Coastguard Worker struct aws_allocator *allocator,
186*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
187*3c7ae9deSAndroid Build Coastguard Worker jobject http_request_body_stream) {
188*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_request_body_stream_impl *impl =
189*3c7ae9deSAndroid Build Coastguard Worker aws_mem_calloc(allocator, 1, sizeof(struct aws_http_request_body_stream_impl));
190*3c7ae9deSAndroid Build Coastguard Worker
191*3c7ae9deSAndroid Build Coastguard Worker impl->allocator = allocator;
192*3c7ae9deSAndroid Build Coastguard Worker impl->base.vtable = &s_aws_input_stream_vtable;
193*3c7ae9deSAndroid Build Coastguard Worker aws_ref_count_init(&impl->base.ref_count, impl, (aws_simple_completion_callback *)s_aws_input_stream_destroy);
194*3c7ae9deSAndroid Build Coastguard Worker
195*3c7ae9deSAndroid Build Coastguard Worker jint jvmresult = (*env)->GetJavaVM(env, &impl->jvm);
196*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(jvmresult == 0);
197*3c7ae9deSAndroid Build Coastguard Worker
198*3c7ae9deSAndroid Build Coastguard Worker impl->is_valid = true;
199*3c7ae9deSAndroid Build Coastguard Worker if (http_request_body_stream != NULL) {
200*3c7ae9deSAndroid Build Coastguard Worker impl->http_request_body_stream = (*env)->NewGlobalRef(env, http_request_body_stream);
201*3c7ae9deSAndroid Build Coastguard Worker if (impl->http_request_body_stream == NULL) {
202*3c7ae9deSAndroid Build Coastguard Worker goto on_error;
203*3c7ae9deSAndroid Build Coastguard Worker }
204*3c7ae9deSAndroid Build Coastguard Worker } else {
205*3c7ae9deSAndroid Build Coastguard Worker impl->body_done = true;
206*3c7ae9deSAndroid Build Coastguard Worker }
207*3c7ae9deSAndroid Build Coastguard Worker
208*3c7ae9deSAndroid Build Coastguard Worker return &impl->base;
209*3c7ae9deSAndroid Build Coastguard Worker
210*3c7ae9deSAndroid Build Coastguard Worker on_error:
211*3c7ae9deSAndroid Build Coastguard Worker
212*3c7ae9deSAndroid Build Coastguard Worker aws_input_stream_release(&impl->base);
213*3c7ae9deSAndroid Build Coastguard Worker
214*3c7ae9deSAndroid Build Coastguard Worker return NULL;
215*3c7ae9deSAndroid Build Coastguard Worker }
216*3c7ae9deSAndroid Build Coastguard Worker
s_marshal_http_header_to_buffer(struct aws_byte_buf * buf,const struct aws_byte_cursor * name,const struct aws_byte_cursor * value)217*3c7ae9deSAndroid Build Coastguard Worker static inline int s_marshal_http_header_to_buffer(
218*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_buf *buf,
219*3c7ae9deSAndroid Build Coastguard Worker const struct aws_byte_cursor *name,
220*3c7ae9deSAndroid Build Coastguard Worker const struct aws_byte_cursor *value) {
221*3c7ae9deSAndroid Build Coastguard Worker if (aws_byte_buf_reserve_relative(buf, sizeof(int) + sizeof(int) + name->len + value->len)) {
222*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_ERR;
223*3c7ae9deSAndroid Build Coastguard Worker }
224*3c7ae9deSAndroid Build Coastguard Worker
225*3c7ae9deSAndroid Build Coastguard Worker /* This will append to the buffer without overwriting anything */
226*3c7ae9deSAndroid Build Coastguard Worker aws_byte_buf_write_be32(buf, (uint32_t)name->len);
227*3c7ae9deSAndroid Build Coastguard Worker aws_byte_buf_write_from_whole_cursor(buf, *name);
228*3c7ae9deSAndroid Build Coastguard Worker aws_byte_buf_write_be32(buf, (uint32_t)value->len);
229*3c7ae9deSAndroid Build Coastguard Worker aws_byte_buf_write_from_whole_cursor(buf, *value);
230*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_SUCCESS;
231*3c7ae9deSAndroid Build Coastguard Worker }
232*3c7ae9deSAndroid Build Coastguard Worker
aws_marshal_http_headers_array_to_dynamic_buffer(struct aws_byte_buf * buf,const struct aws_http_header * header_array,size_t num_headers)233*3c7ae9deSAndroid Build Coastguard Worker int aws_marshal_http_headers_array_to_dynamic_buffer(
234*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_buf *buf,
235*3c7ae9deSAndroid Build Coastguard Worker const struct aws_http_header *header_array,
236*3c7ae9deSAndroid Build Coastguard Worker size_t num_headers) {
237*3c7ae9deSAndroid Build Coastguard Worker for (size_t i = 0; i < num_headers; ++i) {
238*3c7ae9deSAndroid Build Coastguard Worker if (s_marshal_http_header_to_buffer(buf, &header_array[i].name, &header_array[i].value)) {
239*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_ERR;
240*3c7ae9deSAndroid Build Coastguard Worker }
241*3c7ae9deSAndroid Build Coastguard Worker }
242*3c7ae9deSAndroid Build Coastguard Worker
243*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_SUCCESS;
244*3c7ae9deSAndroid Build Coastguard Worker }
245*3c7ae9deSAndroid Build Coastguard Worker
aws_marshal_http_headers_to_dynamic_buffer(struct aws_byte_buf * buf,const struct aws_http_headers * headers)246*3c7ae9deSAndroid Build Coastguard Worker int aws_marshal_http_headers_to_dynamic_buffer(struct aws_byte_buf *buf, const struct aws_http_headers *headers) {
247*3c7ae9deSAndroid Build Coastguard Worker for (size_t i = 0; i < aws_http_headers_count(headers); ++i) {
248*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_header header;
249*3c7ae9deSAndroid Build Coastguard Worker aws_http_headers_get_index(headers, i, &header);
250*3c7ae9deSAndroid Build Coastguard Worker if (s_marshal_http_header_to_buffer(buf, &header.name, &header.value)) {
251*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_ERR;
252*3c7ae9deSAndroid Build Coastguard Worker }
253*3c7ae9deSAndroid Build Coastguard Worker }
254*3c7ae9deSAndroid Build Coastguard Worker
255*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_SUCCESS;
256*3c7ae9deSAndroid Build Coastguard Worker }
257*3c7ae9deSAndroid Build Coastguard Worker
258*3c7ae9deSAndroid Build Coastguard Worker /**
259*3c7ae9deSAndroid Build Coastguard Worker * Unmarshal the request from java.
260*3c7ae9deSAndroid Build Coastguard Worker *
261*3c7ae9deSAndroid Build Coastguard Worker * Version is as int: [4-bytes BE]
262*3c7ae9deSAndroid Build Coastguard Worker *
263*3c7ae9deSAndroid Build Coastguard Worker * Each string field is: [4-bytes BE] [variable length bytes specified
264*3c7ae9deSAndroid Build Coastguard Worker * by the previous field]
265*3c7ae9deSAndroid Build Coastguard Worker *
266*3c7ae9deSAndroid Build Coastguard Worker * Each request is like: [version][method][path][header name-value
267*3c7ae9deSAndroid Build Coastguard Worker * pairs]
268*3c7ae9deSAndroid Build Coastguard Worker *
269*3c7ae9deSAndroid Build Coastguard Worker * s_unmarshal_http_request_to_get_version to get the version field, which is a 4 byte int.
270*3c7ae9deSAndroid Build Coastguard Worker * s_unmarshal_http_request_without_version to get the whole request without version field.
271*3c7ae9deSAndroid Build Coastguard Worker */
s_unmarshal_http_request_to_get_version(struct aws_byte_cursor * request_blob)272*3c7ae9deSAndroid Build Coastguard Worker static inline enum aws_http_version s_unmarshal_http_request_to_get_version(struct aws_byte_cursor *request_blob) {
273*3c7ae9deSAndroid Build Coastguard Worker uint32_t version = 0;
274*3c7ae9deSAndroid Build Coastguard Worker if (!aws_byte_cursor_read_be32(request_blob, &version)) {
275*3c7ae9deSAndroid Build Coastguard Worker aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
276*3c7ae9deSAndroid Build Coastguard Worker }
277*3c7ae9deSAndroid Build Coastguard Worker return version;
278*3c7ae9deSAndroid Build Coastguard Worker }
279*3c7ae9deSAndroid Build Coastguard Worker
s_unmarshal_http_request_without_version(struct aws_http_message * message,struct aws_byte_cursor * request_blob)280*3c7ae9deSAndroid Build Coastguard Worker static inline int s_unmarshal_http_request_without_version(
281*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_message *message,
282*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor *request_blob) {
283*3c7ae9deSAndroid Build Coastguard Worker uint32_t field_len = 0;
284*3c7ae9deSAndroid Build Coastguard Worker if (aws_http_message_get_protocol_version(message) != AWS_HTTP_VERSION_2) {
285*3c7ae9deSAndroid Build Coastguard Worker /* HTTP/1 puts method and path first, but those are empty in HTTP/2 */
286*3c7ae9deSAndroid Build Coastguard Worker if (!aws_byte_cursor_read_be32(request_blob, &field_len)) {
287*3c7ae9deSAndroid Build Coastguard Worker return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
288*3c7ae9deSAndroid Build Coastguard Worker }
289*3c7ae9deSAndroid Build Coastguard Worker
290*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor method = aws_byte_cursor_advance(request_blob, field_len);
291*3c7ae9deSAndroid Build Coastguard Worker
292*3c7ae9deSAndroid Build Coastguard Worker int result = aws_http_message_set_request_method(message, method);
293*3c7ae9deSAndroid Build Coastguard Worker if (result != AWS_OP_SUCCESS) {
294*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_ERR;
295*3c7ae9deSAndroid Build Coastguard Worker }
296*3c7ae9deSAndroid Build Coastguard Worker
297*3c7ae9deSAndroid Build Coastguard Worker if (!aws_byte_cursor_read_be32(request_blob, &field_len)) {
298*3c7ae9deSAndroid Build Coastguard Worker return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
299*3c7ae9deSAndroid Build Coastguard Worker }
300*3c7ae9deSAndroid Build Coastguard Worker
301*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor path = aws_byte_cursor_advance(request_blob, field_len);
302*3c7ae9deSAndroid Build Coastguard Worker
303*3c7ae9deSAndroid Build Coastguard Worker result = aws_http_message_set_request_path(message, path);
304*3c7ae9deSAndroid Build Coastguard Worker if (result != AWS_OP_SUCCESS) {
305*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_ERR;
306*3c7ae9deSAndroid Build Coastguard Worker }
307*3c7ae9deSAndroid Build Coastguard Worker } else {
308*3c7ae9deSAndroid Build Coastguard Worker /* Read empty method and path from the marshalled request */
309*3c7ae9deSAndroid Build Coastguard Worker if (!aws_byte_cursor_read_be32(request_blob, &field_len) || field_len) {
310*3c7ae9deSAndroid Build Coastguard Worker return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
311*3c7ae9deSAndroid Build Coastguard Worker }
312*3c7ae9deSAndroid Build Coastguard Worker if (!aws_byte_cursor_read_be32(request_blob, &field_len) || field_len) {
313*3c7ae9deSAndroid Build Coastguard Worker return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
314*3c7ae9deSAndroid Build Coastguard Worker }
315*3c7ae9deSAndroid Build Coastguard Worker }
316*3c7ae9deSAndroid Build Coastguard Worker while (request_blob->len) {
317*3c7ae9deSAndroid Build Coastguard Worker if (!aws_byte_cursor_read_be32(request_blob, &field_len)) {
318*3c7ae9deSAndroid Build Coastguard Worker return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
319*3c7ae9deSAndroid Build Coastguard Worker }
320*3c7ae9deSAndroid Build Coastguard Worker
321*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor header_name = aws_byte_cursor_advance(request_blob, field_len);
322*3c7ae9deSAndroid Build Coastguard Worker
323*3c7ae9deSAndroid Build Coastguard Worker if (!aws_byte_cursor_read_be32(request_blob, &field_len)) {
324*3c7ae9deSAndroid Build Coastguard Worker return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
325*3c7ae9deSAndroid Build Coastguard Worker }
326*3c7ae9deSAndroid Build Coastguard Worker
327*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor header_value = aws_byte_cursor_advance(request_blob, field_len);
328*3c7ae9deSAndroid Build Coastguard Worker
329*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_header header = {
330*3c7ae9deSAndroid Build Coastguard Worker .name = header_name,
331*3c7ae9deSAndroid Build Coastguard Worker .value = header_value,
332*3c7ae9deSAndroid Build Coastguard Worker };
333*3c7ae9deSAndroid Build Coastguard Worker
334*3c7ae9deSAndroid Build Coastguard Worker aws_http_message_add_header(message, header);
335*3c7ae9deSAndroid Build Coastguard Worker }
336*3c7ae9deSAndroid Build Coastguard Worker
337*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_SUCCESS;
338*3c7ae9deSAndroid Build Coastguard Worker }
339*3c7ae9deSAndroid Build Coastguard Worker
s_unmarshal_http_headers(struct aws_http_headers * headers,struct aws_byte_cursor * request_blob)340*3c7ae9deSAndroid Build Coastguard Worker static inline int s_unmarshal_http_headers(struct aws_http_headers *headers, struct aws_byte_cursor *request_blob) {
341*3c7ae9deSAndroid Build Coastguard Worker uint32_t field_len = 0;
342*3c7ae9deSAndroid Build Coastguard Worker while (request_blob->len) {
343*3c7ae9deSAndroid Build Coastguard Worker if (!aws_byte_cursor_read_be32(request_blob, &field_len)) {
344*3c7ae9deSAndroid Build Coastguard Worker return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
345*3c7ae9deSAndroid Build Coastguard Worker }
346*3c7ae9deSAndroid Build Coastguard Worker
347*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor header_name = aws_byte_cursor_advance(request_blob, field_len);
348*3c7ae9deSAndroid Build Coastguard Worker
349*3c7ae9deSAndroid Build Coastguard Worker if (!aws_byte_cursor_read_be32(request_blob, &field_len)) {
350*3c7ae9deSAndroid Build Coastguard Worker return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
351*3c7ae9deSAndroid Build Coastguard Worker }
352*3c7ae9deSAndroid Build Coastguard Worker
353*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor header_value = aws_byte_cursor_advance(request_blob, field_len);
354*3c7ae9deSAndroid Build Coastguard Worker
355*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_header header = {
356*3c7ae9deSAndroid Build Coastguard Worker .name = header_name,
357*3c7ae9deSAndroid Build Coastguard Worker .value = header_value,
358*3c7ae9deSAndroid Build Coastguard Worker };
359*3c7ae9deSAndroid Build Coastguard Worker
360*3c7ae9deSAndroid Build Coastguard Worker aws_http_headers_add_header(headers, &header);
361*3c7ae9deSAndroid Build Coastguard Worker }
362*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_SUCCESS;
363*3c7ae9deSAndroid Build Coastguard Worker }
364*3c7ae9deSAndroid Build Coastguard Worker
aws_apply_java_http_request_changes_to_native_request(JNIEnv * env,jbyteArray marshalled_request,jobject jni_body_stream,struct aws_http_message * message)365*3c7ae9deSAndroid Build Coastguard Worker int aws_apply_java_http_request_changes_to_native_request(
366*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
367*3c7ae9deSAndroid Build Coastguard Worker jbyteArray marshalled_request,
368*3c7ae9deSAndroid Build Coastguard Worker jobject jni_body_stream,
369*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_message *message) {
370*3c7ae9deSAndroid Build Coastguard Worker
371*3c7ae9deSAndroid Build Coastguard Worker /* come back to this when we decide we need to. */
372*3c7ae9deSAndroid Build Coastguard Worker (void)jni_body_stream;
373*3c7ae9deSAndroid Build Coastguard Worker
374*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_headers *headers = aws_http_message_get_headers(message);
375*3c7ae9deSAndroid Build Coastguard Worker aws_http_headers_clear(headers);
376*3c7ae9deSAndroid Build Coastguard Worker int result = AWS_OP_SUCCESS;
377*3c7ae9deSAndroid Build Coastguard Worker
378*3c7ae9deSAndroid Build Coastguard Worker const size_t marshalled_request_length = (*env)->GetArrayLength(env, marshalled_request);
379*3c7ae9deSAndroid Build Coastguard Worker
380*3c7ae9deSAndroid Build Coastguard Worker uint8_t *marshalled_request_data = (*env)->GetPrimitiveArrayCritical(env, marshalled_request, NULL);
381*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor marshalled_cur =
382*3c7ae9deSAndroid Build Coastguard Worker aws_byte_cursor_from_array((uint8_t *)marshalled_request_data, marshalled_request_length);
383*3c7ae9deSAndroid Build Coastguard Worker
384*3c7ae9deSAndroid Build Coastguard Worker enum aws_http_version version = s_unmarshal_http_request_to_get_version(&marshalled_cur);
385*3c7ae9deSAndroid Build Coastguard Worker if (version != aws_http_message_get_protocol_version(message)) {
386*3c7ae9deSAndroid Build Coastguard Worker result = aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
387*3c7ae9deSAndroid Build Coastguard Worker } else {
388*3c7ae9deSAndroid Build Coastguard Worker result = s_unmarshal_http_request_without_version(message, &marshalled_cur);
389*3c7ae9deSAndroid Build Coastguard Worker }
390*3c7ae9deSAndroid Build Coastguard Worker (*env)->ReleasePrimitiveArrayCritical(env, marshalled_request, marshalled_request_data, 0);
391*3c7ae9deSAndroid Build Coastguard Worker
392*3c7ae9deSAndroid Build Coastguard Worker if (result) {
393*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
394*3c7ae9deSAndroid Build Coastguard Worker env, "HttpRequest.applyChangesToNativeRequest: %s\n", aws_error_debug_str(aws_last_error()));
395*3c7ae9deSAndroid Build Coastguard Worker return result;
396*3c7ae9deSAndroid Build Coastguard Worker }
397*3c7ae9deSAndroid Build Coastguard Worker
398*3c7ae9deSAndroid Build Coastguard Worker if (jni_body_stream) {
399*3c7ae9deSAndroid Build Coastguard Worker struct aws_input_stream *body_stream =
400*3c7ae9deSAndroid Build Coastguard Worker aws_input_stream_new_from_java_http_request_body_stream(aws_jni_get_allocator(), env, jni_body_stream);
401*3c7ae9deSAndroid Build Coastguard Worker
402*3c7ae9deSAndroid Build Coastguard Worker aws_http_message_set_body_stream(message, body_stream);
403*3c7ae9deSAndroid Build Coastguard Worker /* request controls the lifetime of body stream fully */
404*3c7ae9deSAndroid Build Coastguard Worker aws_input_stream_release(body_stream);
405*3c7ae9deSAndroid Build Coastguard Worker }
406*3c7ae9deSAndroid Build Coastguard Worker
407*3c7ae9deSAndroid Build Coastguard Worker return result;
408*3c7ae9deSAndroid Build Coastguard Worker }
409*3c7ae9deSAndroid Build Coastguard Worker
aws_http_request_new_from_java_http_request(JNIEnv * env,jbyteArray marshalled_request,jobject jni_body_stream)410*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_message *aws_http_request_new_from_java_http_request(
411*3c7ae9deSAndroid Build Coastguard Worker JNIEnv *env,
412*3c7ae9deSAndroid Build Coastguard Worker jbyteArray marshalled_request,
413*3c7ae9deSAndroid Build Coastguard Worker jobject jni_body_stream) {
414*3c7ae9deSAndroid Build Coastguard Worker const char *exception_message = NULL;
415*3c7ae9deSAndroid Build Coastguard Worker const size_t marshalled_request_length = (*env)->GetArrayLength(env, marshalled_request);
416*3c7ae9deSAndroid Build Coastguard Worker
417*3c7ae9deSAndroid Build Coastguard Worker jbyte *marshalled_request_data = (*env)->GetPrimitiveArrayCritical(env, marshalled_request, NULL);
418*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor marshalled_cur =
419*3c7ae9deSAndroid Build Coastguard Worker aws_byte_cursor_from_array((uint8_t *)marshalled_request_data, marshalled_request_length);
420*3c7ae9deSAndroid Build Coastguard Worker enum aws_http_version version = s_unmarshal_http_request_to_get_version(&marshalled_cur);
421*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_message *request = version == AWS_HTTP_VERSION_2
422*3c7ae9deSAndroid Build Coastguard Worker ? aws_http2_message_new_request(aws_jni_get_allocator())
423*3c7ae9deSAndroid Build Coastguard Worker : aws_http_message_new_request(aws_jni_get_allocator());
424*3c7ae9deSAndroid Build Coastguard Worker
425*3c7ae9deSAndroid Build Coastguard Worker int result = AWS_OP_SUCCESS;
426*3c7ae9deSAndroid Build Coastguard Worker if (version != aws_http_message_get_protocol_version(request)) {
427*3c7ae9deSAndroid Build Coastguard Worker result = aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
428*3c7ae9deSAndroid Build Coastguard Worker } else {
429*3c7ae9deSAndroid Build Coastguard Worker result = s_unmarshal_http_request_without_version(request, &marshalled_cur);
430*3c7ae9deSAndroid Build Coastguard Worker }
431*3c7ae9deSAndroid Build Coastguard Worker (*env)->ReleasePrimitiveArrayCritical(env, marshalled_request, marshalled_request_data, 0);
432*3c7ae9deSAndroid Build Coastguard Worker
433*3c7ae9deSAndroid Build Coastguard Worker if (result) {
434*3c7ae9deSAndroid Build Coastguard Worker exception_message = "aws_http_request_new_from_java_http_request: Invalid marshalled request data.";
435*3c7ae9deSAndroid Build Coastguard Worker goto on_error;
436*3c7ae9deSAndroid Build Coastguard Worker }
437*3c7ae9deSAndroid Build Coastguard Worker
438*3c7ae9deSAndroid Build Coastguard Worker if (jni_body_stream != NULL) {
439*3c7ae9deSAndroid Build Coastguard Worker struct aws_input_stream *body_stream =
440*3c7ae9deSAndroid Build Coastguard Worker aws_input_stream_new_from_java_http_request_body_stream(aws_jni_get_allocator(), env, jni_body_stream);
441*3c7ae9deSAndroid Build Coastguard Worker if (body_stream == NULL) {
442*3c7ae9deSAndroid Build Coastguard Worker exception_message = "aws_fill_out_request: Error building body stream";
443*3c7ae9deSAndroid Build Coastguard Worker goto on_error;
444*3c7ae9deSAndroid Build Coastguard Worker }
445*3c7ae9deSAndroid Build Coastguard Worker
446*3c7ae9deSAndroid Build Coastguard Worker aws_http_message_set_body_stream(request, body_stream);
447*3c7ae9deSAndroid Build Coastguard Worker /* request controls the lifetime of body stream fully */
448*3c7ae9deSAndroid Build Coastguard Worker aws_input_stream_release(body_stream);
449*3c7ae9deSAndroid Build Coastguard Worker }
450*3c7ae9deSAndroid Build Coastguard Worker
451*3c7ae9deSAndroid Build Coastguard Worker return request;
452*3c7ae9deSAndroid Build Coastguard Worker
453*3c7ae9deSAndroid Build Coastguard Worker on_error:
454*3c7ae9deSAndroid Build Coastguard Worker if (exception_message) {
455*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, exception_message);
456*3c7ae9deSAndroid Build Coastguard Worker }
457*3c7ae9deSAndroid Build Coastguard Worker
458*3c7ae9deSAndroid Build Coastguard Worker /* Don't need to destroy input stream since it's the last thing created */
459*3c7ae9deSAndroid Build Coastguard Worker aws_http_message_destroy(request);
460*3c7ae9deSAndroid Build Coastguard Worker
461*3c7ae9deSAndroid Build Coastguard Worker return NULL;
462*3c7ae9deSAndroid Build Coastguard Worker }
463*3c7ae9deSAndroid Build Coastguard Worker
aws_http_headers_new_from_java_http_headers(JNIEnv * env,jbyteArray marshalled_headers)464*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_headers *aws_http_headers_new_from_java_http_headers(JNIEnv *env, jbyteArray marshalled_headers) {
465*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_headers *headers = aws_http_headers_new(aws_jni_get_allocator());
466*3c7ae9deSAndroid Build Coastguard Worker if (headers == NULL) {
467*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "aws_http_headers_new_from_java_http_headers: Unable to allocate headers");
468*3c7ae9deSAndroid Build Coastguard Worker return NULL;
469*3c7ae9deSAndroid Build Coastguard Worker }
470*3c7ae9deSAndroid Build Coastguard Worker const size_t marshalled_headers_length = (*env)->GetArrayLength(env, marshalled_headers);
471*3c7ae9deSAndroid Build Coastguard Worker
472*3c7ae9deSAndroid Build Coastguard Worker jbyte *marshalled_headers_data = (*env)->GetPrimitiveArrayCritical(env, marshalled_headers, NULL);
473*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor marshalled_cur =
474*3c7ae9deSAndroid Build Coastguard Worker aws_byte_cursor_from_array((uint8_t *)marshalled_headers_data, marshalled_headers_length);
475*3c7ae9deSAndroid Build Coastguard Worker int result = s_unmarshal_http_headers(headers, &marshalled_cur);
476*3c7ae9deSAndroid Build Coastguard Worker (*env)->ReleasePrimitiveArrayCritical(env, marshalled_headers, marshalled_headers_data, 0);
477*3c7ae9deSAndroid Build Coastguard Worker
478*3c7ae9deSAndroid Build Coastguard Worker if (result) {
479*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
480*3c7ae9deSAndroid Build Coastguard Worker env, "aws_http_headers_new_from_java_http_headers: Invalid marshalled headers data.");
481*3c7ae9deSAndroid Build Coastguard Worker goto on_error;
482*3c7ae9deSAndroid Build Coastguard Worker }
483*3c7ae9deSAndroid Build Coastguard Worker
484*3c7ae9deSAndroid Build Coastguard Worker return headers;
485*3c7ae9deSAndroid Build Coastguard Worker
486*3c7ae9deSAndroid Build Coastguard Worker on_error:
487*3c7ae9deSAndroid Build Coastguard Worker aws_http_headers_release(headers);
488*3c7ae9deSAndroid Build Coastguard Worker return NULL;
489*3c7ae9deSAndroid Build Coastguard Worker }
490*3c7ae9deSAndroid Build Coastguard Worker
s_marshall_http_request(const struct aws_http_message * message,struct aws_byte_buf * request_buf)491*3c7ae9deSAndroid Build Coastguard Worker static inline int s_marshall_http_request(const struct aws_http_message *message, struct aws_byte_buf *request_buf) {
492*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor method;
493*3c7ae9deSAndroid Build Coastguard Worker AWS_ZERO_STRUCT(method);
494*3c7ae9deSAndroid Build Coastguard Worker
495*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(!aws_http_message_get_request_method(message, &method));
496*3c7ae9deSAndroid Build Coastguard Worker
497*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_cursor path;
498*3c7ae9deSAndroid Build Coastguard Worker AWS_ZERO_STRUCT(path);
499*3c7ae9deSAndroid Build Coastguard Worker
500*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(!aws_http_message_get_request_path(message, &path));
501*3c7ae9deSAndroid Build Coastguard Worker
502*3c7ae9deSAndroid Build Coastguard Worker if (aws_byte_buf_reserve_relative(request_buf, sizeof(int) + sizeof(int) + sizeof(int) + method.len + path.len)) {
503*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_ERR;
504*3c7ae9deSAndroid Build Coastguard Worker }
505*3c7ae9deSAndroid Build Coastguard Worker
506*3c7ae9deSAndroid Build Coastguard Worker aws_byte_buf_write_be32(request_buf, (uint32_t)aws_http_message_get_protocol_version(message));
507*3c7ae9deSAndroid Build Coastguard Worker aws_byte_buf_write_be32(request_buf, (uint32_t)method.len);
508*3c7ae9deSAndroid Build Coastguard Worker aws_byte_buf_write_from_whole_cursor(request_buf, method);
509*3c7ae9deSAndroid Build Coastguard Worker aws_byte_buf_write_be32(request_buf, (uint32_t)path.len);
510*3c7ae9deSAndroid Build Coastguard Worker aws_byte_buf_write_from_whole_cursor(request_buf, path);
511*3c7ae9deSAndroid Build Coastguard Worker
512*3c7ae9deSAndroid Build Coastguard Worker const struct aws_http_headers *headers = aws_http_message_get_const_headers(message);
513*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(headers);
514*3c7ae9deSAndroid Build Coastguard Worker size_t header_count = aws_http_message_get_header_count(message);
515*3c7ae9deSAndroid Build Coastguard Worker for (size_t i = 0; i < header_count; ++i) {
516*3c7ae9deSAndroid Build Coastguard Worker struct aws_http_header header;
517*3c7ae9deSAndroid Build Coastguard Worker AWS_ZERO_STRUCT(header);
518*3c7ae9deSAndroid Build Coastguard Worker
519*3c7ae9deSAndroid Build Coastguard Worker AWS_FATAL_ASSERT(!aws_http_headers_get_index(headers, i, &header));
520*3c7ae9deSAndroid Build Coastguard Worker if (s_marshal_http_header_to_buffer(request_buf, &header.name, &header.value)) {
521*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_ERR;
522*3c7ae9deSAndroid Build Coastguard Worker }
523*3c7ae9deSAndroid Build Coastguard Worker }
524*3c7ae9deSAndroid Build Coastguard Worker
525*3c7ae9deSAndroid Build Coastguard Worker return AWS_OP_SUCCESS;
526*3c7ae9deSAndroid Build Coastguard Worker }
527*3c7ae9deSAndroid Build Coastguard Worker
aws_java_http_request_from_native(JNIEnv * env,struct aws_http_message * message,jobject request_body_stream)528*3c7ae9deSAndroid Build Coastguard Worker jobject aws_java_http_request_from_native(JNIEnv *env, struct aws_http_message *message, jobject request_body_stream) {
529*3c7ae9deSAndroid Build Coastguard Worker jobject jni_request_blob = NULL;
530*3c7ae9deSAndroid Build Coastguard Worker jobject j_request = NULL;
531*3c7ae9deSAndroid Build Coastguard Worker struct aws_byte_buf marshaling_buf;
532*3c7ae9deSAndroid Build Coastguard Worker
533*3c7ae9deSAndroid Build Coastguard Worker if (aws_byte_buf_init(&marshaling_buf, aws_jni_get_allocator(), 1024)) {
534*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(env, "aws_java_http_request_from_native: allocation failed");
535*3c7ae9deSAndroid Build Coastguard Worker return NULL;
536*3c7ae9deSAndroid Build Coastguard Worker }
537*3c7ae9deSAndroid Build Coastguard Worker
538*3c7ae9deSAndroid Build Coastguard Worker if (s_marshall_http_request(message, &marshaling_buf)) {
539*3c7ae9deSAndroid Build Coastguard Worker aws_jni_throw_runtime_exception(
540*3c7ae9deSAndroid Build Coastguard Worker env, "aws_java_http_request_from_native: %s.", aws_error_debug_str(aws_last_error()));
541*3c7ae9deSAndroid Build Coastguard Worker goto done;
542*3c7ae9deSAndroid Build Coastguard Worker }
543*3c7ae9deSAndroid Build Coastguard Worker
544*3c7ae9deSAndroid Build Coastguard Worker jni_request_blob = aws_jni_direct_byte_buffer_from_raw_ptr(env, marshaling_buf.buffer, marshaling_buf.len);
545*3c7ae9deSAndroid Build Coastguard Worker
546*3c7ae9deSAndroid Build Coastguard Worker /* Currently our only use case for this does not involve a body stream. We should come back and handle this
547*3c7ae9deSAndroid Build Coastguard Worker when it's not time sensitive to do so. */
548*3c7ae9deSAndroid Build Coastguard Worker j_request = (*env)->NewObject(
549*3c7ae9deSAndroid Build Coastguard Worker env,
550*3c7ae9deSAndroid Build Coastguard Worker http_request_properties.http_request_class,
551*3c7ae9deSAndroid Build Coastguard Worker http_request_properties.constructor_method_id,
552*3c7ae9deSAndroid Build Coastguard Worker jni_request_blob,
553*3c7ae9deSAndroid Build Coastguard Worker request_body_stream);
554*3c7ae9deSAndroid Build Coastguard Worker
555*3c7ae9deSAndroid Build Coastguard Worker if (aws_jni_check_and_clear_exception(env)) {
556*3c7ae9deSAndroid Build Coastguard Worker aws_raise_error(AWS_ERROR_HTTP_CALLBACK_FAILURE);
557*3c7ae9deSAndroid Build Coastguard Worker goto done;
558*3c7ae9deSAndroid Build Coastguard Worker }
559*3c7ae9deSAndroid Build Coastguard Worker
560*3c7ae9deSAndroid Build Coastguard Worker done:
561*3c7ae9deSAndroid Build Coastguard Worker if (jni_request_blob) {
562*3c7ae9deSAndroid Build Coastguard Worker (*env)->DeleteLocalRef(env, jni_request_blob);
563*3c7ae9deSAndroid Build Coastguard Worker }
564*3c7ae9deSAndroid Build Coastguard Worker
565*3c7ae9deSAndroid Build Coastguard Worker aws_byte_buf_clean_up(&marshaling_buf);
566*3c7ae9deSAndroid Build Coastguard Worker return j_request;
567*3c7ae9deSAndroid Build Coastguard Worker }
568