]> granicus.if.org Git - apache/blob - modules/proxy/ajp_header.c
Remove logging inside ajp_send_data_msg. If send fails it is logged
[apache] / modules / proxy / ajp_header.c
1 /*
2  *  Copyright 1999-2004 The Apache Software Foundation
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  */
16
17 #include "ajp_header.h"
18 #include "ajp.h"
19
20 static const char *response_trans_headers[] = {
21     "Content-Type", 
22     "Content-Language", 
23     "Content-Length", 
24     "Date", 
25     "Last-Modified", 
26     "Location", 
27     "Set-Cookie", 
28     "Set-Cookie2", 
29     "Servlet-Engine", 
30     "Status", 
31     "WWW-Authenticate"
32 };
33
34 static const char *long_res_header_for_sc(int sc) 
35 {
36     const char *rc = NULL;
37     sc = sc & 0X00FF;
38     if(sc <= SC_RES_HEADERS_NUM && sc > 0) {
39         rc = response_trans_headers[sc - 1];
40     }
41
42     return rc;
43 }
44
45 #define UNKNOWN_METHOD (-1)
46
47 static int sc_for_req_header(const char *header_name)
48 {
49     char header[16];
50     apr_size_t len = strlen(header_name);
51     const char *p = header_name;
52     int i = 0;
53
54     /* ACCEPT-LANGUAGE is the longest headeer
55      * that is of interest.
56      */
57     if (len < 4 || len > 15)
58         return UNKNOWN_METHOD;
59     
60     while (*p)
61         header[i++] = apr_toupper(*p++);
62     header[i] = '\0';
63     p = &header[1];
64
65     switch (header[0]) {
66         case 'A':
67             if (memcmp(p, "CCEPT", 5) == 0) {
68                 if (!header[6])
69                     return SC_ACCEPT;
70                 else if (header[6] == '-') {
71                     p += 6;
72                     if (memcmp(p, "CHARSET", 7) == 0)
73                         return SC_ACCEPT_CHARSET;
74                     else if (memcmp(p,  "ENCODING", 8) == 0)
75                         return SC_ACCEPT_ENCODING;
76                     else if (memcmp(p, "LANGUAGE", 8) == 0)
77                         return SC_ACCEPT_LANGUAGE;
78                     else
79                         return UNKNOWN_METHOD;
80                 }
81                 else
82                     return UNKNOWN_METHOD;
83             }
84             else if (memcmp(p, "UTHORIZATION", 12) == 0)
85                 return SC_AUTHORIZATION;
86             else
87                 return UNKNOWN_METHOD;
88         break;
89         case 'C':
90             if (memcmp(p, "OOKIE", 5) == 0)
91                 return SC_COOKIE;
92             else if(memcmp(p, "ONNECTION", 9) == 0)
93                 return SC_CONNECTION;
94             else if(memcmp(p, "ONTENT-TYPE", 11) == 0)
95                 return SC_CONTENT_TYPE;
96             else if(memcmp(p, "ONTENT-LENGTH", 13) == 0)
97                 return SC_CONTENT_LENGTH;
98             else if(memcmp(p, "OOKIE2", 6) == 0)
99                 return SC_COOKIE2;
100             else
101                 return UNKNOWN_METHOD;
102         break;
103         case 'H':
104             if(memcmp(p, "OST", 3) == 0)
105                 return SC_HOST;
106             else
107                 return UNKNOWN_METHOD;
108         break;
109         case 'P':
110             if(memcmp(p, "RAGMA", 5) == 0)
111                 return SC_PRAGMA;
112             else
113                 return UNKNOWN_METHOD;
114         break;
115         case 'R':
116             if(memcmp(p, "EFERER", 6) == 0)
117                 return SC_REFERER;
118             else
119                 return UNKNOWN_METHOD;
120         break;
121         case 'U':
122             if(memcmp(p, "SER-AGENT", 9) == 0)
123                 return SC_USER_AGENT;
124             else
125                 return UNKNOWN_METHOD;
126         break;
127         default:
128             return UNKNOWN_METHOD;
129     }
130
131     /* NOTREACHED */
132 }
133
134 /* Apache method number to SC methods transform table */
135 static const unsigned char sc_for_req_method_table[] = {
136     SC_M_GET,
137     SC_M_PUT,
138     SC_M_POST,
139     SC_M_DELETE,
140     0,                      /* M_DELETE */
141     SC_M_OPTIONS,
142     SC_M_TRACE,
143     0,                      /* M_PATCH  */
144     SC_M_PROPFIND,
145     SC_M_PROPPATCH,
146     SC_M_MKCOL,
147     SC_M_COPY,
148     SC_M_MOVE,
149     SC_M_LOCK,
150     SC_M_UNLOCK,
151     SC_M_VERSION_CONTROL,
152     SC_M_CHECKOUT,
153     SC_M_UNCHECKOUT,
154     SC_M_CHECKIN,
155     SC_M_UPDATE,
156     SC_M_LABEL,
157     SC_M_REPORT,
158     SC_M_MKWORKSPACE,
159     SC_M_MKACTIVITY,
160     SC_M_BASELINE_CONTROL,
161     SC_M_MERGE,           
162     0                       /* M_INVALID */
163 };
164
165 static int sc_for_req_method_by_id(int method_id)
166 {
167     if (method_id < 0 || method_id > M_INVALID)
168         return UNKNOWN_METHOD;
169     else
170         return sc_for_req_method_table[method_id] ?
171                sc_for_req_method_table[method_id] : UNKNOWN_METHOD;
172 }
173
174 /*
175  * Message structure
176  *
177  *
178 AJPV13_REQUEST/AJPV14_REQUEST=
179     request_prefix (1) (byte)
180     method         (byte)
181     protocol       (string)
182     req_uri        (string)
183     remote_addr    (string)
184     remote_host    (string)
185     server_name    (string)
186     server_port    (short)
187     is_ssl         (boolean)
188     num_headers    (short)
189     num_headers*(req_header_name header_value)
190
191     ?context       (byte)(string)
192     ?servlet_path  (byte)(string)
193     ?remote_user   (byte)(string)
194     ?auth_type     (byte)(string)
195     ?query_string  (byte)(string)
196     ?jvm_route     (byte)(string)
197     ?ssl_cert      (byte)(string)
198     ?ssl_cipher    (byte)(string)
199     ?ssl_session   (byte)(string)
200     ?ssl_key_size  (byte)(int)      via JkOptions +ForwardKeySize
201     request_terminator (byte)
202     ?body          content_length*(var binary)
203
204  */
205
206 static apr_status_t ajp_marshal_into_msgb(ajp_msg_t    *msg,
207                                  request_rec *r)
208 {
209     int method;
210     apr_uint32_t i, num_headers = 0;
211     apr_byte_t is_ssl;
212     char *remote_host;
213     char *uri;
214     const char *session_route, *envvar;
215     const apr_array_header_t *arr = apr_table_elts(r->subprocess_env);
216     const apr_table_entry_t *elts = (const apr_table_entry_t *)arr->elts;
217
218     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
219                          "Into ajp_marshal_into_msgb");
220
221     if ((method = sc_for_req_method_by_id(r->method_number)) == UNKNOWN_METHOD) { 
222         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
223                "Error ajp_marshal_into_msgb - No such method %s",
224                r->method);
225         return APR_EGENERAL;
226     }
227
228     /* XXXX need something */
229     is_ssl = (apr_byte_t) 0; /* s->is_ssl */
230
231     if (r->headers_in && apr_table_elts(r->headers_in)) {
232         const apr_array_header_t *t = apr_table_elts(r->headers_in);
233         num_headers = t->nelts;
234     }
235
236     remote_host = (char *)ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_HOST, NULL);
237
238     uri = apr_pstrdup(r->pool, r->uri);
239     if (uri != NULL) {
240         char *query_str = strchr(uri, '?');
241         if (query_str != NULL) {
242             *query_str = 0;
243         }
244     }
245     
246
247     ajp_msg_reset(msg);
248
249     if (ajp_msg_append_uint8(msg, CMD_AJP13_FORWARD_REQUEST)     ||
250         ajp_msg_append_uint8(msg, method)                        ||
251         ajp_msg_append_string(msg, r->protocol)                  ||
252         ajp_msg_append_string(msg, uri)                          ||
253         ajp_msg_append_string(msg, r->connection->remote_ip)     ||
254         ajp_msg_append_string(msg, remote_host)                  ||
255         ajp_msg_append_string(msg, ap_get_server_name(r))        ||
256         ajp_msg_append_uint16(msg, (apr_uint16_t)r->connection->local_addr->port) ||
257         ajp_msg_append_uint8(msg, is_ssl)                        ||
258         ajp_msg_append_uint16(msg, (apr_uint16_t) num_headers)) {
259
260         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
261                "Error ajp_marshal_into_msgb - "
262                "Error appending the message begining");
263         return APR_EGENERAL;
264     }
265
266     for (i = 0 ; i < num_headers ; i++) {
267         int sc;
268         const apr_array_header_t *t = apr_table_elts(r->headers_in);
269         const apr_table_entry_t *elts = (apr_table_entry_t *)t->elts;
270
271         if ((sc = sc_for_req_header(elts[i].key)) != UNKNOWN_METHOD) {
272             if (ajp_msg_append_uint16(msg, (apr_uint16_t)sc)) {
273                 ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
274                        "Error ajp_marshal_into_msgb - "
275                        "Error appending the header name");
276                 return APR_EGENERAL;
277             }
278         }
279         else {
280             if (ajp_msg_append_string(msg, elts[i].key)) {
281                 ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
282                        "Error ajp_marshal_into_msgb - "
283                        "Error appending the header name");
284                 return APR_EGENERAL;
285             }
286         }
287         
288         if (ajp_msg_append_string(msg, elts[i].val)) {
289             ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
290                    "Error ajp_marshal_into_msgb - "
291                    "Error appending the header value");
292             return APR_EGENERAL;
293         }
294         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
295                    "ajp_marshal_into_msgb: Header[%d] [%s] = [%s]",
296                    i, elts[i].key, elts[i].val);
297     }
298
299 /* XXXX need to figure out how to do this
300     if (s->secret) {
301         if (ajp_msg_append_uint8(msg, SC_A_SECRET) ||
302             ajp_msg_append_string(msg, s->secret)) {
303             ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
304                    "Error ajp_marshal_into_msgb - "
305                    "Error appending secret");
306             return APR_EGENERAL;
307         }
308     }
309  */
310         
311     if (r->user) {
312         if (ajp_msg_append_uint8(msg, SC_A_REMOTE_USER) ||
313             ajp_msg_append_string(msg, r->user)) {
314             ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
315                    "Error ajp_marshal_into_msgb - "
316                    "Error appending the remote user");
317             return APR_EGENERAL;
318         }
319     }
320     if (r->ap_auth_type) {
321         if (ajp_msg_append_uint8(msg, SC_A_AUTH_TYPE) ||
322             ajp_msg_append_string(msg, r->ap_auth_type)) {
323             ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
324                    "Error ajp_marshal_into_msgb - "
325                    "Error appending the auth type");
326             return APR_EGENERAL;
327         }
328     }
329     /* XXXX  ebcdic (args converted?) */
330     if (r->args) {
331         if (ajp_msg_append_uint8(msg, SC_A_QUERY_STRING) ||
332             ajp_msg_append_string(msg, r->args)) {
333             ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
334                    "Error ajp_marshal_into_msgb - "
335                    "Error appending the query string");
336             return APR_EGENERAL;
337         }
338     }
339     if ((session_route = apr_table_get(r->notes, "session-route"))) {
340         if (ajp_msg_append_uint8(msg, SC_A_JVM_ROUTE) ||
341             ajp_msg_append_string(msg, session_route)) {
342             ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
343                    "Error ajp_marshal_into_msgb - "
344                    "Error appending the jvm route");
345             return APR_EGENERAL;
346         }
347     }
348 /* XXX: Is the subprocess_env a right place?
349  * <Location /examples>
350  *   ProxyPass ajp://remote:8009/servlets-examples 
351  *   SetEnv SSL_SESSION_ID CUSTOM_SSL_SESSION_ID
352  * </Location>
353  */
354     if ((envvar = apr_table_get(r->subprocess_env,
355                                 AJP13_SSL_CLIENT_CERT_INDICATOR))) {
356         if (ajp_msg_append_uint8(msg, SC_A_SSL_CERT) ||
357             ajp_msg_append_string(msg, envvar)) {
358             ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
359                    "Error ajp_marshal_into_msgb - "
360                    "Error appending the SSL certificates");
361             return APR_EGENERAL;
362         }
363     }
364
365     if ((envvar = apr_table_get(r->subprocess_env,
366                                 AJP13_SSL_CIPHER_INDICATOR))) {
367         if (ajp_msg_append_uint8(msg, SC_A_SSL_CIPHER) ||
368             ajp_msg_append_string(msg, envvar)) {
369             ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
370                    "Error ajp_marshal_into_msgb - "
371                    "Error appending the SSL ciphers");
372             return APR_EGENERAL;
373         }
374     }
375
376     if ((envvar = apr_table_get(r->subprocess_env,
377                                 AJP13_SSL_SESSION_INDICATOR))) {
378         if (ajp_msg_append_uint8(msg, SC_A_SSL_SESSION) ||
379             ajp_msg_append_string(msg, envvar)) {
380             ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
381                    "Error ajp_marshal_into_msgb - "
382                    "Error appending the SSL session");
383             return APR_EGENERAL;
384         }
385     }
386
387     /*
388      * ssl_key_size is required by Servlet 2.3 API
389      * added support only in ajp14 mode
390      * JFC removed: ae->proto == AJP14_PROTO
391      */
392  /* XXXX ignored for the moment
393     if (s->ssl_key_size != -1) {
394         if (ajp_msg_append_uint8(msg, SC_A_SSL_KEY_SIZE) ||
395             ajp_msg_append_uint16(msg, (unsigned short) s->ssl_key_size)) {
396             ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
397                    "Error ajp_marshal_into_msgb - "
398                    "Error appending the SSL key size");
399             return APR_EGENERAL;
400         }
401     }
402  */
403     /* Use the environment vars prefixed with AJP_
404      * and pass it to the header striping that prefix.
405      */
406     for (i = 0; i < (apr_uint32_t)arr->nelts; i++) {
407         if (!strncmp(elts[i].key, "AJP_", 4)) {
408             if (ajp_msg_append_uint8(msg, SC_A_REQ_ATTRIBUTE) ||
409                 ajp_msg_append_string(msg, elts[i].key + 4)   ||
410                 ajp_msg_append_string(msg, elts[i].val)) {
411                 ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
412                         "Error ajp_marshal_into_msgb - "
413                         "Error appending attribute %s=%s",
414                         elts[i].key, elts[i].val);
415                 return APR_EGENERAL;
416             }
417         }
418     }
419
420     if (ajp_msg_append_uint8(msg, SC_A_ARE_DONE)) {
421         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
422                "Error ajp_marshal_into_msgb - "
423                "Error appending the message end");
424         return APR_EGENERAL;
425     }
426
427     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
428            "ajp_marshal_into_msgb - Done");
429     return APR_SUCCESS;
430 }
431
432 /*
433 AJPV13_RESPONSE/AJPV14_RESPONSE:=
434     response_prefix (2)
435     status          (short)
436     status_msg      (short)
437     num_headers     (short)
438     num_headers*(res_header_name header_value)
439     *body_chunk
440     terminator      boolean <! -- recycle connection or not  -->
441
442 req_header_name := 
443     sc_req_header_name | (string)
444
445 res_header_name := 
446     sc_res_header_name | (string)
447
448 header_value :=
449     (string)
450
451 body_chunk :=
452     length  (short)
453     body    length*(var binary)
454
455  */
456
457
458 static apr_status_t ajp_unmarshal_response(ajp_msg_t   *msg,
459                                   request_rec  *r)
460 {
461     apr_uint16_t status;
462     apr_status_t rc;
463     char *ptr;
464     apr_uint16_t  num_headers;
465     int i;
466
467     rc = ajp_msg_get_uint16(msg, &status);
468
469     if (rc != APR_SUCCESS) {
470          ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
471                "Error ajp_unmarshal_response - Null status");
472         return APR_EGENERAL;
473     }
474     r->status = status;
475
476     rc = ajp_msg_get_string(msg, &ptr);
477     if (rc == APR_SUCCESS) {
478         r->status_line =  apr_psprintf(r->pool, "%d %s", status, ptr);
479 #if defined(AS400) || defined(_OSD_POSIX)
480         ap_xlate_proto_from_ascii(r->status_line, strlen(r->status_line));
481 #endif
482     } else {
483         r->status_line = NULL;
484     }
485
486     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
487            "ajp_unmarshal_response: status = %d", status);
488
489     rc = ajp_msg_get_uint16(msg, &num_headers);
490     if (rc == APR_SUCCESS) {
491         r->headers_out = apr_table_make(r->pool, num_headers);
492     } else {
493         r->headers_out = NULL;
494         num_headers = 0;
495     }
496
497     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
498            "ajp_unmarshal_response: Number of headers is = %d",
499            num_headers);
500
501     for(i = 0 ; i < (int) num_headers ; i++) {
502         apr_uint16_t name;
503         char *stringname;
504         char *value;
505         rc  = ajp_msg_peek_uint16(msg, &name);
506         if (rc != APR_SUCCESS) {
507             return APR_EGENERAL;
508         }
509                 
510         if ((name & 0XFF00) == 0XA000) {
511             ajp_msg_peek_uint16(msg, &name);
512             stringname = (char *)long_res_header_for_sc(name);
513             if (stringname == NULL) {
514                 ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
515                        "Error ajp_unmarshal_response - "
516                        "No such sc (%08x)",
517                        name);
518                 return APR_EGENERAL;
519             }
520         } else {
521             name = 0;
522             rc = ajp_msg_get_string(msg, &stringname);
523             if (rc != APR_SUCCESS) {
524                 ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
525                        "Error ajp_unmarshal_response - "
526                        "Null header name");
527                 return APR_EGENERAL;
528             }
529 #if defined(AS400) || defined(_OSD_POSIX)
530             ap_xlate_proto_from_ascii(stringname, strlen(stringname));
531 #endif
532         }
533
534         rc = ajp_msg_get_string(msg, &value);
535         if (rc != APR_SUCCESS) {
536             ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
537                    "Error ajp_unmarshal_response - "
538                    "Null header value");
539             return APR_EGENERAL;
540         }
541
542 #if defined(AS400) || defined(_OSD_POSIX)
543         ap_xlate_proto_from_ascii(value, strlen(value));
544 #endif
545         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
546                "ajp_unmarshal_response: Header[%d] [%s] = [%s]", 
547                        i, stringname, value);
548         apr_table_add(r->headers_out, stringname, value);
549
550         /* Content-type needs an additional handling */
551         if (memcmp(stringname, "Content-Type", 12) == 0) {
552              /* add corresponding filter */
553             ap_set_content_type(r, apr_pstrdup(r->pool, value));
554             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
555                "ajp_unmarshal_response: ap_set_content_type done");
556         }
557     }
558
559     return APR_SUCCESS;
560 }
561
562 /*
563  * Build the ajp header message and send it
564  */
565 apr_status_t ajp_send_header(apr_socket_t *sock,
566                                   request_rec  *r)
567 {
568     ajp_msg_t *msg;
569     apr_status_t rc;
570
571     rc = ajp_msg_create(r->pool, &msg);
572     if (rc != APR_SUCCESS) {
573         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
574                "ajp_send_header: ajp_msg_create failed");
575         return rc;
576     }
577
578     rc = ajp_marshal_into_msgb(msg, r);    
579     if (rc != APR_SUCCESS) {
580         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
581                "ajp_send_header: ajp_marshal_into_msgb failed");
582         return rc;
583     }
584
585     rc = ajp_ilink_send(sock, msg);
586     if (rc != APR_SUCCESS) {
587         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
588                "ajp_send_header: ajp_ilink_send failed");
589         return rc;
590     }
591
592     return APR_SUCCESS;
593 }
594
595 /*
596  * Read the ajp message and return the type of the message.
597  */
598 apr_status_t ajp_read_header(apr_socket_t *sock,
599                              request_rec  *r,
600                              ajp_msg_t **msg)
601 {
602     apr_byte_t result;
603     apr_status_t rc;
604     
605     rc = ajp_msg_create(r->pool, msg);
606     if (rc != APR_SUCCESS) {
607         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
608                "ajp_read_header: ajp_msg_create failed");
609         return rc;
610     }
611     ajp_msg_reset(*msg);
612     rc = ajp_ilink_receive(sock, *msg);
613     if (rc != APR_SUCCESS) {
614         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
615                "ajp_read_header: ajp_ilink_receive failed");
616         return rc;
617     }
618     rc = ajp_msg_peek_uint8(*msg, &result);
619     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
620                "ajp_read_header: ajp_ilink_received %02x", result);
621     return APR_SUCCESS;
622 }
623
624 /* parse the msg to read the type */
625 int ajp_parse_type(request_rec  *r, ajp_msg_t *msg)
626 {
627     apr_byte_t result;
628     ajp_msg_peek_uint8(msg, &result);
629     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
630                "ajp_parse_type: got %02x", result);
631     return (int) result;
632 }
633
634 /* parse the header */
635 apr_status_t ajp_parse_header(request_rec  *r, ajp_msg_t *msg)
636 {
637     apr_byte_t result;
638     apr_status_t rc;
639
640     rc = ajp_msg_get_uint8(msg, &result);
641     if (rc != APR_SUCCESS) {
642         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
643                "ajp_parse_headers: ajp_msg_get_byte failed");
644         return rc;
645     }
646     if (result != CMD_AJP13_SEND_HEADERS) {
647         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
648                "ajp_parse_headers: wrong type %02x expecting 0x04", result);
649         return APR_EGENERAL;
650     }
651     return ajp_unmarshal_response(msg, r);
652 }
653
654 /* parse the body and return data address and length */
655 apr_status_t  ajp_parse_data(request_rec  *r, ajp_msg_t *msg,
656                              apr_uint16_t *len, char **ptr)
657 {
658     apr_byte_t result;
659     apr_status_t rc;
660
661     rc = ajp_msg_get_uint8(msg, &result);
662     if (rc != APR_SUCCESS) {
663         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
664                "ajp_parse_data: ajp_msg_get_byte failed");
665         return rc;
666     }
667     if (result != CMD_AJP13_SEND_BODY_CHUNK) {
668         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
669                "ajp_parse_data: wrong type %02x expecting 0x03", result);
670         return APR_EGENERAL;
671     }
672     rc = ajp_msg_get_uint16(msg, len);
673     if (rc != APR_SUCCESS) {
674         return APR_EGENERAL;
675     }
676     *ptr = (char *)&(msg->buf[msg->pos]);
677     return APR_SUCCESS;
678 }
679
680 /*
681  * Allocate a msg to send data
682  */
683 apr_status_t  ajp_alloc_data_msg(request_rec *r, char **ptr, apr_size_t *len,
684                                  ajp_msg_t **msg)
685 {
686     apr_status_t rc;
687
688     rc = ajp_msg_create(r->pool, msg);
689     if (rc != APR_SUCCESS) {
690         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
691                "ajp_alloc_data_msg: ajp_msg_create failed");
692         return rc;
693     }
694     ajp_msg_reset(*msg);
695     *ptr = (char *)&((*msg)->buf[6]);
696     *len = AJP_MSG_BUFFER_SZ-6;
697
698     return APR_SUCCESS;
699 }
700
701 /*
702  * Send the data message
703  */
704 apr_status_t  ajp_send_data_msg(apr_socket_t *sock, request_rec  *r,
705                                 ajp_msg_t *msg, apr_size_t len)
706 {
707
708     msg->buf[4] = (apr_byte_t)((len >> 8) & 0xFF);
709     msg->buf[5] = (apr_byte_t)(len & 0xFF);
710
711     msg->len += len + 2; /* + 1 XXXX where is '\0' */
712
713     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
714                "ajp_send_data_msg: sending %" APR_SIZE_T_FMT, len);
715
716     return ajp_ilink_send(sock, msg);
717
718 }