bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / tomcat-connectors-1.2.32-src / native / common / jk_ajp14.c
1 /*
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
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 /***************************************************************************
19  * Description: Next generation bi-directional protocol handler.           *
20  * Author:      Henri Gomez <hgomez@apache.org>                            *
21  * Version:     $Revision: 466585 $                                          *
22  ***************************************************************************/
23
24
25 #include "jk_global.h"
26 #include "jk_util.h"
27 #include "jk_map.h"
28 #include "jk_ajp_common.h"
29 #include "jk_ajp14.h"
30 #include "jk_md5.h"
31
32 /*
33  * Compute the MD5 with ENTROPY / SECRET KEY
34  */
35
36 void ajp14_compute_md5(jk_login_service_t *s, jk_logger_t *l)
37 {
38     JK_TRACE_ENTER(l);
39     jk_md5((const unsigned char *)s->entropy,
40            (const unsigned char *)s->secret_key, s->computed_key);
41
42     if (JK_IS_DEBUG_LEVEL(l))
43         jk_log(l, JK_LOG_DEBUG, "(%s/%s) -> (%s)",
44                s->entropy, s->secret_key, s->computed_key);
45     JK_TRACE_EXIT(l);
46 }
47
48
49 /*
50  * Build the Login Init Command
51  *
52  * +-------------------------+---------------------------+---------------------------+
53  * | LOGIN INIT CMD (1 byte) | NEGOCIATION DATA (32bits) | WEB SERVER INFO (CString) |
54  * +-------------------------+---------------------------+---------------------------+
55  *
56  */
57
58 int ajp14_marshal_login_init_into_msgb(jk_msg_buf_t *msg,
59                                        jk_login_service_t *s, jk_logger_t *l)
60 {
61     JK_TRACE_ENTER(l);
62     /* To be on the safe side */
63     jk_b_reset(msg);
64
65     /*
66      * LOGIN
67      */
68     if (jk_b_append_byte(msg, AJP14_LOGINIT_CMD)) {
69         JK_TRACE_EXIT(l);
70         return JK_FALSE;
71     }
72     /*
73      * NEGOCIATION FLAGS
74      */
75     if (jk_b_append_long(msg, s->negociation)) {
76         JK_TRACE_EXIT(l);
77         return JK_FALSE;
78     }
79     /*
80      * WEB-SERVER NAME
81      */
82     if (jk_b_append_string(msg, s->web_server_name)) {
83         jk_log(l, JK_LOG_ERROR,
84                "failed appending the web_server_name string");
85         JK_TRACE_EXIT(l);
86         return JK_FALSE;
87     }
88
89     JK_TRACE_EXIT(l);
90     return JK_TRUE;
91 }
92
93
94 /*
95  * Decode the Login Seed Command
96  *
97  * +-------------------------+---------------------------+
98  * | LOGIN SEED CMD (1 byte) | MD5 of entropy (32 chars) |
99  * +-------------------------+---------------------------+
100  *
101  */
102
103 int ajp14_unmarshal_login_seed(jk_msg_buf_t *msg,
104                                jk_login_service_t *s, jk_logger_t *l)
105 {
106     JK_TRACE_ENTER(l);
107
108     if (jk_b_get_bytes
109         (msg, (unsigned char *)s->entropy, AJP14_ENTROPY_SEED_LEN) < 0) {
110         jk_log(l, JK_LOG_ERROR,
111                "can't get seed");
112         JK_TRACE_EXIT(l);
113         return JK_FALSE;
114     }
115
116     s->entropy[AJP14_ENTROPY_SEED_LEN] = 0;     /* Just to have a CString */
117     JK_TRACE_EXIT(l);
118     return JK_TRUE;
119 }
120
121 /*
122  * Build the Login Computed Command
123  *
124  * +-------------------------+---------------------------------------+
125  * | LOGIN COMP CMD (1 byte) | MD5 of RANDOM + SECRET KEY (32 chars) |
126  * +-------------------------+---------------------------------------+
127  *
128  */
129
130 int ajp14_marshal_login_comp_into_msgb(jk_msg_buf_t *msg,
131                                        jk_login_service_t *s, jk_logger_t *l)
132 {
133     JK_TRACE_ENTER(l);
134
135     /* To be on the safe side */
136     jk_b_reset(msg);
137
138     /*
139      * LOGIN
140      */
141     if (jk_b_append_byte(msg, AJP14_LOGCOMP_CMD)) {
142         JK_TRACE_EXIT(l);
143         return JK_FALSE;
144     }
145     /*
146      * COMPUTED-SEED
147      */
148     if (jk_b_append_bytes
149         (msg, (const unsigned char *)s->computed_key,
150          AJP14_COMPUTED_KEY_LEN)) {
151         jk_log(l, JK_LOG_ERROR,
152                "failed appending the COMPUTED MD5 bytes");
153         JK_TRACE_EXIT(l);
154         return JK_FALSE;
155     }
156
157     JK_TRACE_EXIT(l);
158     return JK_TRUE;
159 }
160
161
162 /*
163  * Decode the LogOk Command
164  *
165  * +--------------------+------------------------+-------------------------------+
166  * | LOGOK CMD (1 byte) | NEGOCIED DATA (32bits) | SERVLET ENGINE INFO (CString) |
167  * +--------------------+------------------------+-------------------------------+
168  *
169  */
170
171 int ajp14_unmarshal_log_ok(jk_msg_buf_t *msg,
172                            jk_login_service_t *s, jk_logger_t *l)
173 {
174     unsigned long nego;
175     char *sname;
176
177     JK_TRACE_ENTER(l);
178
179     nego = jk_b_get_long(msg);
180
181     if (nego == 0xFFFFFFFF) {
182         jk_log(l, JK_LOG_ERROR,
183                "can't get negociated data");
184         JK_TRACE_EXIT(l);
185         return JK_FALSE;
186     }
187
188     sname = (char *)jk_b_get_string(msg);
189
190     if (!sname) {
191         jk_log(l, JK_LOG_ERROR,
192                "can't get servlet engine name");
193         JK_TRACE_EXIT(l);
194         return JK_FALSE;
195     }
196
197     if (s->servlet_engine_name) /* take care of removing previously allocated data */
198         free(s->servlet_engine_name);
199
200     s->servlet_engine_name = strdup(sname);
201
202     if (!s->servlet_engine_name) {
203         jk_log(l, JK_LOG_ERROR,
204                "can't malloc servlet engine name");
205         JK_TRACE_EXIT(l);
206         return JK_FALSE;
207     }
208
209     JK_TRACE_EXIT(l);
210     return JK_TRUE;
211 }
212
213
214 /*
215  * Decode the Log Nok Command 
216  *
217  * +---------------------+-----------------------+
218  * | LOGNOK CMD (1 byte) | FAILURE CODE (32bits) |
219  * +---------------------+-----------------------+
220  *
221  */
222
223 int ajp14_unmarshal_log_nok(jk_msg_buf_t *msg, jk_logger_t *l)
224 {
225     unsigned long status;
226
227     JK_TRACE_ENTER(l);
228
229     status = jk_b_get_long(msg);
230
231     if (status == 0xFFFFFFFF) {
232         jk_log(l, JK_LOG_ERROR,
233                "can't get failure code");
234         JK_TRACE_EXIT(l);
235         return JK_FALSE;
236     }
237
238     jk_log(l, JK_LOG_INFO, "Can't Log with servlet engine - code %08lx",
239            status);
240     JK_TRACE_EXIT(l);
241     return JK_TRUE;
242 }
243
244
245 /* 
246  * Build the Shutdown Cmd
247  *
248  * +-----------------------+---------------------------------------+
249  * | SHUTDOWN CMD (1 byte) | MD5 of RANDOM + SECRET KEY (32 chars) |
250  * +-----------------------+---------------------------------------+
251  *
252  */
253
254 int ajp14_marshal_shutdown_into_msgb(jk_msg_buf_t *msg,
255                                      jk_login_service_t *s, jk_logger_t *l)
256 {
257
258     JK_TRACE_ENTER(l);
259
260     /* To be on the safe side */
261     jk_b_reset(msg);
262
263     /*
264      * SHUTDOWN CMD
265      */
266     if (jk_b_append_byte(msg, AJP14_SHUTDOWN_CMD)) {
267         JK_TRACE_EXIT(l);
268         return JK_FALSE;
269     }
270     /*
271      * COMPUTED-SEED
272      */
273     if (jk_b_append_bytes
274         (msg, (const unsigned char *)s->computed_key,
275          AJP14_COMPUTED_KEY_LEN)) {
276         jk_log(l, JK_LOG_ERROR,
277                "failed appending the COMPUTED MD5 bytes");
278         JK_TRACE_EXIT(l);
279         return JK_FALSE;
280     }
281
282     JK_TRACE_EXIT(l);
283     return JK_TRUE;
284 }
285
286 /*
287  * Decode the Shutdown Nok Command
288  *
289  * +----------------------+-----------------------+
290  * | SHUTNOK CMD (1 byte) | FAILURE CODE (32bits) |
291  * +----------------------+-----------------------+
292  *
293  */
294 int ajp14_unmarshal_shutdown_nok(jk_msg_buf_t *msg, jk_logger_t *l)
295 {
296     unsigned long status;
297
298     JK_TRACE_ENTER(l);
299     status = jk_b_get_long(msg);
300
301     if (status == 0xFFFFFFFF) {
302         jk_log(l, JK_LOG_ERROR,
303                "can't get failure code");
304         JK_TRACE_EXIT(l);
305         return JK_FALSE;
306     }
307
308     jk_log(l, JK_LOG_INFO, "Can't shutdown servlet engine - code %08lx",
309            status);
310     JK_TRACE_EXIT(l);
311     return JK_TRUE;
312 }
313
314 /*
315  * Build the Unknown Packet
316  *
317  * +-----------------------------+---------------------------------+------------------------------+
318  * | UNKNOWN PACKET CMD (1 byte) | UNHANDLED MESSAGE SIZE (16bits) | UNHANDLED MESSAGE (bytes...) |
319  * +-----------------------------+---------------------------------+------------------------------+
320  *
321  */
322
323 int ajp14_marshal_unknown_packet_into_msgb(jk_msg_buf_t *msg,
324                                            jk_msg_buf_t *unk, jk_logger_t *l)
325 {
326     JK_TRACE_ENTER(l);
327
328     /* To be on the safe side */
329     jk_b_reset(msg);
330
331     /*
332      * UNKNOWN PACKET CMD
333      */
334     if (jk_b_append_byte(msg, AJP14_UNKNOW_PACKET_CMD)) {
335         JK_TRACE_EXIT(l);
336         return JK_FALSE;
337     }
338     /*
339      * UNHANDLED MESSAGE SIZE
340      */
341     if (jk_b_append_int(msg, (unsigned short)unk->len)) {
342         JK_TRACE_EXIT(l);
343         return JK_FALSE;
344     }
345     /*
346      * UNHANDLED MESSAGE (Question : Did we have to send all the message or only part of)
347      *                                       (           ie: only 1k max                                                                )
348      */
349     if (jk_b_append_bytes(msg, unk->buf, unk->len)) {
350         jk_log(l, JK_LOG_ERROR,
351                "failed appending the UNHANDLED MESSAGE");
352         JK_TRACE_EXIT(l);
353         return JK_FALSE;
354     }
355
356     JK_TRACE_EXIT(l);
357     return JK_TRUE;
358 }
359
360 /*
361  * Build the Context Query Cmd (autoconf)
362  *
363  * +--------------------------+---------------------------------+
364  * | CONTEXT QRY CMD (1 byte) | VIRTUAL HOST NAME (CString (*)) |
365  * +--------------------------+---------------------------------+
366  *
367  */
368
369 int ajp14_marshal_context_query_into_msgb(jk_msg_buf_t *msg,
370                                           char *virtual, jk_logger_t *l)
371 {
372     JK_TRACE_ENTER(l);
373
374     /* To be on the safe side */
375     jk_b_reset(msg);
376
377     /*
378      * CONTEXT QUERY CMD
379      */
380     if (jk_b_append_byte(msg, AJP14_CONTEXT_QRY_CMD)) {
381         JK_TRACE_EXIT(l);
382         return JK_FALSE;
383     }
384     /*
385      * VIRTUAL HOST CSTRING
386      */
387     if (jk_b_append_string(msg, virtual)) {
388         jk_log(l, JK_LOG_ERROR,
389                "failed appending the virtual host string");
390         JK_TRACE_EXIT(l);
391         return JK_FALSE;
392     }
393
394     JK_TRACE_EXIT(l);
395     return JK_TRUE;
396 }
397
398
399 /*
400  * Decode the Context Info Cmd (Autoconf)
401  *
402  * The Autoconf feature of AJP14, let us know which URL/URI could
403  * be handled by the servlet-engine
404  *
405  * +---------------------------+---------------------------------+----------------------------+-------------------------------+-----------+
406  * | CONTEXT INFO CMD (1 byte) | VIRTUAL HOST NAME (CString (*)) | CONTEXT NAME (CString (*)) | URL1 [\n] URL2 [\n] URL3 [\n] | NEXT CTX. |
407  * +---------------------------+---------------------------------+----------------------------+-------------------------------+-----------+
408  */
409
410 int ajp14_unmarshal_context_info(jk_msg_buf_t *msg,
411                                  jk_context_t *c, jk_logger_t *l)
412 {
413     char *vname;
414     char *cname;
415     char *uri;
416
417     vname = (char *)jk_b_get_string(msg);
418
419     JK_TRACE_ENTER(l);
420     jk_log(l, JK_LOG_DEBUG,
421            "get virtual %s for virtual %s",
422            vname, c->virt);
423
424     if (!vname) {
425         jk_log(l, JK_LOG_ERROR,
426                "can't get virtual hostname");
427         JK_TRACE_EXIT(l);
428         return JK_FALSE;
429     }
430
431     /* Check if we get the correct virtual host */
432     if (c->virt != NULL && vname != NULL && strcmp(c->virt, vname)) {
433         /* set the virtual name, better to add to a virtual list ? */
434
435         if (context_set_virtual(c, vname) == JK_FALSE) {
436             jk_log(l, JK_LOG_ERROR,
437                    "can't malloc virtual hostname");
438             JK_TRACE_EXIT(l);
439             return JK_FALSE;
440         }
441     }
442
443     for (;;) {
444
445         cname = (char *)jk_b_get_string(msg);
446
447         if (!cname) {
448             jk_log(l, JK_LOG_ERROR,
449                    "can't get context");
450             JK_TRACE_EXIT(l);
451             return JK_FALSE;
452         }
453
454         jk_log(l, JK_LOG_DEBUG,
455                "get context %s for virtual %s",
456                cname, vname);
457
458         /* grab all contexts up to empty one which indicate end of contexts */
459         if (!strlen(cname))
460             break;
461
462         /* create new context base (if needed) */
463
464         if (context_add_base(c, cname) == JK_FALSE) {
465             jk_log(l, JK_LOG_ERROR,
466                    "can't add/set context %s",
467                    cname);
468             JK_TRACE_EXIT(l);
469             return JK_FALSE;
470         }
471
472         for (;;) {
473
474             uri = (char *)jk_b_get_string(msg);
475
476             if (!uri) {
477                 jk_log(l, JK_LOG_ERROR,
478                        "can't get URI");
479                 JK_TRACE_EXIT(l);
480                 return JK_FALSE;
481             }
482
483             if (!strlen(uri)) {
484                 jk_log(l, JK_LOG_DEBUG, "No more URI for context %s", cname);
485                 break;
486             }
487
488             jk_log(l, JK_LOG_INFO,
489                    "Got URI (%s) for virtualhost %s and context %s", uri,
490                    vname, cname);
491
492             if (context_add_uri(c, cname, uri) == JK_FALSE) {
493                 jk_log(l, JK_LOG_ERROR,
494                        "can't add/set uri (%s) for context %s",
495                        uri, cname);
496                 JK_TRACE_EXIT(l);
497                 return JK_FALSE;
498             }
499         }
500     }
501
502     JK_TRACE_EXIT(l);
503     return JK_TRUE;
504 }
505
506
507 /*
508  * Build the Context State Query Cmd
509  *
510  * We send the list of contexts where we want to know state, empty string end context list*
511  * If cname is set, only ask about THIS context
512  *
513  * +----------------------------+----------------------------------+----------------------------+----+
514  * | CONTEXT STATE CMD (1 byte) |  VIRTUAL HOST NAME (CString (*)) | CONTEXT NAME (CString (*)) | .. |
515  * +----------------------------+----------------------------------+----------------------------+----+
516  *
517  */
518
519 int ajp14_marshal_context_state_into_msgb(jk_msg_buf_t *msg,
520                                           jk_context_t *c,
521                                           char *cname, jk_logger_t *l)
522 {
523     jk_context_item_t *ci;
524     int i;
525
526     JK_TRACE_ENTER(l);
527
528     /* To be on the safe side */
529     jk_b_reset(msg);
530
531     /*
532      * CONTEXT STATE CMD
533      */
534     if (jk_b_append_byte(msg, AJP14_CONTEXT_STATE_CMD)) {
535         JK_TRACE_EXIT(l);
536         return JK_FALSE;
537     }
538     /*
539      * VIRTUAL HOST CSTRING
540      */
541     if (jk_b_append_string(msg, c->virt)) {
542         jk_log(l, JK_LOG_ERROR,
543                "failed appending the virtual host string");
544         JK_TRACE_EXIT(l);
545         return JK_FALSE;
546     }
547
548     if (cname) {
549
550         ci = context_find_base(c, cname);
551
552         if (!ci) {
553             jk_log(l, JK_LOG_ERROR,
554                    "unknown context %s",
555                    cname);
556             JK_TRACE_EXIT(l);
557             return JK_FALSE;
558         }
559
560         /*
561          * CONTEXT CSTRING
562          */
563
564         if (jk_b_append_string(msg, cname)) {
565             jk_log(l, JK_LOG_ERROR,
566                    "failed appending the context string %s",
567                    cname);
568             JK_TRACE_EXIT(l);
569             return JK_FALSE;
570         }
571     }
572     else {                      /* Grab all contexts name */
573
574         for (i = 0; i < c->size; i++) {
575
576             /*
577              * CONTEXT CSTRING
578              */
579             if (jk_b_append_string(msg, c->contexts[i]->cbase)) {
580                 jk_log(l, JK_LOG_ERROR,
581                        "failed appending the context string %s",
582                        c->contexts[i]->cbase);
583                 JK_TRACE_EXIT(l);
584                 return JK_FALSE;
585             }
586         }
587     }
588
589     /* End of context list, an empty string */
590
591     if (jk_b_append_string(msg, "")) {
592         jk_log(l, JK_LOG_ERROR,
593                "failed appending end of contexts");
594         JK_TRACE_EXIT(l);
595         return JK_FALSE;
596     }
597
598     JK_TRACE_EXIT(l);
599     return JK_TRUE;
600 }
601
602
603 /*
604  * Decode the Context State Reply Cmd
605  *
606  * We get update of contexts list, empty string end context list*
607  *
608  * +----------------------------------+---------------------------------+----------------------------+------------------+----+
609  * | CONTEXT STATE REPLY CMD (1 byte) | VIRTUAL HOST NAME (CString (*)) | CONTEXT NAME (CString (*)) | UP/DOWN (1 byte) | .. |
610  * +----------------------------------+---------------------------------+----------------------------+------------------+----+
611  *
612  */
613
614 int ajp14_unmarshal_context_state_reply(jk_msg_buf_t *msg,
615                                         jk_context_t *c, jk_logger_t *l)
616 {
617     char *vname;
618     char *cname;
619     jk_context_item_t *ci;
620
621     JK_TRACE_ENTER(l);
622     /* get virtual name */
623     vname = (char *)jk_b_get_string(msg);
624
625     if (!vname) {
626         jk_log(l, JK_LOG_ERROR,
627                "can't get virtual hostname");
628         JK_TRACE_EXIT(l);
629         return JK_FALSE;
630     }
631
632     /* Check if we speak about the correct virtual */
633     if (strcmp(c->virt, vname)) {
634         jk_log(l, JK_LOG_ERROR,
635                "incorrect virtual %s instead of %s",
636                vname, c->virt);
637         JK_TRACE_EXIT(l);
638         return JK_FALSE;
639     }
640
641     for (;;) {
642
643         /* get context name */
644         cname = (char *)jk_b_get_string(msg);
645
646         if (!cname) {
647             jk_log(l, JK_LOG_ERROR,
648                    "can't get context");
649             JK_TRACE_EXIT(l);
650             return JK_FALSE;
651         }
652
653         if (!strlen(cname))
654             break;
655
656         ci = context_find_base(c, cname);
657
658         if (!ci) {
659             jk_log(l, JK_LOG_ERROR,
660                    "unknow context %s for virtual %s",
661                    cname, vname);
662             JK_TRACE_EXIT(l);
663             return JK_FALSE;
664         }
665
666         ci->status = jk_b_get_int(msg);
667
668         if (JK_IS_DEBUG_LEVEL(l))
669             jk_log(l, JK_LOG_DEBUG,
670                    "updated context %s to state %d",
671                    cname, ci->status);
672     }
673
674     JK_TRACE_EXIT(l);
675     return JK_TRUE;
676 }
677
678 /*
679  * Decode the Context Update Cmd
680  * 
681  * +-----------------------------+---------------------------------+----------------------------+------------------+
682  * | CONTEXT UPDATE CMD (1 byte) | VIRTUAL HOST NAME (CString (*)) | CONTEXT NAME (CString (*)) | UP/DOWN (1 byte) |
683  * +-----------------------------+---------------------------------+----------------------------+------------------+
684  * 
685  */
686
687 int ajp14_unmarshal_context_update_cmd(jk_msg_buf_t *msg,
688                                        jk_context_t *c, jk_logger_t *l)
689 {
690     int rc;
691     JK_TRACE_ENTER(l);
692     rc = ajp14_unmarshal_context_state_reply(msg, c, l);
693     JK_TRACE_EXIT(l);
694     return rc;
695 }