xref: /unit/src/java/nxt_jni_Response.c (revision 977)
1*977Smax.romanov@gmail.com 
2*977Smax.romanov@gmail.com /*
3*977Smax.romanov@gmail.com  * Copyright (C) NGINX, Inc.
4*977Smax.romanov@gmail.com  */
5*977Smax.romanov@gmail.com 
6*977Smax.romanov@gmail.com #include <nxt_auto_config.h>
7*977Smax.romanov@gmail.com 
8*977Smax.romanov@gmail.com #include <nxt_unit.h>
9*977Smax.romanov@gmail.com #include <nxt_unit_response.h>
10*977Smax.romanov@gmail.com #include <jni.h>
11*977Smax.romanov@gmail.com #include <stdio.h>
12*977Smax.romanov@gmail.com 
13*977Smax.romanov@gmail.com #include "nxt_jni.h"
14*977Smax.romanov@gmail.com #include "nxt_jni_Response.h"
15*977Smax.romanov@gmail.com #include "nxt_jni_HeadersEnumeration.h"
16*977Smax.romanov@gmail.com #include "nxt_jni_HeaderNamesEnumeration.h"
17*977Smax.romanov@gmail.com #include "nxt_jni_OutputStream.h"
18*977Smax.romanov@gmail.com #include "nxt_jni_URLClassLoader.h"
19*977Smax.romanov@gmail.com 
20*977Smax.romanov@gmail.com 
21*977Smax.romanov@gmail.com static jclass     nxt_java_Response_class;
22*977Smax.romanov@gmail.com static jmethodID  nxt_java_Response_ctor;
23*977Smax.romanov@gmail.com 
24*977Smax.romanov@gmail.com 
25*977Smax.romanov@gmail.com static void JNICALL nxt_java_Response_addHeader(JNIEnv *env, jclass cls,
26*977Smax.romanov@gmail.com     jlong req_info_ptr, jarray name, jarray value);
27*977Smax.romanov@gmail.com 
28*977Smax.romanov@gmail.com static nxt_unit_request_info_t *nxt_java_get_response_info(
29*977Smax.romanov@gmail.com     jlong req_info_ptr, uint32_t extra_fields, uint32_t extra_data);
30*977Smax.romanov@gmail.com 
31*977Smax.romanov@gmail.com static void JNICALL nxt_java_Response_addIntHeader(JNIEnv *env, jclass cls,
32*977Smax.romanov@gmail.com     jlong req_info_ptr, jarray name, jint value);
33*977Smax.romanov@gmail.com 
34*977Smax.romanov@gmail.com static void nxt_java_add_int_header(nxt_unit_request_info_t *req,
35*977Smax.romanov@gmail.com     const char *name, uint8_t name_len, int value);
36*977Smax.romanov@gmail.com 
37*977Smax.romanov@gmail.com static jboolean JNICALL nxt_java_Response_containsHeader(JNIEnv *env,
38*977Smax.romanov@gmail.com     jclass cls, jlong req_info_ptr, jarray name);
39*977Smax.romanov@gmail.com 
40*977Smax.romanov@gmail.com static jstring JNICALL nxt_java_Response_getHeader(JNIEnv *env, jclass cls,
41*977Smax.romanov@gmail.com     jlong req_info_ptr, jarray name);
42*977Smax.romanov@gmail.com 
43*977Smax.romanov@gmail.com static jobject JNICALL nxt_java_Response_getHeaderNames(JNIEnv *env,
44*977Smax.romanov@gmail.com     jclass cls, jlong req_info_ptr);
45*977Smax.romanov@gmail.com 
46*977Smax.romanov@gmail.com static jobject JNICALL nxt_java_Response_getHeaders(JNIEnv *env, jclass cls,
47*977Smax.romanov@gmail.com     jlong req_info_ptr, jarray name);
48*977Smax.romanov@gmail.com 
49*977Smax.romanov@gmail.com static jint JNICALL nxt_java_Response_getStatus(JNIEnv *env, jclass cls,
50*977Smax.romanov@gmail.com     jlong req_info_ptr);
51*977Smax.romanov@gmail.com 
52*977Smax.romanov@gmail.com static jobject JNICALL nxt_java_Response_getRequest(JNIEnv *env, jclass cls,
53*977Smax.romanov@gmail.com     jlong req_info_ptr);
54*977Smax.romanov@gmail.com 
55*977Smax.romanov@gmail.com static void JNICALL nxt_java_Response_commit(JNIEnv *env, jclass cls,
56*977Smax.romanov@gmail.com     jlong req_info_ptr);
57*977Smax.romanov@gmail.com 
58*977Smax.romanov@gmail.com static void JNICALL nxt_java_Response_sendRedirect(JNIEnv *env, jclass cls,
59*977Smax.romanov@gmail.com     jlong req_info_ptr, jarray loc);
60*977Smax.romanov@gmail.com 
61*977Smax.romanov@gmail.com static int nxt_java_response_set_header(jlong req_info_ptr,
62*977Smax.romanov@gmail.com     const char *name, jint name_len, const char *value, jint value_len);
63*977Smax.romanov@gmail.com 
64*977Smax.romanov@gmail.com static void JNICALL nxt_java_Response_setHeader(JNIEnv *env, jclass cls,
65*977Smax.romanov@gmail.com     jlong req_info_ptr, jarray name, jarray value);
66*977Smax.romanov@gmail.com 
67*977Smax.romanov@gmail.com static void JNICALL nxt_java_Response_removeHeader(JNIEnv *env, jclass cls,
68*977Smax.romanov@gmail.com     jlong req_info_ptr, jarray name);
69*977Smax.romanov@gmail.com 
70*977Smax.romanov@gmail.com static int nxt_java_response_remove_header(jlong req_info_ptr,
71*977Smax.romanov@gmail.com     const char *name, jint name_len);
72*977Smax.romanov@gmail.com 
73*977Smax.romanov@gmail.com static void JNICALL nxt_java_Response_setIntHeader(JNIEnv *env, jclass cls,
74*977Smax.romanov@gmail.com     jlong req_info_ptr, jarray name, jint value);
75*977Smax.romanov@gmail.com 
76*977Smax.romanov@gmail.com static void JNICALL nxt_java_Response_setStatus(JNIEnv *env, jclass cls,
77*977Smax.romanov@gmail.com     jlong req_info_ptr, jint sc);
78*977Smax.romanov@gmail.com 
79*977Smax.romanov@gmail.com static jstring JNICALL nxt_java_Response_getContentType(JNIEnv *env,
80*977Smax.romanov@gmail.com     jclass cls, jlong req_info_ptr);
81*977Smax.romanov@gmail.com 
82*977Smax.romanov@gmail.com static jboolean JNICALL nxt_java_Response_isCommitted(JNIEnv *env, jclass cls,
83*977Smax.romanov@gmail.com     jlong req_info_ptr);
84*977Smax.romanov@gmail.com 
85*977Smax.romanov@gmail.com static void JNICALL nxt_java_Response_reset(JNIEnv *env, jclass cls,
86*977Smax.romanov@gmail.com     jlong req_info_ptr);
87*977Smax.romanov@gmail.com 
88*977Smax.romanov@gmail.com static void JNICALL nxt_java_Response_resetBuffer(JNIEnv *env, jclass cls,
89*977Smax.romanov@gmail.com     jlong req_info_ptr);
90*977Smax.romanov@gmail.com 
91*977Smax.romanov@gmail.com static void JNICALL nxt_java_Response_setBufferSize(JNIEnv *env, jclass cls,
92*977Smax.romanov@gmail.com     jlong req_info_ptr, jint size);
93*977Smax.romanov@gmail.com 
94*977Smax.romanov@gmail.com static jint JNICALL nxt_java_Response_getBufferSize(JNIEnv *env, jclass cls,
95*977Smax.romanov@gmail.com     jlong req_info_ptr);
96*977Smax.romanov@gmail.com 
97*977Smax.romanov@gmail.com static void JNICALL nxt_java_Response_setContentLength(JNIEnv *env, jclass cls,
98*977Smax.romanov@gmail.com     jlong req_info_ptr, jlong len);
99*977Smax.romanov@gmail.com 
100*977Smax.romanov@gmail.com static void JNICALL nxt_java_Response_setContentType(JNIEnv *env, jclass cls,
101*977Smax.romanov@gmail.com     jlong req_info_ptr, jarray type);
102*977Smax.romanov@gmail.com 
103*977Smax.romanov@gmail.com static void JNICALL nxt_java_Response_removeContentType(JNIEnv *env, jclass cls,
104*977Smax.romanov@gmail.com     jlong req_info_ptr);
105*977Smax.romanov@gmail.com 
106*977Smax.romanov@gmail.com static void JNICALL nxt_java_Response_log(JNIEnv *env, jclass cls,
107*977Smax.romanov@gmail.com     jlong req_info_ptr, jarray msg);
108*977Smax.romanov@gmail.com 
109*977Smax.romanov@gmail.com static void JNICALL nxt_java_Response_trace(JNIEnv *env, jclass cls,
110*977Smax.romanov@gmail.com     jlong req_info_ptr, jarray msg);
111*977Smax.romanov@gmail.com 
112*977Smax.romanov@gmail.com int
113*977Smax.romanov@gmail.com nxt_java_initResponse(JNIEnv *env, jobject cl)
114*977Smax.romanov@gmail.com {
115*977Smax.romanov@gmail.com     int     res;
116*977Smax.romanov@gmail.com     jclass  cls;
117*977Smax.romanov@gmail.com 
118*977Smax.romanov@gmail.com     cls = nxt_java_loadClass(env, cl, "nginx.unit.Response");
119*977Smax.romanov@gmail.com     if (cls == NULL) {
120*977Smax.romanov@gmail.com         return NXT_UNIT_ERROR;
121*977Smax.romanov@gmail.com     }
122*977Smax.romanov@gmail.com 
123*977Smax.romanov@gmail.com     nxt_java_Response_class = (*env)->NewGlobalRef(env, cls);
124*977Smax.romanov@gmail.com     (*env)->DeleteLocalRef(env, cls);
125*977Smax.romanov@gmail.com     cls = nxt_java_Response_class;
126*977Smax.romanov@gmail.com 
127*977Smax.romanov@gmail.com     nxt_java_Response_ctor = (*env)->GetMethodID(env, cls, "<init>", "(J)V");
128*977Smax.romanov@gmail.com     if (nxt_java_Response_ctor == NULL) {
129*977Smax.romanov@gmail.com         (*env)->DeleteGlobalRef(env, cls);
130*977Smax.romanov@gmail.com         return NXT_UNIT_ERROR;
131*977Smax.romanov@gmail.com     }
132*977Smax.romanov@gmail.com 
133*977Smax.romanov@gmail.com     JNINativeMethod resp_methods[] = {
134*977Smax.romanov@gmail.com         { (char *) "addHeader",
135*977Smax.romanov@gmail.com           (char *) "(J[B[B)V",
136*977Smax.romanov@gmail.com           nxt_java_Response_addHeader },
137*977Smax.romanov@gmail.com 
138*977Smax.romanov@gmail.com         { (char *) "addIntHeader",
139*977Smax.romanov@gmail.com           (char *) "(J[BI)V",
140*977Smax.romanov@gmail.com           nxt_java_Response_addIntHeader },
141*977Smax.romanov@gmail.com 
142*977Smax.romanov@gmail.com         { (char *) "containsHeader",
143*977Smax.romanov@gmail.com           (char *) "(J[B)Z",
144*977Smax.romanov@gmail.com           nxt_java_Response_containsHeader },
145*977Smax.romanov@gmail.com 
146*977Smax.romanov@gmail.com         { (char *) "getHeader",
147*977Smax.romanov@gmail.com           (char *) "(J[B)Ljava/lang/String;",
148*977Smax.romanov@gmail.com           nxt_java_Response_getHeader },
149*977Smax.romanov@gmail.com 
150*977Smax.romanov@gmail.com         { (char *) "getHeaderNames",
151*977Smax.romanov@gmail.com           (char *) "(J)Ljava/util/Enumeration;",
152*977Smax.romanov@gmail.com           nxt_java_Response_getHeaderNames },
153*977Smax.romanov@gmail.com 
154*977Smax.romanov@gmail.com         { (char *) "getHeaders",
155*977Smax.romanov@gmail.com           (char *) "(J[B)Ljava/util/Enumeration;",
156*977Smax.romanov@gmail.com           nxt_java_Response_getHeaders },
157*977Smax.romanov@gmail.com 
158*977Smax.romanov@gmail.com         { (char *) "getStatus",
159*977Smax.romanov@gmail.com           (char *) "(J)I",
160*977Smax.romanov@gmail.com           nxt_java_Response_getStatus },
161*977Smax.romanov@gmail.com 
162*977Smax.romanov@gmail.com         { (char *) "getRequest",
163*977Smax.romanov@gmail.com           (char *) "(J)Lnginx/unit/Request;",
164*977Smax.romanov@gmail.com           nxt_java_Response_getRequest },
165*977Smax.romanov@gmail.com 
166*977Smax.romanov@gmail.com         { (char *) "commit",
167*977Smax.romanov@gmail.com           (char *) "(J)V",
168*977Smax.romanov@gmail.com           nxt_java_Response_commit },
169*977Smax.romanov@gmail.com 
170*977Smax.romanov@gmail.com         { (char *) "sendRedirect",
171*977Smax.romanov@gmail.com           (char *) "(J[B)V",
172*977Smax.romanov@gmail.com           nxt_java_Response_sendRedirect },
173*977Smax.romanov@gmail.com 
174*977Smax.romanov@gmail.com         { (char *) "setHeader",
175*977Smax.romanov@gmail.com           (char *) "(J[B[B)V",
176*977Smax.romanov@gmail.com           nxt_java_Response_setHeader },
177*977Smax.romanov@gmail.com 
178*977Smax.romanov@gmail.com         { (char *) "removeHeader",
179*977Smax.romanov@gmail.com           (char *) "(J[B)V",
180*977Smax.romanov@gmail.com           nxt_java_Response_removeHeader },
181*977Smax.romanov@gmail.com 
182*977Smax.romanov@gmail.com         { (char *) "setIntHeader",
183*977Smax.romanov@gmail.com           (char *) "(J[BI)V",
184*977Smax.romanov@gmail.com           nxt_java_Response_setIntHeader },
185*977Smax.romanov@gmail.com 
186*977Smax.romanov@gmail.com         { (char *) "setStatus",
187*977Smax.romanov@gmail.com           (char *) "(JI)V",
188*977Smax.romanov@gmail.com           nxt_java_Response_setStatus },
189*977Smax.romanov@gmail.com 
190*977Smax.romanov@gmail.com         { (char *) "getContentType",
191*977Smax.romanov@gmail.com           (char *) "(J)Ljava/lang/String;",
192*977Smax.romanov@gmail.com           nxt_java_Response_getContentType },
193*977Smax.romanov@gmail.com 
194*977Smax.romanov@gmail.com         { (char *) "isCommitted",
195*977Smax.romanov@gmail.com           (char *) "(J)Z",
196*977Smax.romanov@gmail.com           nxt_java_Response_isCommitted },
197*977Smax.romanov@gmail.com 
198*977Smax.romanov@gmail.com         { (char *) "reset",
199*977Smax.romanov@gmail.com           (char *) "(J)V",
200*977Smax.romanov@gmail.com           nxt_java_Response_reset },
201*977Smax.romanov@gmail.com 
202*977Smax.romanov@gmail.com         { (char *) "resetBuffer",
203*977Smax.romanov@gmail.com           (char *) "(J)V",
204*977Smax.romanov@gmail.com           nxt_java_Response_resetBuffer },
205*977Smax.romanov@gmail.com 
206*977Smax.romanov@gmail.com         { (char *) "setBufferSize",
207*977Smax.romanov@gmail.com           (char *) "(JI)V",
208*977Smax.romanov@gmail.com           nxt_java_Response_setBufferSize },
209*977Smax.romanov@gmail.com 
210*977Smax.romanov@gmail.com         { (char *) "getBufferSize",
211*977Smax.romanov@gmail.com           (char *) "(J)I",
212*977Smax.romanov@gmail.com           nxt_java_Response_getBufferSize },
213*977Smax.romanov@gmail.com 
214*977Smax.romanov@gmail.com         { (char *) "setContentLength",
215*977Smax.romanov@gmail.com           (char *) "(JJ)V",
216*977Smax.romanov@gmail.com           nxt_java_Response_setContentLength },
217*977Smax.romanov@gmail.com 
218*977Smax.romanov@gmail.com         { (char *) "setContentType",
219*977Smax.romanov@gmail.com           (char *) "(J[B)V",
220*977Smax.romanov@gmail.com           nxt_java_Response_setContentType },
221*977Smax.romanov@gmail.com 
222*977Smax.romanov@gmail.com         { (char *) "removeContentType",
223*977Smax.romanov@gmail.com           (char *) "(J)V",
224*977Smax.romanov@gmail.com           nxt_java_Response_removeContentType },
225*977Smax.romanov@gmail.com 
226*977Smax.romanov@gmail.com         { (char *) "log",
227*977Smax.romanov@gmail.com           (char *) "(J[B)V",
228*977Smax.romanov@gmail.com           nxt_java_Response_log },
229*977Smax.romanov@gmail.com 
230*977Smax.romanov@gmail.com         { (char *) "trace",
231*977Smax.romanov@gmail.com           (char *) "(J[B)V",
232*977Smax.romanov@gmail.com           nxt_java_Response_trace },
233*977Smax.romanov@gmail.com 
234*977Smax.romanov@gmail.com     };
235*977Smax.romanov@gmail.com 
236*977Smax.romanov@gmail.com     res = (*env)->RegisterNatives(env, nxt_java_Response_class,
237*977Smax.romanov@gmail.com                                   resp_methods,
238*977Smax.romanov@gmail.com                                   sizeof(resp_methods)
239*977Smax.romanov@gmail.com                                       / sizeof(resp_methods[0]));
240*977Smax.romanov@gmail.com 
241*977Smax.romanov@gmail.com     nxt_unit_debug(NULL, "registered Response methods: %d", res);
242*977Smax.romanov@gmail.com 
243*977Smax.romanov@gmail.com     if (res != 0) {
244*977Smax.romanov@gmail.com         (*env)->DeleteGlobalRef(env, cls);
245*977Smax.romanov@gmail.com         return NXT_UNIT_ERROR;
246*977Smax.romanov@gmail.com     }
247*977Smax.romanov@gmail.com 
248*977Smax.romanov@gmail.com     return NXT_UNIT_OK;
249*977Smax.romanov@gmail.com }
250*977Smax.romanov@gmail.com 
251*977Smax.romanov@gmail.com 
252*977Smax.romanov@gmail.com jobject
253*977Smax.romanov@gmail.com nxt_java_newResponse(JNIEnv *env, nxt_unit_request_info_t *req)
254*977Smax.romanov@gmail.com {
255*977Smax.romanov@gmail.com     return (*env)->NewObject(env, nxt_java_Response_class,
256*977Smax.romanov@gmail.com                              nxt_java_Response_ctor, nxt_ptr2jlong(req));
257*977Smax.romanov@gmail.com }
258*977Smax.romanov@gmail.com 
259*977Smax.romanov@gmail.com 
260*977Smax.romanov@gmail.com static void JNICALL
261*977Smax.romanov@gmail.com nxt_java_Response_addHeader(JNIEnv *env, jclass cls, jlong req_info_ptr,
262*977Smax.romanov@gmail.com     jarray name, jarray value)
263*977Smax.romanov@gmail.com {
264*977Smax.romanov@gmail.com     int                      rc;
265*977Smax.romanov@gmail.com     char                     *name_str, *value_str;
266*977Smax.romanov@gmail.com     jsize                    name_len, value_len;
267*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
268*977Smax.romanov@gmail.com 
269*977Smax.romanov@gmail.com     name_len = (*env)->GetArrayLength(env, name);
270*977Smax.romanov@gmail.com     value_len = (*env)->GetArrayLength(env, value);
271*977Smax.romanov@gmail.com 
272*977Smax.romanov@gmail.com     req = nxt_java_get_response_info(req_info_ptr, 1, name_len + value_len + 2);
273*977Smax.romanov@gmail.com     if (req == NULL) {
274*977Smax.romanov@gmail.com         return;
275*977Smax.romanov@gmail.com     }
276*977Smax.romanov@gmail.com 
277*977Smax.romanov@gmail.com     name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL);
278*977Smax.romanov@gmail.com     if (name_str == NULL) {
279*977Smax.romanov@gmail.com         nxt_unit_req_warn(req, "addHeader: failed to get name content");
280*977Smax.romanov@gmail.com         return;
281*977Smax.romanov@gmail.com     }
282*977Smax.romanov@gmail.com 
283*977Smax.romanov@gmail.com     value_str = (*env)->GetPrimitiveArrayCritical(env, value, NULL);
284*977Smax.romanov@gmail.com     if (value_str == NULL) {
285*977Smax.romanov@gmail.com         (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
286*977Smax.romanov@gmail.com         nxt_unit_req_warn(req, "addHeader: failed to get value content");
287*977Smax.romanov@gmail.com 
288*977Smax.romanov@gmail.com         return;
289*977Smax.romanov@gmail.com     }
290*977Smax.romanov@gmail.com 
291*977Smax.romanov@gmail.com     rc = nxt_unit_response_add_field(req, name_str, name_len,
292*977Smax.romanov@gmail.com                                      value_str, value_len);
293*977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
294*977Smax.romanov@gmail.com         // throw
295*977Smax.romanov@gmail.com     }
296*977Smax.romanov@gmail.com 
297*977Smax.romanov@gmail.com     (*env)->ReleasePrimitiveArrayCritical(env, value, value_str, 0);
298*977Smax.romanov@gmail.com     (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
299*977Smax.romanov@gmail.com }
300*977Smax.romanov@gmail.com 
301*977Smax.romanov@gmail.com 
302*977Smax.romanov@gmail.com static nxt_unit_request_info_t *
303*977Smax.romanov@gmail.com nxt_java_get_response_info(jlong req_info_ptr, uint32_t extra_fields,
304*977Smax.romanov@gmail.com     uint32_t extra_data)
305*977Smax.romanov@gmail.com {
306*977Smax.romanov@gmail.com     int                      rc;
307*977Smax.romanov@gmail.com     char                     *p;
308*977Smax.romanov@gmail.com     uint32_t                 max_size;
309*977Smax.romanov@gmail.com     nxt_unit_buf_t           *buf;
310*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
311*977Smax.romanov@gmail.com     nxt_java_request_data_t  *data;
312*977Smax.romanov@gmail.com 
313*977Smax.romanov@gmail.com     req = nxt_jlong2ptr(req_info_ptr);
314*977Smax.romanov@gmail.com 
315*977Smax.romanov@gmail.com     if (nxt_unit_response_is_sent(req)) {
316*977Smax.romanov@gmail.com         return NULL;
317*977Smax.romanov@gmail.com     }
318*977Smax.romanov@gmail.com 
319*977Smax.romanov@gmail.com     data = req->data;
320*977Smax.romanov@gmail.com 
321*977Smax.romanov@gmail.com     if (!nxt_unit_response_is_init(req)) {
322*977Smax.romanov@gmail.com         max_size = nxt_unit_buf_max();
323*977Smax.romanov@gmail.com         max_size = max_size < data->header_size ? max_size : data->header_size;
324*977Smax.romanov@gmail.com 
325*977Smax.romanov@gmail.com         rc = nxt_unit_response_init(req, 200, 16, max_size);
326*977Smax.romanov@gmail.com         if (rc != NXT_UNIT_OK) {
327*977Smax.romanov@gmail.com             return NULL;
328*977Smax.romanov@gmail.com         }
329*977Smax.romanov@gmail.com     }
330*977Smax.romanov@gmail.com 
331*977Smax.romanov@gmail.com     buf = req->response_buf;
332*977Smax.romanov@gmail.com 
333*977Smax.romanov@gmail.com     if (extra_fields > req->response_max_fields
334*977Smax.romanov@gmail.com                        - req->response->fields_count
335*977Smax.romanov@gmail.com         || extra_data > (uint32_t) (buf->end - buf->free))
336*977Smax.romanov@gmail.com     {
337*977Smax.romanov@gmail.com         p = buf->start + req->response_max_fields * sizeof(nxt_unit_field_t);
338*977Smax.romanov@gmail.com 
339*977Smax.romanov@gmail.com         max_size = 2 * (buf->end - p);
340*977Smax.romanov@gmail.com         if (max_size > nxt_unit_buf_max()) {
341*977Smax.romanov@gmail.com             nxt_unit_req_warn(req, "required max_size is too big: %"PRIu32,
342*977Smax.romanov@gmail.com                 max_size);
343*977Smax.romanov@gmail.com             return NULL;
344*977Smax.romanov@gmail.com         }
345*977Smax.romanov@gmail.com 
346*977Smax.romanov@gmail.com         rc = nxt_unit_response_realloc(req, 2 * req->response_max_fields,
347*977Smax.romanov@gmail.com                                        max_size);
348*977Smax.romanov@gmail.com         if (rc != NXT_UNIT_OK) {
349*977Smax.romanov@gmail.com             nxt_unit_req_warn(req, "reallocation failed: %"PRIu32", %"PRIu32,
350*977Smax.romanov@gmail.com                 2 * req->response_max_fields, max_size);
351*977Smax.romanov@gmail.com             return NULL;
352*977Smax.romanov@gmail.com         }
353*977Smax.romanov@gmail.com     }
354*977Smax.romanov@gmail.com 
355*977Smax.romanov@gmail.com     return req;
356*977Smax.romanov@gmail.com }
357*977Smax.romanov@gmail.com 
358*977Smax.romanov@gmail.com 
359*977Smax.romanov@gmail.com static void JNICALL
360*977Smax.romanov@gmail.com nxt_java_Response_addIntHeader(JNIEnv *env, jclass cls, jlong req_info_ptr,
361*977Smax.romanov@gmail.com     jarray name, jint value)
362*977Smax.romanov@gmail.com {
363*977Smax.romanov@gmail.com     char                     *name_str;
364*977Smax.romanov@gmail.com     jsize                    name_len;
365*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
366*977Smax.romanov@gmail.com 
367*977Smax.romanov@gmail.com     name_len = (*env)->GetArrayLength(env, name);
368*977Smax.romanov@gmail.com 
369*977Smax.romanov@gmail.com     req = nxt_java_get_response_info(req_info_ptr, 1, name_len + 40);
370*977Smax.romanov@gmail.com     if (req == NULL) {
371*977Smax.romanov@gmail.com         return;
372*977Smax.romanov@gmail.com     }
373*977Smax.romanov@gmail.com 
374*977Smax.romanov@gmail.com     name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL);
375*977Smax.romanov@gmail.com     if (name_str == NULL) {
376*977Smax.romanov@gmail.com         nxt_unit_req_warn(req, "addIntHeader: failed to get name content");
377*977Smax.romanov@gmail.com         return;
378*977Smax.romanov@gmail.com     }
379*977Smax.romanov@gmail.com 
380*977Smax.romanov@gmail.com     nxt_java_add_int_header(req, name_str, name_len, value);
381*977Smax.romanov@gmail.com 
382*977Smax.romanov@gmail.com     (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
383*977Smax.romanov@gmail.com }
384*977Smax.romanov@gmail.com 
385*977Smax.romanov@gmail.com 
386*977Smax.romanov@gmail.com static void
387*977Smax.romanov@gmail.com nxt_java_add_int_header(nxt_unit_request_info_t *req, const char *name,
388*977Smax.romanov@gmail.com     uint8_t name_len, int value)
389*977Smax.romanov@gmail.com {
390*977Smax.romanov@gmail.com     char                 *p;
391*977Smax.romanov@gmail.com     nxt_unit_field_t     *f;
392*977Smax.romanov@gmail.com     nxt_unit_response_t  *resp;
393*977Smax.romanov@gmail.com 
394*977Smax.romanov@gmail.com     resp = req->response;
395*977Smax.romanov@gmail.com 
396*977Smax.romanov@gmail.com     f = resp->fields + resp->fields_count;
397*977Smax.romanov@gmail.com     p = req->response_buf->free;
398*977Smax.romanov@gmail.com 
399*977Smax.romanov@gmail.com     f->hash = nxt_unit_field_hash(name, name_len);
400*977Smax.romanov@gmail.com     f->skip = 0;
401*977Smax.romanov@gmail.com     f->name_length = name_len;
402*977Smax.romanov@gmail.com 
403*977Smax.romanov@gmail.com     nxt_unit_sptr_set(&f->name, p);
404*977Smax.romanov@gmail.com     memcpy(p, name, name_len);
405*977Smax.romanov@gmail.com     p += name_len;
406*977Smax.romanov@gmail.com 
407*977Smax.romanov@gmail.com     nxt_unit_sptr_set(&f->value, p);
408*977Smax.romanov@gmail.com     f->value_length = snprintf(p, 40, "%d", (int) value);
409*977Smax.romanov@gmail.com     p += f->value_length + 1;
410*977Smax.romanov@gmail.com 
411*977Smax.romanov@gmail.com     resp->fields_count++;
412*977Smax.romanov@gmail.com     req->response_buf->free = p;
413*977Smax.romanov@gmail.com 
414*977Smax.romanov@gmail.com }
415*977Smax.romanov@gmail.com 
416*977Smax.romanov@gmail.com 
417*977Smax.romanov@gmail.com static jboolean JNICALL
418*977Smax.romanov@gmail.com nxt_java_Response_containsHeader(JNIEnv *env,
419*977Smax.romanov@gmail.com     jclass cls, jlong req_info_ptr, jarray name)
420*977Smax.romanov@gmail.com {
421*977Smax.romanov@gmail.com     jboolean                 res;
422*977Smax.romanov@gmail.com     char                     *name_str;
423*977Smax.romanov@gmail.com     jsize                    name_len;
424*977Smax.romanov@gmail.com     nxt_unit_response_t      *resp;
425*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
426*977Smax.romanov@gmail.com 
427*977Smax.romanov@gmail.com     req = nxt_jlong2ptr(req_info_ptr);
428*977Smax.romanov@gmail.com 
429*977Smax.romanov@gmail.com     if (!nxt_unit_response_is_init(req)) {
430*977Smax.romanov@gmail.com         nxt_unit_req_debug(req, "containsHeader: response is not initialized");
431*977Smax.romanov@gmail.com         return 0;
432*977Smax.romanov@gmail.com     }
433*977Smax.romanov@gmail.com 
434*977Smax.romanov@gmail.com     if (nxt_unit_response_is_sent(req)) {
435*977Smax.romanov@gmail.com         nxt_unit_req_debug(req, "containsHeader: response already sent");
436*977Smax.romanov@gmail.com         return 0;
437*977Smax.romanov@gmail.com     }
438*977Smax.romanov@gmail.com 
439*977Smax.romanov@gmail.com     name_len = (*env)->GetArrayLength(env, name);
440*977Smax.romanov@gmail.com 
441*977Smax.romanov@gmail.com     name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL);
442*977Smax.romanov@gmail.com     if (name_str == NULL) {
443*977Smax.romanov@gmail.com         nxt_unit_req_warn(req, "containsHeader: failed to get name content");
444*977Smax.romanov@gmail.com         return 0;
445*977Smax.romanov@gmail.com     }
446*977Smax.romanov@gmail.com 
447*977Smax.romanov@gmail.com     resp = req->response;
448*977Smax.romanov@gmail.com 
449*977Smax.romanov@gmail.com     res = nxt_java_findHeader(resp->fields,
450*977Smax.romanov@gmail.com                               resp->fields + resp->fields_count,
451*977Smax.romanov@gmail.com                               name_str, name_len) != NULL;
452*977Smax.romanov@gmail.com 
453*977Smax.romanov@gmail.com     (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
454*977Smax.romanov@gmail.com 
455*977Smax.romanov@gmail.com     return res;
456*977Smax.romanov@gmail.com }
457*977Smax.romanov@gmail.com 
458*977Smax.romanov@gmail.com 
459*977Smax.romanov@gmail.com static jstring JNICALL
460*977Smax.romanov@gmail.com nxt_java_Response_getHeader(JNIEnv *env, jclass cls, jlong req_info_ptr,
461*977Smax.romanov@gmail.com     jarray name)
462*977Smax.romanov@gmail.com {
463*977Smax.romanov@gmail.com     char                     *name_str;
464*977Smax.romanov@gmail.com     jsize                    name_len;
465*977Smax.romanov@gmail.com     nxt_unit_field_t         *f;
466*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
467*977Smax.romanov@gmail.com 
468*977Smax.romanov@gmail.com     req = nxt_jlong2ptr(req_info_ptr);
469*977Smax.romanov@gmail.com 
470*977Smax.romanov@gmail.com     if (!nxt_unit_response_is_init(req)) {
471*977Smax.romanov@gmail.com         nxt_unit_req_debug(req, "getHeader: response is not initialized");
472*977Smax.romanov@gmail.com         return NULL;
473*977Smax.romanov@gmail.com     }
474*977Smax.romanov@gmail.com 
475*977Smax.romanov@gmail.com     if (nxt_unit_response_is_sent(req)) {
476*977Smax.romanov@gmail.com         nxt_unit_req_debug(req, "getHeader: response already sent");
477*977Smax.romanov@gmail.com         return NULL;
478*977Smax.romanov@gmail.com     }
479*977Smax.romanov@gmail.com 
480*977Smax.romanov@gmail.com     name_len = (*env)->GetArrayLength(env, name);
481*977Smax.romanov@gmail.com 
482*977Smax.romanov@gmail.com     name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL);
483*977Smax.romanov@gmail.com     if (name_str == NULL) {
484*977Smax.romanov@gmail.com         nxt_unit_req_warn(req, "getHeader: failed to get name content");
485*977Smax.romanov@gmail.com         return NULL;
486*977Smax.romanov@gmail.com     }
487*977Smax.romanov@gmail.com 
488*977Smax.romanov@gmail.com     f = nxt_java_findHeader(req->response->fields,
489*977Smax.romanov@gmail.com                             req->response->fields + req->response->fields_count,
490*977Smax.romanov@gmail.com                             name_str, name_len);
491*977Smax.romanov@gmail.com 
492*977Smax.romanov@gmail.com     (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
493*977Smax.romanov@gmail.com 
494*977Smax.romanov@gmail.com     if (f == NULL) {
495*977Smax.romanov@gmail.com         return NULL;
496*977Smax.romanov@gmail.com     }
497*977Smax.romanov@gmail.com 
498*977Smax.romanov@gmail.com     return nxt_java_newString(env, nxt_unit_sptr_get(&f->value),
499*977Smax.romanov@gmail.com                               f->value_length);
500*977Smax.romanov@gmail.com }
501*977Smax.romanov@gmail.com 
502*977Smax.romanov@gmail.com 
503*977Smax.romanov@gmail.com static jobject JNICALL
504*977Smax.romanov@gmail.com nxt_java_Response_getHeaderNames(JNIEnv *env, jclass cls, jlong req_info_ptr)
505*977Smax.romanov@gmail.com {
506*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
507*977Smax.romanov@gmail.com 
508*977Smax.romanov@gmail.com     req = nxt_jlong2ptr(req_info_ptr);
509*977Smax.romanov@gmail.com 
510*977Smax.romanov@gmail.com     if (!nxt_unit_response_is_init(req)) {
511*977Smax.romanov@gmail.com         nxt_unit_req_debug(req, "getHeaderNames: response is not initialized");
512*977Smax.romanov@gmail.com         return NULL;
513*977Smax.romanov@gmail.com     }
514*977Smax.romanov@gmail.com 
515*977Smax.romanov@gmail.com     if (nxt_unit_response_is_sent(req)) {
516*977Smax.romanov@gmail.com         nxt_unit_req_debug(req, "getHeaderNames: response already sent");
517*977Smax.romanov@gmail.com         return NULL;
518*977Smax.romanov@gmail.com     }
519*977Smax.romanov@gmail.com 
520*977Smax.romanov@gmail.com     return nxt_java_newHeaderNamesEnumeration(env, req->response->fields,
521*977Smax.romanov@gmail.com                                               req->response->fields_count);
522*977Smax.romanov@gmail.com }
523*977Smax.romanov@gmail.com 
524*977Smax.romanov@gmail.com 
525*977Smax.romanov@gmail.com static jobject JNICALL
526*977Smax.romanov@gmail.com nxt_java_Response_getHeaders(JNIEnv *env, jclass cls,
527*977Smax.romanov@gmail.com     jlong req_info_ptr, jarray name)
528*977Smax.romanov@gmail.com {
529*977Smax.romanov@gmail.com     char                     *name_str;
530*977Smax.romanov@gmail.com     jsize                    name_len;
531*977Smax.romanov@gmail.com     nxt_unit_field_t         *f;
532*977Smax.romanov@gmail.com     nxt_unit_response_t      *resp;
533*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
534*977Smax.romanov@gmail.com 
535*977Smax.romanov@gmail.com     req = nxt_jlong2ptr(req_info_ptr);
536*977Smax.romanov@gmail.com 
537*977Smax.romanov@gmail.com     if (!nxt_unit_response_is_init(req)) {
538*977Smax.romanov@gmail.com         nxt_unit_req_debug(req, "getHeaders: response is not initialized");
539*977Smax.romanov@gmail.com         return NULL;
540*977Smax.romanov@gmail.com     }
541*977Smax.romanov@gmail.com 
542*977Smax.romanov@gmail.com     if (nxt_unit_response_is_sent(req)) {
543*977Smax.romanov@gmail.com         nxt_unit_req_debug(req, "getHeaders: response already sent");
544*977Smax.romanov@gmail.com         return NULL;
545*977Smax.romanov@gmail.com     }
546*977Smax.romanov@gmail.com 
547*977Smax.romanov@gmail.com     resp = req->response;
548*977Smax.romanov@gmail.com 
549*977Smax.romanov@gmail.com     name_len = (*env)->GetArrayLength(env, name);
550*977Smax.romanov@gmail.com 
551*977Smax.romanov@gmail.com     name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL);
552*977Smax.romanov@gmail.com     if (name_str == NULL) {
553*977Smax.romanov@gmail.com         nxt_unit_req_warn(req, "getHeaders: failed to get name content");
554*977Smax.romanov@gmail.com         return NULL;
555*977Smax.romanov@gmail.com     }
556*977Smax.romanov@gmail.com 
557*977Smax.romanov@gmail.com     f = nxt_java_findHeader(resp->fields, resp->fields + resp->fields_count,
558*977Smax.romanov@gmail.com                             name_str, name_len);
559*977Smax.romanov@gmail.com 
560*977Smax.romanov@gmail.com     (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
561*977Smax.romanov@gmail.com 
562*977Smax.romanov@gmail.com     if (f == NULL) {
563*977Smax.romanov@gmail.com         f = resp->fields + resp->fields_count;
564*977Smax.romanov@gmail.com     }
565*977Smax.romanov@gmail.com 
566*977Smax.romanov@gmail.com     return nxt_java_newHeadersEnumeration(env, resp->fields, resp->fields_count,
567*977Smax.romanov@gmail.com                                           f - resp->fields);
568*977Smax.romanov@gmail.com }
569*977Smax.romanov@gmail.com 
570*977Smax.romanov@gmail.com 
571*977Smax.romanov@gmail.com static jint JNICALL
572*977Smax.romanov@gmail.com nxt_java_Response_getStatus(JNIEnv *env, jclass cls, jlong req_info_ptr)
573*977Smax.romanov@gmail.com {
574*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
575*977Smax.romanov@gmail.com 
576*977Smax.romanov@gmail.com     req = nxt_jlong2ptr(req_info_ptr);
577*977Smax.romanov@gmail.com 
578*977Smax.romanov@gmail.com     if (!nxt_unit_response_is_init(req)) {
579*977Smax.romanov@gmail.com         nxt_unit_req_debug(req, "getStatus: response is not initialized");
580*977Smax.romanov@gmail.com         return 200;
581*977Smax.romanov@gmail.com     }
582*977Smax.romanov@gmail.com 
583*977Smax.romanov@gmail.com     if (nxt_unit_response_is_sent(req)) {
584*977Smax.romanov@gmail.com         nxt_unit_req_debug(req, "getStatus: response already sent");
585*977Smax.romanov@gmail.com         return 200;
586*977Smax.romanov@gmail.com     }
587*977Smax.romanov@gmail.com 
588*977Smax.romanov@gmail.com     return req->response->status;
589*977Smax.romanov@gmail.com }
590*977Smax.romanov@gmail.com 
591*977Smax.romanov@gmail.com 
592*977Smax.romanov@gmail.com static jobject JNICALL
593*977Smax.romanov@gmail.com nxt_java_Response_getRequest(JNIEnv *env, jclass cls, jlong req_info_ptr)
594*977Smax.romanov@gmail.com {
595*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
596*977Smax.romanov@gmail.com     nxt_java_request_data_t  *data;
597*977Smax.romanov@gmail.com 
598*977Smax.romanov@gmail.com     req = nxt_jlong2ptr(req_info_ptr);
599*977Smax.romanov@gmail.com     data = req->data;
600*977Smax.romanov@gmail.com 
601*977Smax.romanov@gmail.com     return data->jreq;
602*977Smax.romanov@gmail.com }
603*977Smax.romanov@gmail.com 
604*977Smax.romanov@gmail.com 
605*977Smax.romanov@gmail.com static void JNICALL
606*977Smax.romanov@gmail.com nxt_java_Response_commit(JNIEnv *env, jclass cls, jlong req_info_ptr)
607*977Smax.romanov@gmail.com {
608*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
609*977Smax.romanov@gmail.com 
610*977Smax.romanov@gmail.com     req = nxt_jlong2ptr(req_info_ptr);
611*977Smax.romanov@gmail.com 
612*977Smax.romanov@gmail.com     nxt_java_OutputStream_flush_buf(env, req);
613*977Smax.romanov@gmail.com }
614*977Smax.romanov@gmail.com 
615*977Smax.romanov@gmail.com 
616*977Smax.romanov@gmail.com static void JNICALL
617*977Smax.romanov@gmail.com nxt_java_Response_sendRedirect(JNIEnv *env, jclass cls,
618*977Smax.romanov@gmail.com     jlong req_info_ptr, jarray loc)
619*977Smax.romanov@gmail.com {
620*977Smax.romanov@gmail.com     int                      rc;
621*977Smax.romanov@gmail.com     char                     *loc_str;
622*977Smax.romanov@gmail.com     jsize                    loc_len;
623*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
624*977Smax.romanov@gmail.com 
625*977Smax.romanov@gmail.com     static const char        location[] = "Location";
626*977Smax.romanov@gmail.com     static const uint32_t    location_len = sizeof(location) - 1;
627*977Smax.romanov@gmail.com 
628*977Smax.romanov@gmail.com     req = nxt_jlong2ptr(req_info_ptr);
629*977Smax.romanov@gmail.com 
630*977Smax.romanov@gmail.com     if (nxt_unit_response_is_sent(req)) {
631*977Smax.romanov@gmail.com         nxt_java_throw_IllegalStateException(env, "Response already sent");
632*977Smax.romanov@gmail.com 
633*977Smax.romanov@gmail.com         return;
634*977Smax.romanov@gmail.com     }
635*977Smax.romanov@gmail.com 
636*977Smax.romanov@gmail.com     loc_len = (*env)->GetArrayLength(env, loc);
637*977Smax.romanov@gmail.com 
638*977Smax.romanov@gmail.com     req = nxt_java_get_response_info(req_info_ptr, 1,
639*977Smax.romanov@gmail.com                                      location_len + loc_len + 2);
640*977Smax.romanov@gmail.com     if (req == NULL) {
641*977Smax.romanov@gmail.com         return;
642*977Smax.romanov@gmail.com     }
643*977Smax.romanov@gmail.com 
644*977Smax.romanov@gmail.com     loc_str = (*env)->GetPrimitiveArrayCritical(env, loc, NULL);
645*977Smax.romanov@gmail.com     if (loc_str == NULL) {
646*977Smax.romanov@gmail.com         nxt_unit_req_warn(req, "sendRedirect: failed to get loc content");
647*977Smax.romanov@gmail.com         return;
648*977Smax.romanov@gmail.com     }
649*977Smax.romanov@gmail.com 
650*977Smax.romanov@gmail.com     req->response->status = 302;
651*977Smax.romanov@gmail.com 
652*977Smax.romanov@gmail.com     rc = nxt_java_response_set_header(req_info_ptr, location, location_len,
653*977Smax.romanov@gmail.com                                       loc_str, loc_len);
654*977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
655*977Smax.romanov@gmail.com         // throw
656*977Smax.romanov@gmail.com     }
657*977Smax.romanov@gmail.com 
658*977Smax.romanov@gmail.com     (*env)->ReleasePrimitiveArrayCritical(env, loc, loc_str, 0);
659*977Smax.romanov@gmail.com 
660*977Smax.romanov@gmail.com     nxt_unit_response_send(req);
661*977Smax.romanov@gmail.com }
662*977Smax.romanov@gmail.com 
663*977Smax.romanov@gmail.com 
664*977Smax.romanov@gmail.com static int
665*977Smax.romanov@gmail.com nxt_java_response_set_header(jlong req_info_ptr,
666*977Smax.romanov@gmail.com     const char *name, jint name_len, const char *value, jint value_len)
667*977Smax.romanov@gmail.com {
668*977Smax.romanov@gmail.com     int                      add_field;
669*977Smax.romanov@gmail.com     char                     *dst;
670*977Smax.romanov@gmail.com     nxt_unit_field_t         *f, *e;
671*977Smax.romanov@gmail.com     nxt_unit_response_t      *resp;
672*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
673*977Smax.romanov@gmail.com 
674*977Smax.romanov@gmail.com     req = nxt_java_get_response_info(req_info_ptr, 0, 0);
675*977Smax.romanov@gmail.com     if (req == NULL) {
676*977Smax.romanov@gmail.com         return NXT_UNIT_ERROR;
677*977Smax.romanov@gmail.com     }
678*977Smax.romanov@gmail.com 
679*977Smax.romanov@gmail.com     resp = req->response;
680*977Smax.romanov@gmail.com 
681*977Smax.romanov@gmail.com     f = resp->fields;
682*977Smax.romanov@gmail.com     e = f + resp->fields_count;
683*977Smax.romanov@gmail.com 
684*977Smax.romanov@gmail.com     add_field = 1;
685*977Smax.romanov@gmail.com 
686*977Smax.romanov@gmail.com     for ( ;; ) {
687*977Smax.romanov@gmail.com         f = nxt_java_findHeader(f, e, name, name_len);
688*977Smax.romanov@gmail.com         if (f == NULL) {
689*977Smax.romanov@gmail.com             break;
690*977Smax.romanov@gmail.com         }
691*977Smax.romanov@gmail.com 
692*977Smax.romanov@gmail.com         if (add_field && f->value_length >= (uint32_t) value_len) {
693*977Smax.romanov@gmail.com             dst = nxt_unit_sptr_get(&f->value);
694*977Smax.romanov@gmail.com             memcpy(dst, value, value_len);
695*977Smax.romanov@gmail.com             dst[value_len] = '\0';
696*977Smax.romanov@gmail.com             f->value_length = value_len;
697*977Smax.romanov@gmail.com 
698*977Smax.romanov@gmail.com             add_field = 0;
699*977Smax.romanov@gmail.com             f->skip = 0;
700*977Smax.romanov@gmail.com 
701*977Smax.romanov@gmail.com         } else {
702*977Smax.romanov@gmail.com             f->skip = 1;
703*977Smax.romanov@gmail.com         }
704*977Smax.romanov@gmail.com 
705*977Smax.romanov@gmail.com         ++f;
706*977Smax.romanov@gmail.com     }
707*977Smax.romanov@gmail.com 
708*977Smax.romanov@gmail.com     if (!add_field) {
709*977Smax.romanov@gmail.com         return NXT_UNIT_OK;
710*977Smax.romanov@gmail.com     }
711*977Smax.romanov@gmail.com 
712*977Smax.romanov@gmail.com     req = nxt_java_get_response_info(req_info_ptr, 1, name_len + value_len + 2);
713*977Smax.romanov@gmail.com     if (req == NULL) {
714*977Smax.romanov@gmail.com         return NXT_UNIT_ERROR;
715*977Smax.romanov@gmail.com     }
716*977Smax.romanov@gmail.com 
717*977Smax.romanov@gmail.com     return nxt_unit_response_add_field(req, name, name_len, value, value_len);
718*977Smax.romanov@gmail.com }
719*977Smax.romanov@gmail.com 
720*977Smax.romanov@gmail.com 
721*977Smax.romanov@gmail.com static void JNICALL
722*977Smax.romanov@gmail.com nxt_java_Response_setHeader(JNIEnv *env, jclass cls,
723*977Smax.romanov@gmail.com     jlong req_info_ptr, jarray name, jarray value)
724*977Smax.romanov@gmail.com {
725*977Smax.romanov@gmail.com     int                      rc;
726*977Smax.romanov@gmail.com     char                     *name_str, *value_str;
727*977Smax.romanov@gmail.com     jsize                    name_len, value_len;
728*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
729*977Smax.romanov@gmail.com 
730*977Smax.romanov@gmail.com     name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL);
731*977Smax.romanov@gmail.com     if (name_str == NULL) {
732*977Smax.romanov@gmail.com         req = nxt_jlong2ptr(req_info_ptr);
733*977Smax.romanov@gmail.com         nxt_unit_req_warn(req, "setHeader: failed to get name content");
734*977Smax.romanov@gmail.com         return;
735*977Smax.romanov@gmail.com     }
736*977Smax.romanov@gmail.com 
737*977Smax.romanov@gmail.com     value_str = (*env)->GetPrimitiveArrayCritical(env, value, NULL);
738*977Smax.romanov@gmail.com     if (value_str == NULL) {
739*977Smax.romanov@gmail.com         (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
740*977Smax.romanov@gmail.com 
741*977Smax.romanov@gmail.com         req = nxt_jlong2ptr(req_info_ptr);
742*977Smax.romanov@gmail.com         nxt_unit_req_warn(req, "setHeader: failed to get value content");
743*977Smax.romanov@gmail.com 
744*977Smax.romanov@gmail.com         return;
745*977Smax.romanov@gmail.com     }
746*977Smax.romanov@gmail.com 
747*977Smax.romanov@gmail.com     name_len = (*env)->GetArrayLength(env, name);
748*977Smax.romanov@gmail.com     value_len = (*env)->GetArrayLength(env, value);
749*977Smax.romanov@gmail.com 
750*977Smax.romanov@gmail.com     rc = nxt_java_response_set_header(req_info_ptr, name_str, name_len,
751*977Smax.romanov@gmail.com                                       value_str, value_len);
752*977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
753*977Smax.romanov@gmail.com         // throw
754*977Smax.romanov@gmail.com     }
755*977Smax.romanov@gmail.com 
756*977Smax.romanov@gmail.com     (*env)->ReleasePrimitiveArrayCritical(env, value, value_str, 0);
757*977Smax.romanov@gmail.com     (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
758*977Smax.romanov@gmail.com }
759*977Smax.romanov@gmail.com 
760*977Smax.romanov@gmail.com 
761*977Smax.romanov@gmail.com static void JNICALL
762*977Smax.romanov@gmail.com nxt_java_Response_removeHeader(JNIEnv *env, jclass cls,
763*977Smax.romanov@gmail.com     jlong req_info_ptr, jarray name)
764*977Smax.romanov@gmail.com {
765*977Smax.romanov@gmail.com     int                      rc;
766*977Smax.romanov@gmail.com     char                     *name_str;
767*977Smax.romanov@gmail.com     jsize                    name_len;
768*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
769*977Smax.romanov@gmail.com 
770*977Smax.romanov@gmail.com     name_len = (*env)->GetArrayLength(env, name);
771*977Smax.romanov@gmail.com 
772*977Smax.romanov@gmail.com     name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL);
773*977Smax.romanov@gmail.com     if (name_str == NULL) {
774*977Smax.romanov@gmail.com         req = nxt_jlong2ptr(req_info_ptr);
775*977Smax.romanov@gmail.com         nxt_unit_req_warn(req, "setHeader: failed to get name content");
776*977Smax.romanov@gmail.com         return;
777*977Smax.romanov@gmail.com     }
778*977Smax.romanov@gmail.com 
779*977Smax.romanov@gmail.com     rc = nxt_java_response_remove_header(req_info_ptr, name_str, name_len);
780*977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
781*977Smax.romanov@gmail.com         // throw
782*977Smax.romanov@gmail.com     }
783*977Smax.romanov@gmail.com 
784*977Smax.romanov@gmail.com     (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
785*977Smax.romanov@gmail.com }
786*977Smax.romanov@gmail.com 
787*977Smax.romanov@gmail.com 
788*977Smax.romanov@gmail.com static int
789*977Smax.romanov@gmail.com nxt_java_response_remove_header(jlong req_info_ptr,
790*977Smax.romanov@gmail.com     const char *name, jint name_len)
791*977Smax.romanov@gmail.com {
792*977Smax.romanov@gmail.com     nxt_unit_field_t         *f, *e;
793*977Smax.romanov@gmail.com     nxt_unit_response_t      *resp;
794*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
795*977Smax.romanov@gmail.com 
796*977Smax.romanov@gmail.com     req = nxt_java_get_response_info(req_info_ptr, 0, 0);
797*977Smax.romanov@gmail.com     if (req == NULL) {
798*977Smax.romanov@gmail.com         return NXT_UNIT_ERROR;
799*977Smax.romanov@gmail.com     }
800*977Smax.romanov@gmail.com 
801*977Smax.romanov@gmail.com     resp = req->response;
802*977Smax.romanov@gmail.com 
803*977Smax.romanov@gmail.com     f = resp->fields;
804*977Smax.romanov@gmail.com     e = f + resp->fields_count;
805*977Smax.romanov@gmail.com 
806*977Smax.romanov@gmail.com     for ( ;; ) {
807*977Smax.romanov@gmail.com         f = nxt_java_findHeader(f, e, name, name_len);
808*977Smax.romanov@gmail.com         if (f == NULL) {
809*977Smax.romanov@gmail.com             break;
810*977Smax.romanov@gmail.com         }
811*977Smax.romanov@gmail.com 
812*977Smax.romanov@gmail.com         f->skip = 1;
813*977Smax.romanov@gmail.com 
814*977Smax.romanov@gmail.com         ++f;
815*977Smax.romanov@gmail.com     }
816*977Smax.romanov@gmail.com 
817*977Smax.romanov@gmail.com     return NXT_UNIT_OK;
818*977Smax.romanov@gmail.com }
819*977Smax.romanov@gmail.com 
820*977Smax.romanov@gmail.com 
821*977Smax.romanov@gmail.com static void JNICALL
822*977Smax.romanov@gmail.com nxt_java_Response_setIntHeader(JNIEnv *env, jclass cls,
823*977Smax.romanov@gmail.com     jlong req_info_ptr, jarray name, jint value)
824*977Smax.romanov@gmail.com {
825*977Smax.romanov@gmail.com     int    value_len, rc;
826*977Smax.romanov@gmail.com     char   value_str[40];
827*977Smax.romanov@gmail.com     char   *name_str;
828*977Smax.romanov@gmail.com     jsize  name_len;
829*977Smax.romanov@gmail.com 
830*977Smax.romanov@gmail.com     value_len = snprintf(value_str, sizeof(value_str), "%d", (int) value);
831*977Smax.romanov@gmail.com 
832*977Smax.romanov@gmail.com     name_len = (*env)->GetArrayLength(env, name);
833*977Smax.romanov@gmail.com 
834*977Smax.romanov@gmail.com     name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL);
835*977Smax.romanov@gmail.com     if (name_str == NULL) {
836*977Smax.romanov@gmail.com         nxt_unit_req_warn(nxt_jlong2ptr(req_info_ptr),
837*977Smax.romanov@gmail.com                           "setIntHeader: failed to get name content");
838*977Smax.romanov@gmail.com         return;
839*977Smax.romanov@gmail.com     }
840*977Smax.romanov@gmail.com 
841*977Smax.romanov@gmail.com     rc = nxt_java_response_set_header(req_info_ptr, name_str, name_len,
842*977Smax.romanov@gmail.com                                       value_str, value_len);
843*977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
844*977Smax.romanov@gmail.com         // throw
845*977Smax.romanov@gmail.com     }
846*977Smax.romanov@gmail.com 
847*977Smax.romanov@gmail.com     (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
848*977Smax.romanov@gmail.com }
849*977Smax.romanov@gmail.com 
850*977Smax.romanov@gmail.com 
851*977Smax.romanov@gmail.com static void JNICALL
852*977Smax.romanov@gmail.com nxt_java_Response_setStatus(JNIEnv *env, jclass cls, jlong req_info_ptr,
853*977Smax.romanov@gmail.com     jint sc)
854*977Smax.romanov@gmail.com {
855*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
856*977Smax.romanov@gmail.com 
857*977Smax.romanov@gmail.com     req = nxt_java_get_response_info(req_info_ptr, 0, 0);
858*977Smax.romanov@gmail.com     if (req == NULL) {
859*977Smax.romanov@gmail.com         return;
860*977Smax.romanov@gmail.com     }
861*977Smax.romanov@gmail.com 
862*977Smax.romanov@gmail.com     req->response->status = sc;
863*977Smax.romanov@gmail.com }
864*977Smax.romanov@gmail.com 
865*977Smax.romanov@gmail.com 
866*977Smax.romanov@gmail.com static jstring JNICALL
867*977Smax.romanov@gmail.com nxt_java_Response_getContentType(JNIEnv *env, jclass cls, jlong req_info_ptr)
868*977Smax.romanov@gmail.com {
869*977Smax.romanov@gmail.com     nxt_unit_field_t         *f;
870*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
871*977Smax.romanov@gmail.com 
872*977Smax.romanov@gmail.com     req = nxt_jlong2ptr(req_info_ptr);
873*977Smax.romanov@gmail.com 
874*977Smax.romanov@gmail.com     if (!nxt_unit_response_is_init(req)) {
875*977Smax.romanov@gmail.com         nxt_unit_req_debug(req, "getContentType: response is not initialized");
876*977Smax.romanov@gmail.com         return NULL;
877*977Smax.romanov@gmail.com     }
878*977Smax.romanov@gmail.com 
879*977Smax.romanov@gmail.com     if (nxt_unit_response_is_sent(req)) {
880*977Smax.romanov@gmail.com         nxt_unit_req_debug(req, "getContentType: response already sent");
881*977Smax.romanov@gmail.com         return NULL;
882*977Smax.romanov@gmail.com     }
883*977Smax.romanov@gmail.com 
884*977Smax.romanov@gmail.com     f = nxt_java_findHeader(req->response->fields,
885*977Smax.romanov@gmail.com                             req->response->fields + req->response->fields_count,
886*977Smax.romanov@gmail.com                             "Content-Type", sizeof("Content-Type") - 1);
887*977Smax.romanov@gmail.com 
888*977Smax.romanov@gmail.com     if (f == NULL) {
889*977Smax.romanov@gmail.com         return NULL;
890*977Smax.romanov@gmail.com     }
891*977Smax.romanov@gmail.com 
892*977Smax.romanov@gmail.com     return nxt_java_newString(env, nxt_unit_sptr_get(&f->value),
893*977Smax.romanov@gmail.com                               f->value_length);
894*977Smax.romanov@gmail.com }
895*977Smax.romanov@gmail.com 
896*977Smax.romanov@gmail.com 
897*977Smax.romanov@gmail.com static jboolean JNICALL
898*977Smax.romanov@gmail.com nxt_java_Response_isCommitted(JNIEnv *env, jclass cls, jlong req_info_ptr)
899*977Smax.romanov@gmail.com {
900*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
901*977Smax.romanov@gmail.com 
902*977Smax.romanov@gmail.com     req = nxt_jlong2ptr(req_info_ptr);
903*977Smax.romanov@gmail.com 
904*977Smax.romanov@gmail.com     if (nxt_unit_response_is_sent(req)) {
905*977Smax.romanov@gmail.com         return 1;
906*977Smax.romanov@gmail.com     }
907*977Smax.romanov@gmail.com 
908*977Smax.romanov@gmail.com     return 0;
909*977Smax.romanov@gmail.com }
910*977Smax.romanov@gmail.com 
911*977Smax.romanov@gmail.com 
912*977Smax.romanov@gmail.com static void JNICALL
913*977Smax.romanov@gmail.com nxt_java_Response_reset(JNIEnv *env, jclass cls, jlong req_info_ptr)
914*977Smax.romanov@gmail.com {
915*977Smax.romanov@gmail.com     nxt_unit_buf_t           *buf;
916*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
917*977Smax.romanov@gmail.com     nxt_java_request_data_t  *data;
918*977Smax.romanov@gmail.com 
919*977Smax.romanov@gmail.com     req = nxt_jlong2ptr(req_info_ptr);
920*977Smax.romanov@gmail.com 
921*977Smax.romanov@gmail.com     if (nxt_unit_response_is_sent(req)) {
922*977Smax.romanov@gmail.com         nxt_java_throw_IllegalStateException(env, "Response already sent");
923*977Smax.romanov@gmail.com 
924*977Smax.romanov@gmail.com         return;
925*977Smax.romanov@gmail.com     }
926*977Smax.romanov@gmail.com 
927*977Smax.romanov@gmail.com     data = req->data;
928*977Smax.romanov@gmail.com 
929*977Smax.romanov@gmail.com     if (data->buf != NULL && data->buf->free > data->buf->start) {
930*977Smax.romanov@gmail.com         data->buf->free = data->buf->start;
931*977Smax.romanov@gmail.com     }
932*977Smax.romanov@gmail.com 
933*977Smax.romanov@gmail.com     if (nxt_unit_response_is_init(req)) {
934*977Smax.romanov@gmail.com         req->response->status = 200;
935*977Smax.romanov@gmail.com         req->response->fields_count = 0;
936*977Smax.romanov@gmail.com 
937*977Smax.romanov@gmail.com         buf = req->response_buf;
938*977Smax.romanov@gmail.com 
939*977Smax.romanov@gmail.com         buf->free = buf->start + req->response_max_fields
940*977Smax.romanov@gmail.com                                   * sizeof(nxt_unit_field_t);
941*977Smax.romanov@gmail.com     }
942*977Smax.romanov@gmail.com }
943*977Smax.romanov@gmail.com 
944*977Smax.romanov@gmail.com 
945*977Smax.romanov@gmail.com static void JNICALL
946*977Smax.romanov@gmail.com nxt_java_Response_resetBuffer(JNIEnv *env, jclass cls, jlong req_info_ptr)
947*977Smax.romanov@gmail.com {
948*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
949*977Smax.romanov@gmail.com     nxt_java_request_data_t  *data;
950*977Smax.romanov@gmail.com 
951*977Smax.romanov@gmail.com     req = nxt_jlong2ptr(req_info_ptr);
952*977Smax.romanov@gmail.com     data = req->data;
953*977Smax.romanov@gmail.com 
954*977Smax.romanov@gmail.com     if (data->buf != NULL && data->buf->free > data->buf->start) {
955*977Smax.romanov@gmail.com         data->buf->free = data->buf->start;
956*977Smax.romanov@gmail.com     }
957*977Smax.romanov@gmail.com }
958*977Smax.romanov@gmail.com 
959*977Smax.romanov@gmail.com 
960*977Smax.romanov@gmail.com static void JNICALL
961*977Smax.romanov@gmail.com nxt_java_Response_setBufferSize(JNIEnv *env, jclass cls, jlong req_info_ptr,
962*977Smax.romanov@gmail.com     jint size)
963*977Smax.romanov@gmail.com {
964*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
965*977Smax.romanov@gmail.com     nxt_java_request_data_t  *data;
966*977Smax.romanov@gmail.com 
967*977Smax.romanov@gmail.com     req = nxt_jlong2ptr(req_info_ptr);
968*977Smax.romanov@gmail.com     data = req->data;
969*977Smax.romanov@gmail.com 
970*977Smax.romanov@gmail.com     if (data->buf_size == (uint32_t) size) {
971*977Smax.romanov@gmail.com         return;
972*977Smax.romanov@gmail.com     }
973*977Smax.romanov@gmail.com 
974*977Smax.romanov@gmail.com     if (data->buf != NULL && data->buf->free > data->buf->start) {
975*977Smax.romanov@gmail.com         nxt_java_throw_IllegalStateException(env, "Buffer is not empty");
976*977Smax.romanov@gmail.com 
977*977Smax.romanov@gmail.com         return;
978*977Smax.romanov@gmail.com     }
979*977Smax.romanov@gmail.com 
980*977Smax.romanov@gmail.com     data->buf_size = size;
981*977Smax.romanov@gmail.com 
982*977Smax.romanov@gmail.com     if (data->buf_size > nxt_unit_buf_max()) {
983*977Smax.romanov@gmail.com         data->buf_size = nxt_unit_buf_max();
984*977Smax.romanov@gmail.com     }
985*977Smax.romanov@gmail.com 
986*977Smax.romanov@gmail.com     if (data->buf != NULL
987*977Smax.romanov@gmail.com         && (uint32_t) (data->buf->end - data->buf->start) < data->buf_size)
988*977Smax.romanov@gmail.com     {
989*977Smax.romanov@gmail.com         nxt_unit_buf_free(data->buf);
990*977Smax.romanov@gmail.com 
991*977Smax.romanov@gmail.com         data->buf = NULL;
992*977Smax.romanov@gmail.com     }
993*977Smax.romanov@gmail.com }
994*977Smax.romanov@gmail.com 
995*977Smax.romanov@gmail.com 
996*977Smax.romanov@gmail.com static jint JNICALL
997*977Smax.romanov@gmail.com nxt_java_Response_getBufferSize(JNIEnv *env, jclass cls, jlong req_info_ptr)
998*977Smax.romanov@gmail.com {
999*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
1000*977Smax.romanov@gmail.com     nxt_java_request_data_t  *data;
1001*977Smax.romanov@gmail.com 
1002*977Smax.romanov@gmail.com     req = nxt_jlong2ptr(req_info_ptr);
1003*977Smax.romanov@gmail.com     data = req->data;
1004*977Smax.romanov@gmail.com 
1005*977Smax.romanov@gmail.com     return data->buf_size;
1006*977Smax.romanov@gmail.com }
1007*977Smax.romanov@gmail.com 
1008*977Smax.romanov@gmail.com 
1009*977Smax.romanov@gmail.com static void JNICALL
1010*977Smax.romanov@gmail.com nxt_java_Response_setContentLength(JNIEnv *env, jclass cls, jlong req_info_ptr,
1011*977Smax.romanov@gmail.com     jlong len)
1012*977Smax.romanov@gmail.com {
1013*977Smax.romanov@gmail.com     nxt_unit_request_info_t  *req;
1014*977Smax.romanov@gmail.com 
1015*977Smax.romanov@gmail.com     req = nxt_java_get_response_info(req_info_ptr, 0, 0);
1016*977Smax.romanov@gmail.com     if (req == NULL) {
1017*977Smax.romanov@gmail.com         return;
1018*977Smax.romanov@gmail.com     }
1019*977Smax.romanov@gmail.com 
1020*977Smax.romanov@gmail.com     req->response->content_length = len;
1021*977Smax.romanov@gmail.com }
1022*977Smax.romanov@gmail.com 
1023*977Smax.romanov@gmail.com 
1024*977Smax.romanov@gmail.com static void JNICALL
1025*977Smax.romanov@gmail.com nxt_java_Response_setContentType(JNIEnv *env, jclass cls, jlong req_info_ptr,
1026*977Smax.romanov@gmail.com     jarray type)
1027*977Smax.romanov@gmail.com {
1028*977Smax.romanov@gmail.com     int    rc;
1029*977Smax.romanov@gmail.com     char   *type_str;
1030*977Smax.romanov@gmail.com     jsize  type_len;
1031*977Smax.romanov@gmail.com 
1032*977Smax.romanov@gmail.com     static const char      content_type[] = "Content-Type";
1033*977Smax.romanov@gmail.com     static const uint32_t  content_type_len = sizeof(content_type) - 1;
1034*977Smax.romanov@gmail.com 
1035*977Smax.romanov@gmail.com     type_len = (*env)->GetArrayLength(env, type);
1036*977Smax.romanov@gmail.com 
1037*977Smax.romanov@gmail.com     type_str = (*env)->GetPrimitiveArrayCritical(env, type, NULL);
1038*977Smax.romanov@gmail.com     if (type_str == NULL) {
1039*977Smax.romanov@gmail.com         return;
1040*977Smax.romanov@gmail.com     }
1041*977Smax.romanov@gmail.com 
1042*977Smax.romanov@gmail.com     rc = nxt_java_response_set_header(req_info_ptr,
1043*977Smax.romanov@gmail.com                                       content_type, content_type_len,
1044