bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / tomcat-connectors-1.2.32-src / native / common / jk_ajp14_worker.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: AJP14 next generation Bi-directional protocol.             *
20  * Author:      Henri Gomez <hgomez@apache.org>                            *
21  * Version:     $Revision: 611589 $                                          *
22  ***************************************************************************/
23
24 #include "jk_context.h"
25 #include "jk_ajp14_worker.h"
26
27
28 /*
29  * AJP14 Autoconf Phase
30  *
31  * CONTEXT QUERY / REPLY
32  */
33
34 #define MAX_URI_SIZE    512
35
36 static int handle_discovery(ajp_endpoint_t * ae,
37                             jk_worker_env_t *we,
38                             jk_msg_buf_t *msg, jk_logger_t *l)
39 {
40     int cmd;
41     int i, j;
42 #if 0
43     /* Not used for now */
44     jk_login_service_t *jl = ae->worker->login;
45 #endif
46     jk_context_item_t *ci;
47     jk_context_t *c;
48     char *buf;
49
50 #ifndef TESTME
51     JK_TRACE_ENTER(l);
52
53     ajp14_marshal_context_query_into_msgb(msg, we->virtual, l);
54
55     jk_log(l, JK_LOG_DEBUG, "send query");
56
57     if (ajp_connection_tcp_send_message(ae, msg, l) != JK_TRUE) {
58         JK_TRACE_EXIT(l);
59         return JK_FALSE;
60     }
61     jk_log(l, JK_LOG_DEBUG, "wait context reply");
62
63     jk_b_reset(msg);
64
65     if (ajp_connection_tcp_get_message(ae, msg, l) != JK_TRUE) {
66         JK_TRACE_EXIT(l);
67         return JK_FALSE;
68     }
69     if ((cmd = jk_b_get_byte(msg)) != AJP14_CONTEXT_INFO_CMD) {
70         jk_log(l, JK_LOG_ERROR,
71                "awaited command %d, received %d",
72                AJP14_CONTEXT_INFO_CMD, cmd);
73         JK_TRACE_EXIT(l);
74         return JK_FALSE;
75     }
76
77     if (context_alloc(&c, we->virtual) != JK_TRUE) {
78         jk_log(l, JK_LOG_ERROR,
79                "can't allocate context room");
80         JK_TRACE_EXIT(l);
81         return JK_FALSE;
82     }
83
84     if (ajp14_unmarshal_context_info(msg, c, l) != JK_TRUE) {
85         jk_log(l, JK_LOG_ERROR,
86                "can't get context reply");
87         JK_TRACE_EXIT(l);
88         return JK_FALSE;
89     }
90
91     jk_log(l, JK_LOG_DEBUG, "received context");
92
93     buf = malloc(MAX_URI_SIZE); /* Really a very long URI */
94
95     if (!buf) {
96         jk_log(l, JK_LOG_ERROR, "can't malloc buf");
97         JK_TRACE_EXIT(l);
98         return JK_FALSE;
99     }
100
101     for (i = 0; i < c->size; i++) {
102         ci = c->contexts[i];
103         for (j = 0; j < ci->size; j++) {
104
105 #ifndef USE_SPRINTF
106             snprintf(buf, MAX_URI_SIZE - 1, "/%s/%s", ci->cbase, ci->uris[j]);
107 #else
108             sprintf(buf, "/%s/%s", ci->cbase, ci->uris[j]);
109 #endif
110
111             jk_log(l, JK_LOG_INFO,
112                    "worker %s will handle uri %s in context %s [%s]",
113                    ae->worker->name, ci->uris[j], ci->cbase, buf);
114
115             uri_worker_map_add(we->uri_to_worker, buf, ae->worker->name, SOURCE_TYPE_DISCOVER, l);
116         }
117     }
118
119     free(buf);
120     context_free(&c);
121
122 #else
123
124     uri_worker_map_add(we->uri_to_worker, "/examples/servlet/*",
125                        ae->worker->name, SOURCE_TYPE_DISCOVER, l);
126     uri_worker_map_add(we->uri_to_worker, "/examples/*.jsp", ae->worker->name,
127                        SOURCE_TYPE_DISCOVER, l);
128     uri_worker_map_add(we->uri_to_worker, "/examples/*.gif", ae->worker->name,
129                        SOURCE_TYPE_DISCOVER, l);
130
131 #endif
132
133     JK_TRACE_EXIT(l);
134     return JK_TRUE;
135 }
136
137 /*
138  * AJP14 Logon Phase
139  *
140  * INIT + REPLY / NEGO + REPLY
141  */
142
143 static int handle_logon(ajp_endpoint_t * ae,
144                         jk_msg_buf_t *msg, jk_logger_t *l)
145 {
146     int cmd;
147
148     jk_login_service_t *jl = ae->worker->login;
149     JK_TRACE_ENTER(l);
150
151     ajp14_marshal_login_init_into_msgb(msg, jl, l);
152
153     jk_log(l, JK_LOG_DEBUG, "send init");
154
155     if (ajp_connection_tcp_send_message(ae, msg, l) != JK_TRUE) {
156         JK_TRACE_EXIT(l);
157         return JK_FALSE;
158     }
159     jk_log(l, JK_LOG_DEBUG, "wait init reply");
160
161     jk_b_reset(msg);
162
163     if (ajp_connection_tcp_get_message(ae, msg, l) != JK_TRUE) {
164         JK_TRACE_EXIT(l);
165         return JK_FALSE;
166     }
167     if ((cmd = jk_b_get_byte(msg)) != AJP14_LOGSEED_CMD) {
168         jk_log(l, JK_LOG_ERROR,
169                "awaited command %d, received %d",
170                AJP14_LOGSEED_CMD, cmd);
171         JK_TRACE_EXIT(l);
172         return JK_FALSE;
173     }
174
175     if (ajp14_unmarshal_login_seed(msg, jl, l) != JK_TRUE) {
176         JK_TRACE_EXIT(l);
177         return JK_FALSE;
178     }
179     jk_log(l, JK_LOG_DEBUG, "received entropy %s",
180            jl->entropy);
181
182     ajp14_compute_md5(jl, l);
183
184     if (ajp14_marshal_login_comp_into_msgb(msg, jl, l) != JK_TRUE) {
185         JK_TRACE_EXIT(l);
186         return JK_FALSE;
187     }
188     if (ajp_connection_tcp_send_message(ae, msg, l) != JK_TRUE) {
189         JK_TRACE_EXIT(l);
190         return JK_FALSE;
191     }
192     jk_b_reset(msg);
193
194     if (ajp_connection_tcp_get_message(ae, msg, l) != JK_TRUE) {
195         JK_TRACE_EXIT(l);
196         return JK_FALSE;
197     }
198     switch (jk_b_get_byte(msg)) {
199
200     case AJP14_LOGOK_CMD:
201         if (ajp14_unmarshal_log_ok(msg, jl, l) == JK_TRUE) {
202             jk_log(l, JK_LOG_DEBUG,
203                    "Successfully connected to servlet-engine %s",
204                    jl->servlet_engine_name);
205             JK_TRACE_EXIT(l);
206             return JK_TRUE;
207         }
208         break;
209
210     case AJP14_LOGNOK_CMD:
211         ajp14_unmarshal_log_nok(msg, l);
212         break;
213     }
214
215     JK_TRACE_EXIT(l);
216     return JK_FALSE;
217 }
218
219 static int logon(ajp_endpoint_t * ae, jk_logger_t *l)
220 {
221     jk_pool_t *p = &ae->pool;
222     jk_msg_buf_t *msg;
223     int rc;
224
225     JK_TRACE_ENTER(l);
226
227     msg = jk_b_new(p);
228     jk_b_set_buffer_size(msg, DEF_BUFFER_SZ);
229
230     if ((rc = handle_logon(ae, msg, l)) == JK_FALSE)
231         ajp_close_endpoint(ae, l);
232
233     JK_TRACE_EXIT(l);
234     return rc;
235 }
236
237 static int discovery(ajp_endpoint_t * ae, jk_worker_env_t *we, jk_logger_t *l)
238 {
239     jk_pool_t *p = &ae->pool;
240     jk_msg_buf_t *msg;
241     int rc;
242
243     JK_TRACE_ENTER(l);
244
245     msg = jk_b_new(p);
246     jk_b_set_buffer_size(msg, DEF_BUFFER_SZ);
247
248     if ((rc = handle_discovery(ae, we, msg, l)) == JK_FALSE)
249         ajp_close_endpoint(ae, l);
250
251     JK_TRACE_EXIT(l);
252     return rc;
253 }
254
255 /* -------------------- Method -------------------- */
256 static int JK_METHOD validate(jk_worker_t *pThis,
257                               jk_map_t *props,
258                               jk_worker_env_t *we, jk_logger_t *l)
259 {
260     ajp_worker_t *aw;
261     const char *secret_key;
262
263     JK_TRACE_ENTER(l);
264     if (ajp_validate(pThis, props, we, l, AJP14_PROTO) == JK_FALSE) {
265         JK_TRACE_EXIT(l);
266         return JK_FALSE;
267     }
268     aw = pThis->worker_private;
269
270     secret_key = jk_get_worker_secret_key(props, aw->name);
271
272     if ((!secret_key) || (!strlen(secret_key))) {
273         jk_log(l, JK_LOG_ERROR,
274                "validate error, empty or missing secretkey");
275         JK_TRACE_EXIT(l);
276         return JK_FALSE;
277     }
278
279     /* jk_log(l, JK_LOG_DEBUG, "Into ajp14:validate - secret_key=%s", secret_key); */
280     JK_TRACE_EXIT(l);
281     return JK_TRUE;
282 }
283
284 static int JK_METHOD get_endpoint(jk_worker_t *pThis,
285                                   jk_endpoint_t **pend, jk_logger_t *l)
286 {
287     int rc;
288     JK_TRACE_ENTER(l);
289     rc = ajp_get_endpoint(pThis, pend, l, AJP14_PROTO);
290     JK_TRACE_EXIT(l);
291     return rc;
292 }
293
294 static int JK_METHOD init(jk_worker_t *pThis,
295                           jk_map_t *props,
296                           jk_worker_env_t *we, jk_logger_t *l)
297 {
298     ajp_worker_t *aw;
299     ajp_endpoint_t *ae;
300     jk_endpoint_t *je;
301     int rc;
302
303     JK_TRACE_EXIT(l);
304
305     if (ajp_init(pThis, props, we, l, AJP14_PROTO) == JK_FALSE) {
306         JK_TRACE_EXIT(l);
307         return JK_FALSE;
308     }
309     aw = pThis->worker_private;
310
311     /* Set Secret Key (used at logon time) */
312     aw->login->secret_key = jk_get_worker_secret_key(props, aw->name);
313
314     if (aw->login->secret_key == NULL) {
315         jk_log(l, JK_LOG_ERROR, "can't malloc secret_key");
316         JK_TRACE_EXIT(l);
317         return JK_FALSE;
318     }
319
320     /* Set WebServerName (used at logon time) */
321     aw->login->web_server_name = strdup(we->server_name);
322
323     if (aw->login->web_server_name == NULL) {
324         jk_log(l, JK_LOG_ERROR, "can't malloc web_server_name");
325         JK_TRACE_EXIT(l);
326         return JK_FALSE;
327     }
328
329     if (get_endpoint(pThis, &je, l) == JK_FALSE) {
330         JK_TRACE_EXIT(l);
331         return JK_FALSE;
332     }
333     ae = je->endpoint_private;
334
335     if (ajp_connect_to_endpoint(ae, l) == JK_TRUE) {
336
337         /* connection stage passed - try to get context info
338          * this is the long awaited autoconf feature :)
339          */
340         rc = discovery(ae, we, l);
341         ajp_close_endpoint(ae, l);
342         JK_TRACE_EXIT(l);
343         return rc;
344     }
345
346     JK_TRACE_EXIT(l);
347     return JK_TRUE;
348 }
349
350
351 static int JK_METHOD destroy(jk_worker_t **pThis, jk_logger_t *l)
352 {
353     int rc;
354     ajp_worker_t *aw = (*pThis)->worker_private;
355
356     JK_TRACE_ENTER(l);
357
358     if (aw->login) {
359         free(aw->login);
360         aw->login = NULL;
361     }
362
363     rc = ajp_destroy(pThis, l, AJP14_PROTO);
364     JK_TRACE_EXIT(l);
365     return rc;
366 }
367
368 int JK_METHOD ajp14_worker_factory(jk_worker_t **w,
369                                    const char *name, jk_logger_t *l)
370 {
371     ajp_worker_t *aw;
372
373     JK_TRACE_ENTER(l);
374     if (ajp_worker_factory(w, name, l) == JK_FALSE)
375         return 0;
376
377     aw = (*w)->worker_private;
378     aw->proto = AJP14_PROTO;
379
380     aw->login = (jk_login_service_t *)malloc(sizeof(jk_login_service_t));
381
382     if (aw->login == NULL) {
383         jk_log(l, JK_LOG_ERROR,
384                "malloc failed for login area");
385         JK_TRACE_EXIT(l);
386         return 0;
387     }
388
389     memset(aw->login, 0, sizeof(jk_login_service_t));
390
391     aw->login->negociation =
392         (AJP14_CONTEXT_INFO_NEG | AJP14_PROTO_SUPPORT_AJP14_NEG);
393     aw->login->web_server_name = NULL;  /* must be set in init */
394
395     aw->worker.validate = validate;
396     aw->worker.init = init;
397     aw->worker.get_endpoint = get_endpoint;
398     aw->worker.destroy = destroy;
399
400     aw->logon = logon;          /* LogOn Handler for AJP14 */
401
402     JK_TRACE_EXIT(l);
403     return JK_AJP14_WORKER_TYPE;
404 }