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 <jni.h>
9*977Smax.romanov@gmail.com #include <nxt_unit.h>
10*977Smax.romanov@gmail.com
11*977Smax.romanov@gmail.com #include "nxt_jni.h"
12*977Smax.romanov@gmail.com #include "nxt_jni_OutputStream.h"
13*977Smax.romanov@gmail.com #include "nxt_jni_URLClassLoader.h"
14*977Smax.romanov@gmail.com
15*977Smax.romanov@gmail.com
16*977Smax.romanov@gmail.com static void JNICALL nxt_java_OutputStream_writeByte(JNIEnv *env, jclass cls,
17*977Smax.romanov@gmail.com jlong req_info_ptr, jint b);
18*977Smax.romanov@gmail.com static nxt_unit_buf_t *nxt_java_OutputStream_req_buf(JNIEnv *env,
19*977Smax.romanov@gmail.com nxt_unit_request_info_t *req);
20*977Smax.romanov@gmail.com static void JNICALL nxt_java_OutputStream_write(JNIEnv *env, jclass cls,
21*977Smax.romanov@gmail.com jlong req_info_ptr, jarray b, jint off, jint len);
22*977Smax.romanov@gmail.com static void JNICALL nxt_java_OutputStream_flush(JNIEnv *env, jclass cls,
23*977Smax.romanov@gmail.com jlong req_info_ptr);
24*977Smax.romanov@gmail.com static void JNICALL nxt_java_OutputStream_close(JNIEnv *env, jclass cls,
25*977Smax.romanov@gmail.com jlong req_info_ptr);
26*977Smax.romanov@gmail.com
27*977Smax.romanov@gmail.com
28*977Smax.romanov@gmail.com static jclass nxt_java_OutputStream_class;
29*977Smax.romanov@gmail.com
30*977Smax.romanov@gmail.com
31*977Smax.romanov@gmail.com int
nxt_java_initOutputStream(JNIEnv * env,jobject cl)32*977Smax.romanov@gmail.com nxt_java_initOutputStream(JNIEnv *env, jobject cl)
33*977Smax.romanov@gmail.com {
34*977Smax.romanov@gmail.com int res;
35*977Smax.romanov@gmail.com jclass cls;
36*977Smax.romanov@gmail.com
37*977Smax.romanov@gmail.com cls = nxt_java_loadClass(env, cl, "nginx.unit.OutputStream");
38*977Smax.romanov@gmail.com if (cls == NULL) {
39*977Smax.romanov@gmail.com return NXT_UNIT_ERROR;
40*977Smax.romanov@gmail.com }
41*977Smax.romanov@gmail.com
42*977Smax.romanov@gmail.com nxt_java_OutputStream_class = (*env)->NewGlobalRef(env, cls);
43*977Smax.romanov@gmail.com (*env)->DeleteLocalRef(env, cls);
44*977Smax.romanov@gmail.com
45*977Smax.romanov@gmail.com cls = nxt_java_OutputStream_class;
46*977Smax.romanov@gmail.com
47*977Smax.romanov@gmail.com JNINativeMethod os_methods[] = {
48*977Smax.romanov@gmail.com { (char *) "write",
49*977Smax.romanov@gmail.com (char *) "(JI)V",
50*977Smax.romanov@gmail.com nxt_java_OutputStream_writeByte },
51*977Smax.romanov@gmail.com
52*977Smax.romanov@gmail.com { (char *) "write",
53*977Smax.romanov@gmail.com (char *) "(J[BII)V",
54*977Smax.romanov@gmail.com nxt_java_OutputStream_write },
55*977Smax.romanov@gmail.com
56*977Smax.romanov@gmail.com { (char *) "flush",
57*977Smax.romanov@gmail.com (char *) "(J)V",
58*977Smax.romanov@gmail.com nxt_java_OutputStream_flush },
59*977Smax.romanov@gmail.com
60*977Smax.romanov@gmail.com { (char *) "close",
61*977Smax.romanov@gmail.com (char *) "(J)V",
62*977Smax.romanov@gmail.com nxt_java_OutputStream_close },
63*977Smax.romanov@gmail.com };
64*977Smax.romanov@gmail.com
65*977Smax.romanov@gmail.com res = (*env)->RegisterNatives(env, nxt_java_OutputStream_class,
66*977Smax.romanov@gmail.com os_methods,
67*977Smax.romanov@gmail.com sizeof(os_methods) / sizeof(os_methods[0]));
68*977Smax.romanov@gmail.com
69*977Smax.romanov@gmail.com nxt_unit_debug(NULL, "registered OutputStream methods: %d", res);
70*977Smax.romanov@gmail.com
71*977Smax.romanov@gmail.com if (res != 0) {
72*977Smax.romanov@gmail.com (*env)->DeleteGlobalRef(env, cls);
73*977Smax.romanov@gmail.com return NXT_UNIT_ERROR;
74*977Smax.romanov@gmail.com }
75*977Smax.romanov@gmail.com
76*977Smax.romanov@gmail.com return NXT_UNIT_OK;
77*977Smax.romanov@gmail.com }
78*977Smax.romanov@gmail.com
79*977Smax.romanov@gmail.com
80*977Smax.romanov@gmail.com static void JNICALL
nxt_java_OutputStream_writeByte(JNIEnv * env,jclass cls,jlong req_info_ptr,jint b)81*977Smax.romanov@gmail.com nxt_java_OutputStream_writeByte(JNIEnv *env, jclass cls, jlong req_info_ptr,
82*977Smax.romanov@gmail.com jint b)
83*977Smax.romanov@gmail.com {
84*977Smax.romanov@gmail.com nxt_unit_buf_t *buf;
85*977Smax.romanov@gmail.com nxt_unit_request_info_t *req;
86*977Smax.romanov@gmail.com nxt_java_request_data_t *data;
87*977Smax.romanov@gmail.com
88*977Smax.romanov@gmail.com req = nxt_jlong2ptr(req_info_ptr);
89*977Smax.romanov@gmail.com data = req->data;
90*977Smax.romanov@gmail.com
91*977Smax.romanov@gmail.com buf = nxt_java_OutputStream_req_buf(env, req);
92*977Smax.romanov@gmail.com if (buf == NULL) {
93*977Smax.romanov@gmail.com return;
94*977Smax.romanov@gmail.com }
95*977Smax.romanov@gmail.com
96*977Smax.romanov@gmail.com *buf->free++ = b;
97*977Smax.romanov@gmail.com
98*977Smax.romanov@gmail.com if ((uint32_t) (buf->free - buf->start) >= data->buf_size) {
99*977Smax.romanov@gmail.com nxt_java_OutputStream_flush_buf(env, req);
100*977Smax.romanov@gmail.com }
101*977Smax.romanov@gmail.com }
102*977Smax.romanov@gmail.com
103*977Smax.romanov@gmail.com
104*977Smax.romanov@gmail.com int
nxt_java_OutputStream_flush_buf(JNIEnv * env,nxt_unit_request_info_t * req)105*977Smax.romanov@gmail.com nxt_java_OutputStream_flush_buf(JNIEnv *env, nxt_unit_request_info_t *req)
106*977Smax.romanov@gmail.com {
107*977Smax.romanov@gmail.com int rc;
108*977Smax.romanov@gmail.com nxt_java_request_data_t *data;
109*977Smax.romanov@gmail.com
110*977Smax.romanov@gmail.com data = req->data;
111*977Smax.romanov@gmail.com
112*977Smax.romanov@gmail.com if (!nxt_unit_response_is_init(req)) {
113*977Smax.romanov@gmail.com rc = nxt_unit_response_init(req, 200, 0, 0);
114*977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) {
115*977Smax.romanov@gmail.com nxt_java_throw_IOException(env, "Failed to allocate response");
116*977Smax.romanov@gmail.com
117*977Smax.romanov@gmail.com return rc;
118*977Smax.romanov@gmail.com }
119*977Smax.romanov@gmail.com }
120*977Smax.romanov@gmail.com
121*977Smax.romanov@gmail.com if (!nxt_unit_response_is_sent(req)) {
122*977Smax.romanov@gmail.com rc = nxt_unit_response_send(req);
123*977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) {
124*977Smax.romanov@gmail.com nxt_java_throw_IOException(env, "Failed to send response headers");
125*977Smax.romanov@gmail.com
126*977Smax.romanov@gmail.com return rc;
127*977Smax.romanov@gmail.com }
128*977Smax.romanov@gmail.com }
129*977Smax.romanov@gmail.com
130*977Smax.romanov@gmail.com if (data->buf != NULL) {
131*977Smax.romanov@gmail.com rc = nxt_unit_buf_send(data->buf);
132*977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) {
133*977Smax.romanov@gmail.com nxt_java_throw_IOException(env, "Failed to send buffer");
134*977Smax.romanov@gmail.com
135*977Smax.romanov@gmail.com } else {
136*977Smax.romanov@gmail.com data->buf = NULL;
137*977Smax.romanov@gmail.com }
138*977Smax.romanov@gmail.com
139*977Smax.romanov@gmail.com } else {
140*977Smax.romanov@gmail.com rc = NXT_UNIT_OK;
141*977Smax.romanov@gmail.com }
142*977Smax.romanov@gmail.com
143*977Smax.romanov@gmail.com return rc;
144*977Smax.romanov@gmail.com }
145*977Smax.romanov@gmail.com
146*977Smax.romanov@gmail.com
147*977Smax.romanov@gmail.com static nxt_unit_buf_t *
nxt_java_OutputStream_req_buf(JNIEnv * env,nxt_unit_request_info_t * req)148*977Smax.romanov@gmail.com nxt_java_OutputStream_req_buf(JNIEnv *env, nxt_unit_request_info_t *req)
149*977Smax.romanov@gmail.com {
150*977Smax.romanov@gmail.com uint32_t size;
151*977Smax.romanov@gmail.com nxt_unit_buf_t *buf;
152*977Smax.romanov@gmail.com nxt_java_request_data_t *data;
153*977Smax.romanov@gmail.com
154*977Smax.romanov@gmail.com data = req->data;
155*977Smax.romanov@gmail.com buf = data->buf;
156*977Smax.romanov@gmail.com
157*977Smax.romanov@gmail.com if (buf == NULL || buf->free >= buf->end) {
158*977Smax.romanov@gmail.com size = data->buf_size == 0 ? nxt_unit_buf_min() : data->buf_size;
159*977Smax.romanov@gmail.com
160*977Smax.romanov@gmail.com buf = nxt_unit_response_buf_alloc(req, size);
161*977Smax.romanov@gmail.com if (buf == NULL) {
162*977Smax.romanov@gmail.com nxt_java_throw_IOException(env, "Failed to allocate buffer");
163*977Smax.romanov@gmail.com
164*977Smax.romanov@gmail.com return NULL;
165*977Smax.romanov@gmail.com }
166*977Smax.romanov@gmail.com
167*977Smax.romanov@gmail.com data->buf = buf;
168*977Smax.romanov@gmail.com }
169*977Smax.romanov@gmail.com
170*977Smax.romanov@gmail.com return buf;
171*977Smax.romanov@gmail.com }
172*977Smax.romanov@gmail.com
173*977Smax.romanov@gmail.com
174*977Smax.romanov@gmail.com static void JNICALL
nxt_java_OutputStream_write(JNIEnv * env,jclass cls,jlong req_info_ptr,jarray b,jint off,jint len)175*977Smax.romanov@gmail.com nxt_java_OutputStream_write(JNIEnv *env, jclass cls, jlong req_info_ptr,
176*977Smax.romanov@gmail.com jarray b, jint off, jint len)
177*977Smax.romanov@gmail.com {
178*977Smax.romanov@gmail.com int rc;
179*977Smax.romanov@gmail.com jint copy;
180*977Smax.romanov@gmail.com uint8_t *ptr;
181*977Smax.romanov@gmail.com nxt_unit_buf_t *buf;
182*977Smax.romanov@gmail.com nxt_unit_request_info_t *req;
183*977Smax.romanov@gmail.com nxt_java_request_data_t *data;
184*977Smax.romanov@gmail.com
185*977Smax.romanov@gmail.com req = nxt_jlong2ptr(req_info_ptr);
186*977Smax.romanov@gmail.com data = req->data;
187*977Smax.romanov@gmail.com
188*977Smax.romanov@gmail.com ptr = (*env)->GetPrimitiveArrayCritical(env, b, NULL);
189*977Smax.romanov@gmail.com
190*977Smax.romanov@gmail.com while (len > 0) {
191*977Smax.romanov@gmail.com buf = nxt_java_OutputStream_req_buf(env, req);
192*977Smax.romanov@gmail.com if (buf == NULL) {
193*977Smax.romanov@gmail.com return;
194*977Smax.romanov@gmail.com }
195*977Smax.romanov@gmail.com
196*977Smax.romanov@gmail.com copy = buf->end - buf->free;
197*977Smax.romanov@gmail.com copy = copy < len ? copy : len;
198*977Smax.romanov@gmail.com
199*977Smax.romanov@gmail.com memcpy(buf->free, ptr + off, copy);
200*977Smax.romanov@gmail.com buf->free += copy;
201*977Smax.romanov@gmail.com
202*977Smax.romanov@gmail.com len -= copy;
203*977Smax.romanov@gmail.com off += copy;
204*977Smax.romanov@gmail.com
205*977Smax.romanov@gmail.com if ((uint32_t) (buf->free - buf->start) >= data->buf_size) {
206*977Smax.romanov@gmail.com rc = nxt_java_OutputStream_flush_buf(env, req);
207*977Smax.romanov@gmail.com if (rc != NXT_UNIT_OK) {
208*977Smax.romanov@gmail.com break;
209*977Smax.romanov@gmail.com }
210*977Smax.romanov@gmail.com }
211*977Smax.romanov@gmail.com }
212*977Smax.romanov@gmail.com
213*977Smax.romanov@gmail.com (*env)->ReleasePrimitiveArrayCritical(env, b, ptr, 0);
214*977Smax.romanov@gmail.com }
215*977Smax.romanov@gmail.com
216*977Smax.romanov@gmail.com
217*977Smax.romanov@gmail.com static void JNICALL
nxt_java_OutputStream_flush(JNIEnv * env,jclass cls,jlong req_info_ptr)218*977Smax.romanov@gmail.com nxt_java_OutputStream_flush(JNIEnv *env, jclass cls, jlong req_info_ptr)
219*977Smax.romanov@gmail.com {
220*977Smax.romanov@gmail.com nxt_unit_request_info_t *req;
221*977Smax.romanov@gmail.com nxt_java_request_data_t *data;
222*977Smax.romanov@gmail.com
223*977Smax.romanov@gmail.com req = nxt_jlong2ptr(req_info_ptr);
224*977Smax.romanov@gmail.com data = req->data;
225*977Smax.romanov@gmail.com
226*977Smax.romanov@gmail.com if (data->buf != NULL && data->buf->free > data->buf->start) {
227*977Smax.romanov@gmail.com nxt_java_OutputStream_flush_buf(env, req);
228*977Smax.romanov@gmail.com }
229*977Smax.romanov@gmail.com }
230*977Smax.romanov@gmail.com
231*977Smax.romanov@gmail.com
232*977Smax.romanov@gmail.com static void JNICALL
nxt_java_OutputStream_close(JNIEnv * env,jclass cls,jlong req_info_ptr)233*977Smax.romanov@gmail.com nxt_java_OutputStream_close(JNIEnv *env, jclass cls, jlong req_info_ptr)
234*977Smax.romanov@gmail.com {
235*977Smax.romanov@gmail.com nxt_java_OutputStream_flush_buf(env, nxt_jlong2ptr(req_info_ptr));
236*977Smax.romanov@gmail.com }
237