2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 /***************************************************************************
19 * Description: ajpv1.2 worker, used to call local or remote jserv hosts *
20 * This worker is deprecated *
21 * Author: Gal Shachor <shachor@il.ibm.com> *
22 * Based on: jserv_ajpv12.c from Jserv *
23 * Version: $Revision: 747878 $ *
24 ***************************************************************************/
26 #include "jk_ajp12_worker.h"
28 #include "jk_connect.h"
30 #include "jk_sockbuf.h"
31 #if defined(AS400) && !defined(AS400_UTF8)
32 #include "util_ebcdic.h"
36 #define AJP_DEF_HOST ("localhost")
37 #define AJP_DEF_PORT (8007)
38 #define READ_BUF_SIZE (8*1024)
39 #define DEF_RETRY_ATTEMPTS (1)
43 struct sockaddr_in worker_inet_addr;
44 unsigned connect_retry_attempts;
49 typedef struct ajp12_worker ajp12_worker_t;
53 ajp12_worker_t *worker;
58 jk_endpoint_t endpoint;
60 typedef struct ajp12_endpoint ajp12_endpoint_t;
62 static int ajpv12_mark(ajp12_endpoint_t * p, unsigned char type);
64 #if defined(AS400) && !defined(AS400_UTF8)
65 static int ajpv12_sendasciistring(ajp12_endpoint_t * p, char *buffer);
68 #if defined(AS400) && !defined(AS400_UTF8)
69 static int ajpv12_sendstring(ajp12_endpoint_t * p, char *buffer);
71 static int ajpv12_sendstring(ajp12_endpoint_t * p, const char *buffer);
74 static int ajpv12_sendint(ajp12_endpoint_t * p, int d);
76 static int ajpv12_sendnbytes(ajp12_endpoint_t * p,
77 const void *buffer, int bufferlen);
79 static int ajpv12_flush(ajp12_endpoint_t * p);
81 static int ajpv12_handle_response(ajp12_endpoint_t * p,
82 jk_ws_service_t *s, jk_logger_t *l);
84 static int ajpv12_handle_request(ajp12_endpoint_t * p,
85 jk_ws_service_t *s, jk_logger_t *l);
88 * Return values of service() method for ajp12 worker:
89 * return value is_error reason
90 * JK_FALSE JK_HTTP_SERVER_ERROR Invalid parameters (null values)
91 * Error during connect to the backend
92 * ajpv12_handle_request() returns false:
93 * Any error during reading a request body from the client or
94 * sending the request to the backend
95 * JK_FALSE JK_HTTP_OK ajpv12_handle_response() returns false:
96 * Any error during reading parts of response from backend or
98 * JK_TRUE JK_HTTP_OK All other cases
100 static int JK_METHOD service(jk_endpoint_t *e,
102 jk_logger_t *l, int *is_error)
105 unsigned int attempt;
108 * AJP12 protocol is not recoverable.
113 if (!e || !e->endpoint_private || !s || !is_error) {
114 JK_LOG_NULL_PARAMS(l);
116 *is_error = JK_HTTP_SERVER_ERROR;
121 p = e->endpoint_private;
123 /* Set returned error to OK */
124 *is_error = JK_HTTP_OK;
126 for (attempt = 0; attempt < p->worker->connect_retry_attempts;
129 jk_open_socket(&p->worker->worker_inet_addr,
130 JK_FALSE, 0, 0, 0, l);
132 jk_log(l, JK_LOG_DEBUG, "In jk_endpoint_t::service, sd = %d",
134 if (IS_VALID_SOCKET(p->sd)) {
138 if (IS_VALID_SOCKET(p->sd)) {
140 jk_sb_open(&p->sb, p->sd);
141 if (ajpv12_handle_request(p, s, l)) {
142 jk_log(l, JK_LOG_DEBUG,
143 "In jk_endpoint_t::service, sent request");
144 rc = ajpv12_handle_response(p, s, l);
149 jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service, Error sd = %d",
151 *is_error = JK_HTTP_SERVER_ERROR;
157 static int JK_METHOD done(jk_endpoint_t **e, jk_logger_t *l)
159 jk_log(l, JK_LOG_DEBUG, "Into jk_endpoint_t::done");
160 if (e && *e && (*e)->endpoint_private) {
161 ajp12_endpoint_t *p = (*e)->endpoint_private;
162 if (IS_VALID_SOCKET(p->sd)) {
163 jk_shutdown_socket(p->sd, l);
170 jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::done, NULL parameters");
174 static int JK_METHOD validate(jk_worker_t *pThis,
176 jk_worker_env_t *we, jk_logger_t *l)
178 jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::validate");
180 if (pThis && pThis->worker_private) {
181 ajp12_worker_t *p = pThis->worker_private;
182 int port = jk_get_worker_port(props,
186 const char *host = jk_get_worker_host(props,
190 jk_log(l, JK_LOG_DEBUG,
191 "In jk_worker_t::validate for worker %s contact is %s:%d",
192 p->name, host, port);
195 if (jk_resolve(host, port, &p->worker_inet_addr, we->pool, l)) {
198 jk_log(l, JK_LOG_ERROR,
199 "In jk_worker_t::validate, resolve failed");
201 jk_log(l, JK_LOG_ERROR, "In jk_worker_t::validate, Error %s %d",
205 jk_log(l, JK_LOG_ERROR,
206 "In jk_worker_t::validate, NULL parameters");
212 static int JK_METHOD init(jk_worker_t *pThis,
214 jk_worker_env_t *we, jk_logger_t *log)
216 /* Nothing to do for now */
220 static int JK_METHOD get_endpoint(jk_worker_t *pThis,
221 jk_endpoint_t **pend, jk_logger_t *l)
223 jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::get_endpoint");
225 if (pThis && pThis->worker_private && pend) {
226 ajp12_endpoint_t *p =
227 (ajp12_endpoint_t *) malloc(sizeof(ajp12_endpoint_t));
229 p->sd = JK_INVALID_SOCKET;
230 p->worker = pThis->worker_private;
231 p->endpoint.endpoint_private = p;
232 p->endpoint.service = service;
233 p->endpoint.done = done;
234 *pend = &p->endpoint;
237 jk_log(l, JK_LOG_ERROR,
238 "In jk_worker_t::get_endpoint, malloc failed");
241 jk_log(l, JK_LOG_ERROR,
242 "In jk_worker_t::get_endpoint, NULL parameters");
248 static int JK_METHOD destroy(jk_worker_t **pThis, jk_logger_t *l)
250 jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::destroy");
251 if (pThis && *pThis && (*pThis)->worker_private) {
252 ajp12_worker_t *private_data = (*pThis)->worker_private;
253 free(private_data->name);
259 jk_log(l, JK_LOG_ERROR, "In jk_worker_t::destroy, NULL parameters");
263 int JK_METHOD ajp12_worker_factory(jk_worker_t **w,
264 const char *name, jk_logger_t *l)
266 jk_log(l, JK_LOG_DEBUG, "Into ajp12_worker_factory");
267 if (NULL != name && NULL != w) {
268 ajp12_worker_t *private_data =
269 (ajp12_worker_t *) malloc(sizeof(ajp12_worker_t));
272 private_data->name = strdup(name);
274 if (private_data->name) {
275 private_data->connect_retry_attempts = DEF_RETRY_ATTEMPTS;
276 private_data->worker.worker_private = private_data;
278 private_data->worker.validate = validate;
279 private_data->worker.init = init;
280 private_data->worker.get_endpoint = get_endpoint;
281 private_data->worker.destroy = destroy;
282 private_data->worker.maintain = NULL;
284 *w = &private_data->worker;
285 return JK_AJP12_WORKER_TYPE;
290 jk_log(l, JK_LOG_ERROR, "In ajp12_worker_factory, malloc failed");
293 jk_log(l, JK_LOG_ERROR, "In ajp12_worker_factory, NULL parameters");
299 static int ajpv12_sendnbytes(ajp12_endpoint_t * p,
300 const void *buffer, int bufferlen)
302 unsigned char bytes[2];
303 static const unsigned char null_b[2] =
304 { (unsigned char)0xff, (unsigned char)0xff };
307 bytes[0] = (unsigned char)((bufferlen >> 8) & 0xff);
308 bytes[1] = (unsigned char)(bufferlen & 0xff);
310 if (jk_sb_write(&p->sb, bytes, 2)) {
311 return jk_sb_write(&p->sb, buffer, bufferlen);
318 return jk_sb_write(&p->sb, null_b, 2);
322 #if defined(AS400) && !defined(AS400_UTF8)
323 static int ajpv12_sendasciistring(ajp12_endpoint_t * p, const char *buffer)
327 if (buffer && (bufferlen = strlen(buffer))) {
328 return ajpv12_sendnbytes(p, buffer, bufferlen);
331 return ajpv12_sendnbytes(p, NULL, 0);
336 static int ajpv12_sendstring(ajp12_endpoint_t * p, const char *buffer)
340 if (buffer && (bufferlen = (int)strlen(buffer))) {
341 #if (defined(AS400) && !defined(AS400_UTF8)) || defined(_OSD_POSIX)
343 if (bufferlen < 2048) {
344 memcpy(buf, buffer, bufferlen);
345 jk_xlate_to_ascii(buf, bufferlen);
346 return ajpv12_sendnbytes(p, buf, bufferlen);
351 return ajpv12_sendnbytes(p, buffer, bufferlen);
355 return ajpv12_sendnbytes(p, NULL, 0);
359 static int ajpv12_mark(ajp12_endpoint_t * p, unsigned char type)
361 if (jk_sb_write(&p->sb, &type, 1)) {
369 static int ajpv12_sendint(ajp12_endpoint_t * p, int d)
372 sprintf(buf, "%d", d);
373 return ajpv12_sendstring(p, buf);
376 static int ajpv12_flush(ajp12_endpoint_t * p)
378 return jk_sb_flush(&p->sb);
381 static int ajpv12_handle_request(ajp12_endpoint_t * p,
382 jk_ws_service_t *s, jk_logger_t *l)
386 jk_log(l, JK_LOG_DEBUG, "Into ajpv12_handle_request");
388 * Start the ajp 12 service sequence
390 jk_log(l, JK_LOG_DEBUG,
391 "ajpv12_handle_request, sending the ajp12 start sequence");
393 ret = (ajpv12_mark(p, 1) && ajpv12_sendstring(p, s->method) && ajpv12_sendstring(p, 0) && /* zone */
394 ajpv12_sendstring(p, 0) && /* servlet */
395 ajpv12_sendstring(p, s->server_name) && ajpv12_sendstring(p, 0) && /* doc root */
396 ajpv12_sendstring(p, 0) && /* path info */
397 ajpv12_sendstring(p, 0) && /* path translated */
398 #if defined(AS400) && !defined(AS400_UTF8)
399 ajpv12_sendasciistring(p, s->query_string) &&
401 ajpv12_sendstring(p, s->query_string) &&
403 ajpv12_sendstring(p, s->remote_addr) &&
404 ajpv12_sendstring(p, s->remote_host) &&
405 ajpv12_sendstring(p, s->remote_user) &&
406 ajpv12_sendstring(p, s->auth_type) &&
407 ajpv12_sendint(p, s->server_port) &&
408 #if defined(AS400) && !defined(AS400_UTF8)
409 ajpv12_sendasciistring(p, s->method) &&
411 ajpv12_sendstring(p, s->method) &&
413 ajpv12_sendstring(p, s->req_uri) && ajpv12_sendstring(p, 0) && /* */
414 ajpv12_sendstring(p, 0) && /* SCRIPT_NAME */
415 #if defined(AS400) && !defined(AS400_UTF8)
416 ajpv12_sendasciistring(p, s->server_name) &&
418 ajpv12_sendstring(p, s->server_name) &&
420 ajpv12_sendint(p, s->server_port) && ajpv12_sendstring(p, s->protocol) && ajpv12_sendstring(p, 0) && /* SERVER_SIGNATURE */
421 ajpv12_sendstring(p, s->server_software) && ajpv12_sendstring(p, s->route) && /* JSERV_ROUTE */
422 ajpv12_sendstring(p, "") && /* JSERV ajpv12 compatibility */
423 ajpv12_sendstring(p, "")); /* JSERV ajpv12 compatibility */
426 jk_log(l, JK_LOG_ERROR,
427 "In ajpv12_handle_request, failed to send the ajp12 start sequence");
431 if (s->num_attributes > 0) {
433 jk_log(l, JK_LOG_DEBUG,
434 "ajpv12_handle_request, sending the environment variables");
436 for (i = 0; i < s->num_attributes; i++) {
437 ret = (ajpv12_mark(p, 5) &&
438 ajpv12_sendstring(p, s->attributes_names[i]) &&
439 ajpv12_sendstring(p, s->attributes_values[i]));
441 jk_log(l, JK_LOG_ERROR,
442 "In ajpv12_handle_request, failed to send environment");
448 jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_request, sending the headers");
450 /* Send the request headers */
451 if (s->num_headers) {
453 for (i = 0; i < s->num_headers; ++i) {
454 ret = (ajpv12_mark(p, 3) &&
455 ajpv12_sendstring(p, s->headers_names[i]) &&
456 ajpv12_sendstring(p, s->headers_values[i]));
459 jk_log(l, JK_LOG_ERROR,
460 "In ajpv12_handle_request, failed to send headers");
466 jk_log(l, JK_LOG_DEBUG,
467 "ajpv12_handle_request, sending the terminating mark");
469 ret = (ajpv12_mark(p, 4) && ajpv12_flush(p));
471 jk_log(l, JK_LOG_ERROR,
472 "In ajpv12_handle_request, failed to send the terminating mark");
476 if (s->content_length) {
477 char buf[READ_BUF_SIZE];
478 jk_uint64_t so_far = 0;
480 jk_log(l, JK_LOG_DEBUG,
481 "ajpv12_handle_request, sending the request body");
483 while (so_far < s->content_length) {
484 unsigned this_time = 0;
486 if (s->content_length > so_far + READ_BUF_SIZE) {
487 to_read = READ_BUF_SIZE;
490 to_read = (unsigned int)(s->content_length - so_far);
493 if (!s->read(s, buf, to_read, &this_time)) {
494 jk_log(l, JK_LOG_ERROR,
495 "In ajpv12_handle_request, failed to read from the web server");
498 jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_request, read %d bytes",
502 if ((int)this_time != send(p->sd, buf, this_time, 0)) {
503 jk_log(l, JK_LOG_ERROR,
504 "In ajpv12_handle_request, failed to write to the container");
507 jk_log(l, JK_LOG_DEBUG,
508 "ajpv12_handle_request, sent %d bytes", this_time);
510 else if (this_time == 0) {
511 jk_log(l, JK_LOG_ERROR,
512 "In ajpv12_handle_request, Error: short read. content length is %" JK_UINT64_T_FMT ", read %" JK_UINT64_T_FMT,
513 s->content_length, so_far);
519 jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_request done");
523 static int ajpv12_handle_response(ajp12_endpoint_t * p,
524 jk_ws_service_t *s, jk_logger_t *l)
529 char **values = NULL;
530 int headers_capacity = 0;
534 jk_log(l, JK_LOG_DEBUG, "Into ajpv12_handle_response");
542 #ifdef _MT_CODE_PTHREAD
546 if (!jk_sb_gets(&p->sb, &line)) {
547 jk_log(l, JK_LOG_ERROR,
548 "ajpv12_handle_response, error reading header line");
551 #if (defined(AS400) && !defined(AS400_UTF8)) || defined(_OSD_POSIX)
552 jk_xlate_from_ascii(line, strlen(line));
555 jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_response, read %s", line);
556 if (0 == strlen(line)) {
557 jk_log(l, JK_LOG_DEBUG,
558 "ajpv12_handle_response, headers are done");
559 break; /* Empty line -> end of headers */
563 while (isspace((int)(*name)) && *name) {
564 name++; /* Skip leading white chars */
566 if (!*name) { /* Empty header name */
567 jk_log(l, JK_LOG_ERROR,
568 "ajpv12_handle_response, empty header name");
571 if (!(value = strchr(name, ':'))) {
572 jk_log(l, JK_LOG_ERROR,
573 "ajpv12_handle_response, no value supplied");
574 return JK_FALSE; /* No value !!! */
578 while (isspace((int)(*value)) && *value) {
579 value++; /* Skip leading white chars */
581 if (!*value) { /* Empty header value */
582 jk_log(l, JK_LOG_ERROR,
583 "ajpv12_handle_response, empty header value");
587 jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_response, read %s=%s", name,
589 if (0 == strcmp("Status", name)) {
590 #ifdef _MT_CODE_PTHREAD
591 char *numeric = strtok_r(value, " \t", &lasts);
593 char *numeric = strtok(value, " \t");
596 status = atoi(numeric);
597 if (status < 100 || status > 999) {
598 jk_log(l, JK_LOG_ERROR,
599 "ajpv12_handle_response, invalid status code");
602 #ifdef _MT_CODE_PTHREAD
603 reason = jk_pool_strdup(s->pool, strtok_r(NULL, " \t", &lasts));
605 reason = jk_pool_strdup(s->pool, strtok(NULL, " \t"));
609 if (headers_capacity == headers_len) {
610 jk_log(l, JK_LOG_DEBUG,
611 "ajpv12_handle_response, allocating header arrays");
613 (char **)jk_pool_realloc(s->pool,
615 (headers_capacity + 5), names,
619 (char **)jk_pool_realloc(s->pool,
621 (headers_capacity + 5), values,
624 if (!values || !names) {
625 jk_log(l, JK_LOG_ERROR,
626 "ajpv12_handle_response, malloc error");
629 headers_capacity = headers_capacity + 5;
631 names[headers_len] = jk_pool_strdup(s->pool, name);
632 values[headers_len] = jk_pool_strdup(s->pool, value);
637 jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_response, starting response");
638 if (!s->start_response(s,
641 (const char *const *)names,
642 (const char *const *)values, headers_len)) {
643 jk_log(l, JK_LOG_ERROR,
644 "ajpv12_handle_response, error starting response");
648 jk_log(l, JK_LOG_DEBUG,
649 "ajpv12_handle_response, reading response body");
653 write_to_ws = JK_TRUE;
655 unsigned to_read = READ_BUF_SIZE;
659 if (!jk_sb_read(&p->sb, &buf, to_read, &acc)) {
660 jk_log(l, JK_LOG_ERROR,
661 "ajpv12_handle_response, error reading from ");
666 jk_log(l, JK_LOG_DEBUG,
667 "ajpv12_handle_response, response body is done");
672 if (!s->write(s, buf, acc)) {
673 jk_log(l, JK_LOG_ERROR,
674 "ajpv12_handle_response, error writing back to server");
675 write_to_ws = JK_FALSE;
680 jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_response done");