1 /*
2  * Copyright 1999-2006 University of Chicago
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
18 #include "globus_i_service_engine.h"
19 #include "globus_service_registry.h"
20 #include "globus_soap_message.h"
21 #include "globus_soap_message_attrs.h"
22 #include "globus_soap_message_fault.h"
23 #include "globus_xio_tcp_driver.h"
24 #include "globus_xio_http.h"
25 #include "globus_xio_buffer.h"
26 #include "globus_xio_gsi.h"
27 #include "version.h"
28 #include "globus_flavor.h"
29 #include "libxml/uri.h"
30 #include "globus_ws_addressing.h"
31 #include "globus_soap_message_markers.h"
32 #include "globus_i_soap_message.h"
33 #ifndef TARGET_ARCH_NETOS
34 #include "globus_usage.h"
35 #endif
36
37 #define SOAP_ACTION_HEADER              "SOAPAction"
38 #define CONTENT_TYPE_HEADER             "Content-Type"
39
40 #define GLOBUS_I_SERVICE_DESCRIPTOR_KEY       "GLOBUS_SERVICE_DESCRIPTOR"
41 #define GLOBUS_I_SERVICE_EXTENSION_HANDLE_KEY "GLOBUS_SERVICE_EXTENSION_HANDLE"
42 #define GLOBUS_I_SESSION_HANDLE_KEY           "GLOBUS_ENGINE_CALLBACK_HANDLE"
43 #define GLOBUS_I_SERVICE_OPERATION_QNAME_KEY  "GLOBUS_SERVICE_OPERATION_QNAME"
44
45 static globus_list_t *              globus_l_service_engine_extensions;
46 static globus_list_t *              globus_l_service_engine_instances;
47 static globus_mutex_t               globus_l_service_engine_extensions_mutex;
48
49 #define GlobusServiceEngineExtensionLock() \
50     GlobusDebugPrintf(GLOBUS_SOAP_MESSAGE, GLOBUS_SOAP_MESSAGE_DEBUG_DEBUG, \
51         ("%s:%d locking service extension mutex\n", __FILE__, __LINE__)); \
52     globus_mutex_lock(&globus_l_service_engine_extensions_mutex)
53
54 #define GlobusServiceEngineExtensionUnlock() \
55     globus_mutex_unlock(&globus_l_service_engine_extensions_mutex); \
56     GlobusDebugPrintf(GLOBUS_SOAP_MESSAGE, GLOBUS_SOAP_MESSAGE_DEBUG_DEBUG, \
57         ("%s: %d unlocked service extension mutex\n", __FILE__, __LINE__))
58
59 globus_extension_registry_t             globus_service_registry =
60 {
61     NULL,
62     GLOBUS_FALSE,
63     GLOBUS_FALSE
64 };
65
66 static int
67 globus_l_service_engine_activate();
68
69 static int
70 globus_l_service_engine_deactivate();
71
72 globus_module_descriptor_t              globus_l_service_engine_module =
73 {
74     "globus_service_engine_module",
75     globus_l_service_engine_activate,
76     globus_l_service_engine_deactivate,
77     NULL,
78     NULL,
79     &local_version
80 };
81
82 0 GlobusDebugDefine(GLOBUS_SERVICE_ENGINE);
83
84 typedef enum
85 {
86     GLOBUS_L_SERVICE_ENGINE_REQUEST_READ_MESSAGE,
87     GLOBUS_L_SERVICE_ENGINE_REQUEST_INIT_SERVICE_HANDLERS,
88     GLOBUS_L_SERVICE_ENGINE_REQUEST_INIT_HANDLERS,
89     GLOBUS_L_SERVICE_ENGINE_START_DESERIALIZE,
90     GLOBUS_L_SERVICE_ENGINE_TRIGGER_INVOKE_HANDLERS,
91     GLOBUS_L_SERVICE_ENGINE_REQUEST_HEADER_FAILED,
92     GLOBUS_L_SERVICE_ENGINE_REQUEST_INVOKE_HANDLERS,
93     GLOBUS_L_SERVICE_ENGINE_REQUEST_INVOKE_SERVICE_HANDLERS,
94     GLOBUS_L_SERVICE_ENGINE_REQUEST_DESERIALIZE,
95     GLOBUS_L_SERVICE_ENGINE_REQUEST_DESTROY_SERVICE_HANDLERS,
96     GLOBUS_L_SERVICE_ENGINE_REQUEST_DESTROY_HANDLERS,
97     GLOBUS_L_SERVICE_ENGINE_REQUEST_INVOKE_OPERATION,
98     GLOBUS_L_SERVICE_ENGINE_REQUEST_READ_ANOTHER_MESSAGE,
99     GLOBUS_L_SERVICE_ENGINE_RESPONSE_INIT_SERVICE_HANDLERS,
100     GLOBUS_L_SERVICE_ENGINE_RESPONSE_INIT_HANDLERS,
101     GLOBUS_L_SERVICE_ENGINE_RESPONSE_INVOKE_SERVICE_HANDLERS,
102     GLOBUS_L_SERVICE_ENGINE_RESPONSE_INVOKE_HANDLERS,
103     GLOBUS_L_SERVICE_ENGINE_RESPONSE_DESTROY_SERVICE_HANDLERS,
104     GLOBUS_L_SERVICE_ENGINE_RESPONSE_DESTROY_HANDLERS,
105     GLOBUS_L_SERVICE_ENGINE_RESPONSE_SEND,
106     GLOBUS_L_SERVICE_ENGINE_RESPONSE_CLOSE,
107     GLOBUS_L_SERVICE_ENGINE_RESPONSE_DONE
108 } globus_l_service_session_state_t;
109
110 static char * globus_l_service_engine_state_strings[22] =
111 {
112     "GLOBUS_L_SERVICE_ENGINE_REQUEST_READ_MESSAGE",
113     "GLOBUS_L_SERVICE_ENGINE_REQUEST_INIT_SERVICE_HANDLERS",
114     "GLOBUS_L_SERVICE_ENGINE_REQUEST_INIT_HANDLERS",
115     "GLOBUS_L_SERVICE_ENGINE_START_DESERIALIZE",
116     "GLOBUS_L_SERVICE_ENGINE_TRIGGER_INVOKE_HANDLERS",
117     "GLOBUS_L_SERVICE_ENGINE_REQUEST_HEADER_FAILED",
118     "GLOBUS_L_SERVICE_ENGINE_REQUEST_INVOKE_HANDLERS",
119     "GLOBUS_L_SERVICE_ENGINE_REQUEST_INVOKE_SERVICE_HANDLERS",
120     "GLOBUS_L_SERVICE_ENGINE_REQUEST_DESERIALIZE",
121     "GLOBUS_L_SERVICE_ENGINE_REQUEST_DESTROY_SERVICE_HANDLERS",
122     "GLOBUS_L_SERVICE_ENGINE_REQUEST_DESTROY_HANDLERS",
123     "GLOBUS_L_SERVICE_ENGINE_REQUEST_INVOKE_OPERATION",
124     "GLOBUS_L_SERVICE_ENGINE_REQUEST_READ_ANOTHER_MESSAGE",
125     "GLOBUS_L_SERVICE_ENGINE_RESPONSE_INIT_SERVICE_HANDLERS",
126     "GLOBUS_L_SERVICE_ENGINE_RESPONSE_INIT_HANDLERS",
127     "GLOBUS_L_SERVICE_ENGINE_RESPONSE_INVOKE_SERVICE_HANDLERS",
128     "GLOBUS_L_SERVICE_ENGINE_RESPONSE_INVOKE_HANDLERS",
129     "GLOBUS_L_SERVICE_ENGINE_RESPONSE_DESTROY_SERVICE_HANDLERS",
130     "GLOBUS_L_SERVICE_ENGINE_RESPONSE_DESTROY_HANDLERS",
131     "GLOBUS_L_SERVICE_ENGINE_RESPONSE_SEND",
132     "GLOBUS_L_SERVICE_ENGINE_RESPONSE_CLOSE",
133     "GLOBUS_L_SERVICE_ENGINE_RESPONSE_DONE"
134 };
135
136 typedef struct globus_l_session_callback_handle_s
137 {
138     globus_service_engine_t                engine;
139     globus_soap_message_handle_t           message;
140     globus_service_session_callback_func_t callback;
141     void *                                 args;
142     globus_l_service_session_state_t       state;
143     globus_result_t                        result;
144     globus_result_t                        callback_result;
145     globus_service_response_t              response;
146
147     globus_service_session_callback_func_t process_callback;
148     void *                                 process_args;
149     globus_bool_t                          faulting;
150 } globus_l_session_callback_handle_t;
151
152 typedef struct
153 {
154     globus_service_engine_t               engine;
155     globus_service_engine_callback_func_t callback;
156     void *                                args;
157     globus_result_t                       result;
158 } globus_l_service_engine_callback_handle_t;
159
160 static
161 void
162 globus_l_service_session_callback(
163     void *                              args);
164
165 static
166 void
167 globus_l_service_session_callback_handle_destroy(
168     globus_l_session_callback_handle_t * callback_handle);
169
170 static
171 void
172 globus_l_service_engine_open_callback(
173     globus_xio_handle_t                 handle,
174     globus_result_t                     result,
175     void *                              user_arg);
176
177 static
178 void
179 globus_l_service_engine_service_module_destroy(
180     void *                              ext);
181
182 static
183 void
184 globus_l_service_engine_request_ready_callback(
185     globus_xio_handle_t                 handle,
186     globus_result_t                     result,
187     globus_byte_t *                     buffer,
188     globus_size_t                       len,
189     globus_size_t                       nbytes,
190     globus_xio_data_descriptor_t        data_desc,
191     void *                              user_arg);
192
193 static
194 void
195 globus_l_service_engine_accept_callback(
196     globus_xio_server_t                 server,
197     globus_xio_handle_t                 new_handle,
198     globus_result_t                     result,
199     void *                              user_args);
200
201 static
202 void
203 globus_l_service_session_result_callback(
204     globus_result_t                     result,
205     void *                              args);
206
207 static
208 void
209 globus_l_service_engine_send_client_fault(
210     void *                              args);
211
212 static
213 void 
214 globus_l_service_engine_session_complete_callback(
215     globus_result_t                     result,
216     globus_service_engine_t             engine,
217     globus_soap_message_handle_t        session,
218     void *                              args);
219
220 static
221 void
222 globus_l_service_engine_session_started_callback(
223     globus_result_t                     result,
224     globus_service_engine_t             engine,
225     globus_soap_message_handle_t        session,
226     void *                              args);
227
228 static
229 int
230 globus_l_service_engine_is_equal(
231     void *                              datum,
232     void *                              arg);
233
234 #ifndef TARGET_ARCH_NETOS
235 static globus_usage_stats_handle_t globus_l_service_engine_usage;
236 #endif
237
238 static int
239 globus_l_service_engine_activate()
240 {
241 174     int                                 rc = 0;
242 174     GlobusFuncName(globus_l_service_engine_activate);
243
244 174     globus_l_service_engine_extensions = NULL;
245 174     globus_l_service_engine_instances = NULL;
246
247 174     rc = globus_module_activate(GLOBUS_COMMON_MODULE);
248 174     if(rc != GLOBUS_SUCCESS)
249     {
250 0         return rc;
251     }
252
253 174     GlobusDebugInit(GLOBUS_SERVICE_ENGINE, DEBUG INFO TRACE WARN ERROR);
254 174     GlobusServiceEngineDebugEnter();
255
256 174     rc = globus_module_activate(GLOBUS_SOAP_MESSAGE_MODULE);
257 174     if(rc != GLOBUS_SUCCESS)
258     {
259 0         globus_module_deactivate(GLOBUS_COMMON_MODULE);
260 0         goto error_exit;
261     }
262     
263 174     rc = globus_module_activate(GLOBUS_OPERATION_PROVIDER_MODULE);
264 174     if(rc != GLOBUS_SUCCESS)
265     {
266 0         globus_module_deactivate(GLOBUS_SOAP_MESSAGE_MODULE);
267 0         globus_module_deactivate(GLOBUS_COMMON_MODULE);
268 0         goto error_exit;
269     }
270
271 #ifndef TARGET_ARCH_NETOS
272 174     rc = globus_module_activate(GLOBUS_USAGE_MODULE);
273 174     if(rc == GLOBUS_SUCCESS)
274     {
275 174         globus_result_t                 result;
276
277 174         result = globus_usage_stats_handle_init(
278             &globus_l_service_engine_usage,
279             4, 1, NULL);
280 174         if(result == GLOBUS_SUCCESS)
281         {
282 174             globus_usage_stats_send(globus_l_service_engine_usage, 0);
283         }
284         else
285         {
286 0             globus_l_service_engine_usage = NULL;
287 0             globus_module_deactivate(GLOBUS_USAGE_MODULE);
288 0             globus_object_free(globus_error_get(result));
289 0             rc = GLOBUS_SUCCESS;
290         }
291     }
292     else
293     {
294 0         rc = GLOBUS_SUCCESS;
295     }
296 #endif
297
298 174     globus_mutex_init(&globus_l_service_engine_extensions_mutex, NULL);
299     
300 174     goto exit;
301
302  error_exit:
303
304 0     GlobusServiceEngineDebugExit();
305 0     GlobusDebugDestroy(GLOBUS_SERVICE_ENGINE);
306 0     return rc;
307
308  exit:
309
310 174     GlobusServiceEngineDebugExit();
311 174     return rc;
312 }
313
314 static
315 void
316 globus_l_service_engine_extension_destroy(
317     void *                              sym)
318 202 {
319 202     char *                              symbol = (char *) sym;
320
321 202     globus_extension_deactivate(sym);
322 202     globus_free(symbol);
323 }
324
325 static
326 void
327 globus_l_service_engine_destroy(
328     void *                              p)
329 10 {
330 10     globus_service_engine_t             engine = p;
331 10     int                                 res;
332
333 10     GlobusFuncName(globus_l_service_engine_destroy);
334 10     GlobusServiceEngineDebugEnter();
335     
336 10     if(engine->handlers)
337     {
338 10         globus_handler_chain_destroy(engine->handlers);
339     }
340
341 10     if(engine->contact)
342     {
343 10         free(engine->contact);
344     }
345
346 10     if(engine->server)
347     {
348 10         globus_xio_server_close(engine->server);
349     }
350
351 10     res = globus_mutex_destroy(&engine->mutex);
352 10     globus_assert_string((res == 0), "Failed to destroy mutex");
353
354 10     if(engine->attrs)
355     {
356 10         globus_soap_message_attr_destroy(engine->attrs);
357     }
358     
359 10     free(engine);
360 10     GlobusServiceEngineDebugExit();
361 }
362
363 static int
364 globus_l_service_engine_deactivate()
365 161 {
366 161     int                                 rc = 0;
367 161     GlobusFuncName(globus_l_service_engine_deactivate);
368 161     GlobusServiceEngineDebugEnter();
369
370 161     GlobusServiceEngineExtensionLock();
371 161     globus_list_destroy_all(globus_l_service_engine_extensions,
372                             globus_l_service_engine_extension_destroy);
373 161     globus_list_destroy_all(globus_l_service_engine_instances,
374                             globus_l_service_engine_destroy);
375 161     GlobusServiceEngineExtensionUnlock();
376 161     globus_mutex_destroy(&globus_l_service_engine_extensions_mutex);
377
378 #ifndef TARGET_ARCH_NETOS
379 161     if (globus_l_service_engine_usage != NULL)
380     {
381 161         globus_usage_stats_handle_destroy(globus_l_service_engine_usage);
382     
383 161         rc = globus_module_deactivate(GLOBUS_USAGE_MODULE);
384 161         if(rc != GLOBUS_SUCCESS)
385         {
386 0             goto exit;
387         }
388     }
389 #endif
390
391 161     rc = globus_module_deactivate(GLOBUS_OPERATION_PROVIDER_MODULE);
392 161     if(rc != GLOBUS_SUCCESS)
393     {
394 0         goto exit;
395     }
396
397 161     rc = globus_module_deactivate(GLOBUS_SOAP_MESSAGE_MODULE);
398 161     if(rc != GLOBUS_SUCCESS)
399     {
400 161         goto exit;
401     }
402
403  exit:
404
405 161     GlobusServiceEngineDebugExit();
406 161     GlobusDebugDestroy(GLOBUS_SERVICE_ENGINE);
407 161     globus_module_deactivate(GLOBUS_COMMON_MODULE);
408
409 161     return rc;
410 }
411
412 static
413 globus_bool_t
414 globus_l_service_engine_timeout_callback(
415     globus_xio_handle_t                 handle,
416     globus_xio_operation_type_t         type,
417     void *                              user_arg)
418 0 {
419 0     return GLOBUS_TRUE;
420 }
421
422 globus_result_t
423 globus_service_engine_init(
424     globus_service_engine_t *           new_engine,
425     globus_soap_message_attr_t          attrs,
426     const char *                        port_contact,
427     globus_handler_chain_t              handlers,
428     globus_bool_t                       enable_https)
429 153 {
430 153     globus_result_t                     result = GLOBUS_SUCCESS;
431 153     int                                 port = 0;
432 153     globus_i_service_engine_t *         engine = NULL;
433 153     globus_xio_attr_t                   server_attr = NULL;
434 153     char *                              contact = NULL;
435 153     void *                              timeout = NULL;
436 153     globus_soap_message_auth_method_t   secattr;
437 153     GlobusFuncName(globus_service_engine_init);
438 153     GlobusServiceEngineDebugEnter();
439
440 153     engine = malloc(sizeof(globus_i_service_engine_t));
441 153     if(!engine)
442     {
443 0         result = GlobusServiceEngineErrorOutOfMemory;
444 0         goto exit;
445     }
446 153     memset(engine, 0, sizeof(globus_i_service_engine_t));
447
448 153     if(!attrs)
449     {
450 153         result = globus_soap_message_attr_init(&engine->attrs);
451 153         if(result != GLOBUS_SUCCESS)
452         {
453 0             result = GlobusServiceEngineErrorInitFailed(result);
454 0             goto exit;
455         }
456     }
457     else
458     {
459 0         result = globus_soap_message_attr_copy(
460             &engine->attrs, attrs);
461 0         if(result != GLOBUS_SUCCESS)
462         {
463 0             result = GlobusServiceEngineErrorInitFailed(result);
464 0             goto exit;
465         }
466     }
467
468 153     result = globus_xio_attr_init(&server_attr);
469 153     if(result != GLOBUS_SUCCESS)
470     {
471 0         result = GlobusServiceEngineErrorInitFailed(result);
472 0         goto error;
473     }
474         
475 153     if(port_contact)
476     {
477 0         port = atoi(port_contact);
478 0         if(port < 0)
479         {
480 0             result = GlobusServiceEngineErrorInvalidContact(port_contact);
481 0             goto error;
482         }
483
484 0         result = globus_xio_attr_cntl(server_attr, 
485                                       globus_i_soap_message_tcp_driver,
486                                       GLOBUS_XIO_TCP_SET_PORT, port);
487 0         if(result != GLOBUS_SUCCESS)
488         {
489 0             result = GlobusServiceEngineErrorInitFailed(result);
490 0             goto error;
491         }
492         
493 0         result = globus_xio_attr_cntl(server_attr, 
494                                       globus_i_soap_message_tcp_driver,
495                                       GLOBUS_XIO_TCP_SET_REUSEADDR,
496                                       GLOBUS_TRUE);
497 0         if(result != GLOBUS_SUCCESS)
498         {
499 0             result = GlobusServiceEngineErrorInitFailed(result);
500 0             goto error;
501         }
502     }
503 153     result = globus_xio_attr_cntl(server_attr,
504                                   globus_i_soap_message_tcp_driver,
505                                   GLOBUS_XIO_TCP_SET_NODELAY,
506                                   GLOBUS_TRUE);
507
508 153     if(result != GLOBUS_SUCCESS)
509     {
510 0         result = GlobusServiceEngineErrorInitFailed(result);
511 0         goto error;
512     }
513
514
515 153     timeout = globus_soap_message_attr_get(
516         engine->attrs, GLOBUS_SOAP_MESSAGE_TIMEOUT_KEY);
517 153     if(timeout)
518     {
519 0         result = globus_xio_attr_cntl(
520             server_attr,
521             GLOBUS_NULL,
522             GLOBUS_XIO_ATTR_SET_TIMEOUT_ALL,
523             globus_l_service_engine_timeout_callback,
524             timeout,
525             GLOBUS_NULL);
526 0         if(result != GLOBUS_SUCCESS)
527         {
528 0             result = GlobusSoapMessageErrorFailedTransport(
529                 result, "Failed to set timeout for xio handle");
530 0             goto exit;
531         }
532     }
533
534 153     if(enable_https)
535     {
536 2         engine->https = GLOBUS_TRUE;
537 2         result = globus_i_soap_message_setup_transport_security(
538             engine->attrs,
539             server_attr);
540 2         if(result != GLOBUS_SUCCESS)
541         {
542 0             result = GlobusServiceEngineErrorInitFailed(result);
543 0             goto error;
544         }
545
546 2         result = globus_xio_server_create(
547             &engine->server,
548             server_attr,
549             globus_i_soap_message_xio_https_stack);
550 2         if(result != GLOBUS_SUCCESS)
551         {
552 0             result = GlobusServiceEngineErrorInitFailed(result);
553 0             goto error;
554         }
555     }
556     else
557     {
558 151         result = globus_xio_server_create(&engine->server, 
559                                           server_attr, 
560                                           globus_i_soap_message_xio_stack);
561 151         if(result != GLOBUS_SUCCESS)
562         {
563 0             result = GlobusServiceEngineErrorInitFailed(result);
564 0             goto error;
565         }
566     }
567
568 153     globus_mutex_init(&engine->mutex, NULL);
569
570 153     globus_xio_server_get_contact_string(engine->server, &contact);
571 153     engine->contact = globus_common_create_string(
572         "http%s://%s/",
573         (enable_https ? "s" : ""),
574         contact);
575 153     free(contact);
576
577 153     if(!handlers)
578     {
579 153         int                             res = 0;
580 153         res = globus_extension_activate(GLOBUS_HANDLER_WS_ADDRESSING_LIB);
581 153         if(res != 0)
582         {
583 0             globus_object_t *           tmp = globus_error_get((globus_result_t) res);
584 0             result = GlobusServiceEngineErrorHandlerLoadFailed(
585                 GLOBUS_HANDLER_WS_ADDRESSING_MODULE,
586                 tmp);
587 0             goto error;
588         }
589         
590 153         GlobusServiceEngineExtensionLock();
591 153         globus_list_insert(&globus_l_service_engine_extensions,
592                            strdup(GLOBUS_HANDLER_WS_ADDRESSING_LIB));
593 153         GlobusServiceEngineExtensionUnlock();
594
595 153         globus_handler_chain_init(&engine->handlers);
596         
597 153         result = globus_handler_chain_push(
598             engine->handlers, 
599             GLOBUS_HANDLER_TYPE_REQUEST_ALL,
600             GLOBUS_HANDLER_WS_ADDRESSING_SERVER);
601 153         if(result != GLOBUS_SUCCESS)
602         {
603 0             result = GlobusServiceEngineErrorInitFailed(result);
604 0             goto error;
605         }
606         
607 153         result = globus_handler_chain_push(
608             engine->handlers, 
609             GLOBUS_HANDLER_TYPE_RESPONSE_ALL,
610             GLOBUS_HANDLER_WS_ADDRESSING_SERVER);
611 153         if(result != GLOBUS_SUCCESS)
612         {
613 0             result = GlobusServiceEngineErrorInitFailed(result);
614 0             goto error;
615         }
616
617 153         secattr = (globus_soap_message_auth_method_t)
618             globus_soap_message_attr_get(
619                 engine->attrs,
620                 GLOBUS_SOAP_MESSAGE_AUTHENTICATION_METHOD_KEY);
621
622 153         if ((!enable_https) &&
623                 (secattr == GLOBUS_SOAP_MESSAGE_AUTH_SECURE ||
624                  secattr == GLOBUS_SOAP_MESSAGE_AUTH_SECURE_MESSAGE))
625         {
626 0             res = globus_extension_activate("globus_handler_ws_secure_message");
627 0             if(res != 0)
628             {
629 0                 globus_object_t *       tmp = globus_error_get((globus_result_t) res);
630 0                 result = GlobusServiceEngineErrorHandlerLoadFailed(
631                     "globus_handler_ws_secure_message",
632                     tmp);
633 0                 goto error;
634             }
635             
636 0             GlobusServiceEngineExtensionLock();
637 0             globus_list_insert(&globus_l_service_engine_extensions,
638                                strdup("globus_handler_ws_secure_message"));
639 0             GlobusServiceEngineExtensionUnlock();
640
641 0             result = globus_handler_chain_push(
642                 engine->handlers,
643                 GLOBUS_HANDLER_TYPE_REQUEST,
644                 "globus_handler_ws_secure_message_server");
645 0             if(result != GLOBUS_SUCCESS)
646             {
647 0                 result = GlobusServiceEngineErrorInitFailed(result);
648 0                 goto error;
649             }
650
651 0             result = globus_handler_chain_push(
652                 engine->handlers,
653                 GLOBUS_HANDLER_TYPE_RESPONSE_ALL,
654                 "globus_handler_ws_secure_message_server");
655 0             if(result != GLOBUS_SUCCESS)
656             {
657 0                 result = GlobusServiceEngineErrorInitFailed(result);
658 0                 goto error;
659             }
660         }
661     }
662     else
663     {
664 0         globus_handler_chain_copy(&engine->handlers, handlers);
665     }
666
667 153     *new_engine = (globus_service_engine_t) engine;
668 153     GlobusServiceEngineExtensionLock();
669 153     globus_list_insert(&globus_l_service_engine_instances, engine);
670 153     GlobusServiceEngineExtensionUnlock();
671 0     goto exit;
672
673  error:
674
675 0     if(server_attr)
676     {
677 0         globus_xio_attr_destroy(server_attr);
678     }
679
680 0     if(engine)
681     {
682 0         if(engine->server)
683         {
684 0             globus_xio_server_close(engine->server);
685         }
686
687 0         free(engine);
688     }
689
690  exit:
691
692 153     GlobusServiceEngineDebugExit();
693 153     return result;
694 }
695
696 /**
697  * Get a list of contacts for all engines running in this process.
698  */
699 globus_result_t
700 globus_service_get_engine_contacts(
701     xsd_anyURI **                       contacts,
702     globus_size_t *                     contacts_length)
703 0 {
704 0     globus_result_t                     result = GLOBUS_SUCCESS;
705 0     globus_size_t                       num_engines;
706 0     globus_list_t *                     tmp;
707 0     globus_service_engine_t             tmp_engine;
708 0     xsd_anyURI *                        contact_array = NULL;
709 0     int                                 i = 0;
710
711 0     GlobusServiceEngineExtensionLock();
712
713 0     num_engines = globus_list_size(globus_l_service_engine_instances);
714 0     if (num_engines == 0)
715     {
716 0         goto unlock_out;
717     }
718 0     contact_array = malloc(num_engines * sizeof(xsd_anyURI));
719
720 0     if (contact_array == NULL)
721     {
722 0         result = GlobusServiceEngineErrorOutOfMemory;
723
724 0         goto unlock_out;
725     }
726
727 0     tmp = globus_l_service_engine_instances;
728 0     while (!globus_list_empty(tmp))
729     {
730 0         tmp_engine = globus_list_first(tmp);
731
732 0         contact_array[i] = globus_libc_strdup(tmp_engine->contact);
733
734 0         if (contact_array[i] == NULL)
735         {
736 0             result = GlobusServiceEngineErrorOutOfMemory;
737
738 0             for (i--; i >= 0; i--)
739             {
740 0                 free(contact_array[i]);
741             }
742
743 0             free(contact_array);
744
745 0             contact_array = NULL;
746 0             i = 0;
747
748 0             goto unlock_out;
749         }
750
751 0         i++;
752
753 0         tmp = globus_list_rest(tmp);
754     }
755
756 unlock_out:
757 0     GlobusServiceEngineExtensionUnlock();
758
759 0     *contacts = contact_array;
760 0     *contacts_length = i;
761
762 0     return GLOBUS_SUCCESS;
763 }
764 /* globus_service_get_engine_contacts() */
765
766 globus_result_t
767 globus_service_engine_lookup(
768     const char *                        contact,
769     globus_service_engine_t *           engine)
770 3720 {
771 3720     globus_url_t                        url;
772 3720     char                                hostname[MAXHOSTNAMELEN];
773 3720     int                                 rc;
774 3720     globus_result_t                     result = GLOBUS_SUCCESS;
775 3720     globus_list_t *                     tmp;
776 3720     struct hostent                      hostent;
777 3720     char                                hostent_buffer[512];
778 3720     char *                              url_hostname;
779 3720     int                                 h_errnov;
780
781 3720     *engine = NULL;
782
783 3720     rc = globus_url_parse(contact, &url);
784
785 3720     if (rc != GLOBUS_SUCCESS)
786     {
787 0         goto out;
788     }
789
790 3720     rc = globus_libc_gethostname(hostname, sizeof(hostname));
791
792 3720     if (globus_libc_gethostbyname_r(
793                 url.host,
794                 &hostent,
795                 hostent_buffer,
796                 sizeof(hostent_buffer),
797                 &h_errnov) != NULL)
798     {
799 3720         url_hostname = hostent.h_name;
800     }
801     else
802     {
803 0         url_hostname = url.host;
804     }
805
806 3720     if (strlen(hostname) != strlen(url_hostname) ||
807         globus_libc_strncasecmp(hostname, url_hostname, strlen(hostname)))
808     {
809 2777         goto destroy_url_out;
810     }
811
812 2777     GlobusServiceEngineExtensionLock();
813 2777     tmp = globus_list_search_pred(
814             globus_l_service_engine_instances,
815             globus_l_service_engine_is_equal,
816             &url);
817
818 2777     if (tmp != NULL)
819     {
820 453         *engine = globus_list_first(tmp);
821     }
822 2777     GlobusServiceEngineExtensionUnlock();
823 destroy_url_out:
824 3720     globus_url_destroy(&url);
825 out:
826 3720     return result;
827 }
828 /* globus_service_engine_lookup() */
829
830
831 globus_result_t
832 globus_service_engine_get_contact(
833     const globus_service_engine_t       engine,
834     char **                             contact)
835 236 {
836 236     *contact = globus_libc_strdup(engine->contact);
837 236     return GLOBUS_SUCCESS;
838 }
839
840 void
841 globus_service_engine_destroy(
842     globus_service_engine_t             engine)
843 137 {
844 137     int                                 res;
845 137     globus_list_t *                     tmp;
846 137     GlobusFuncName(globus_service_engine_destroy);
847 137     GlobusServiceEngineDebugEnter();
848
849 137     GlobusServiceEngineExtensionLock();
850 137     tmp = globus_list_search(
851                 globus_l_service_engine_instances,
852                 engine);
853
854 137     if (tmp != NULL)
855     {
856 137         globus_list_remove(&globus_l_service_engine_instances, tmp);
857     }
858     else
859     {
860 0         GlobusServiceEngineExtensionUnlock();
861 0         return;
862     }
863     
864 137     GlobusServiceEngineExtensionUnlock();
865 137     if(engine->handlers)
866     {
867 137         globus_handler_chain_destroy(engine->handlers);
868     }
869
870 137     if(engine->contact)
871     {
872 137         free(engine->contact);
873     }
874
875 137     if(engine->server)
876     {
877 137         globus_xio_server_close(engine->server);
878     }
879
880 137     res = globus_mutex_destroy(&engine->mutex);
881 137     globus_assert_string((res == 0), "Failed to destroy mutex");
882
883 137     if(engine->attrs)
884     {
885 137         globus_soap_message_attr_destroy(engine->attrs);
886     }
887     
888 137     free(engine);
889 137     GlobusServiceEngineDebugExit();
890 }
891
892 static
893 void
894 globus_l_service_session_callback_handle_destroy(
895     globus_l_session_callback_handle_t * callback_handle)
896 1248 {
897 1248     if(callback_handle)
898     {
899 1248         if(callback_handle->result)
900         {
901 0             globus_object_free(globus_error_get(callback_handle->result));
902         }
903
904 1248         if(callback_handle->callback_result)
905         {
906 92             globus_object_free(
907                 globus_error_get(callback_handle->callback_result));
908         }
909                
910 1248         free(callback_handle);
911     }
912 }
913
914 static
915 void
916 globus_l_service_engine_open_callback(
917     globus_xio_handle_t                 handle,
918     globus_result_t                     result,
919     void *                              user_arg)
920 1252 {
921 1252     globus_l_session_callback_handle_t *callback_handle = NULL;
922 1252     static globus_byte_t                buffer[1];
923 1252     GlobusFuncName(globus_l_service_engine_open_callback);
924 1252     GlobusServiceEngineDebugEnter();
925
926 1252     callback_handle = (globus_l_session_callback_handle_t *) user_arg;
927
928 1252     GlobusServiceEngineLock(callback_handle->engine);
929 1252     if(result == GLOBUS_SUCCESS)
930     {
931 1252         if (callback_handle->engine->https)
932         {
933 462             gss_name_t                  peer_name = NULL;
934
935             /* Set Security attribute related to our peer */
936 462             result = globus_xio_handle_cntl(
937                     handle,
938                     globus_i_soap_message_gsi_driver,
939                     GLOBUS_XIO_GSI_GET_PEER_NAME,
940                     &peer_name);
941
942 462             if (result != GLOBUS_SUCCESS)
943             {
944 0                 goto cleanup;
945             }
946 462             result = globus_soap_message_handle_set_attr(
947                 callback_handle->message,
948                 GLOBUS_SOAP_MESSAGE_PEER_IDENTITY_KEY,
949                 NULL,
950                 NULL,
951                 (void *) peer_name);
952 462             if (result != GLOBUS_SUCCESS)
953             {
954 0                 goto cleanup;
955             }
956         }
957 1252         result = globus_xio_register_read(handle,
958                 buffer,
959                 0,
960                 0,
961                 NULL,
962                 globus_l_service_engine_request_ready_callback,
963                 callback_handle);
964     }
965
966 cleanup:
967 1252     if (result != GLOBUS_SUCCESS)
968     {
969 0         globus_soap_message_handle_destroy(callback_handle->message);
970 0         callback_handle->message = NULL;
971 0         callback_handle->callback(
972             result, callback_handle->engine,
973             callback_handle->message, callback_handle->args);
974     }
975 1252     GlobusServiceEngineUnlock(callback_handle->engine);
976     
977 1252     GlobusServiceEngineDebugExit();
978 }
979
980 static
981 globus_result_t
982 globus_l_service_engine_service_module_copy(
983     void **                             ne,
984     const void *                        e)
985 2786 {
986 2786     globus_extension_reference((globus_extension_handle_t)e);
987 2786     *ne = (void *) e;
988 2786     return GLOBUS_SUCCESS;
989 }
990
991 static
992 void
993 globus_l_service_engine_service_module_destroy(
994     void *                              e)
995 2786 {
996 2786     globus_extension_release((globus_extension_handle_t)e);
997 }
998
999 static
1000 void
1001 globus_l_service_engine_request_ready_callback(
1002     globus_xio_handle_t                 handle,
1003     globus_result_t                     result,
1004     globus_byte_t *                     buffer,
1005     globus_size_t                       len,
1006     globus_size_t                       nbytes,
1007     globus_xio_data_descriptor_t        data_desc,
1008     void *                              user_arg)
1009 3581 {
1010 3581     char *                              service_path = NULL;
1011 3581     globus_xio_http_header_t *          soap_action = NULL;
1012 3581     globus_xio_http_header_t *          content_type = NULL;
1013 3581     globus_xio_http_header_t *          connection = NULL;
1014 3581     char *                              method = NULL;
1015 3581     char *                              uri = NULL;
1016 3581     globus_xio_http_version_t           http_version;
1017 3581     globus_hashtable_t                  headers;
1018     
1019 3581     globus_l_session_callback_handle_t * callback_handle = NULL;
1020 3581     GlobusFuncName(globus_l_service_engine_request_ready_callback);
1021 3581     GlobusServiceEngineDebugEnter();
1022
1023 3581     callback_handle = (globus_l_session_callback_handle_t *) user_arg;
1024
1025 3581     if (result == GLOBUS_SUCCESS)
1026     {
1027 2450         result = globus_xio_data_descriptor_cntl(
1028                 data_desc,
1029                 globus_i_soap_message_http_driver,
1030                 GLOBUS_XIO_HTTP_GET_REQUEST,
1031                 &method,
1032                 &uri,
1033                 &http_version,
1034                 &headers);
1035
1036     }
1037
1038 3581     if (method == NULL || result != GLOBUS_SUCCESS)
1039     {
1040         /* No more requests */
1041 1157         if (callback_handle->process_callback != NULL)
1042         {
1043 1157             callback_handle->state = GLOBUS_L_SERVICE_ENGINE_RESPONSE_CLOSE;
1044 1157             globus_soap_message_handle_set_attr(
1045                 callback_handle->message,
1046                 GLOBUS_SOAP_MESSAGE_CONNECTION_KEY,
1047                 globus_soap_message_attr_copy_string,
1048                 globus_libc_free,
1049                 (void *) "close");
1050         }
1051     }
1052 2424     else if(!strcmp(method, "POST"))
1053     {
1054 2424         globus_service_descriptor_t *   service_desc;
1055
1056 2424         soap_action = (globus_xio_http_header_t *)
1057         globus_hashtable_lookup(&headers, (void *) SOAP_ACTION_HEADER);
1058 2424         if(!soap_action)
1059         {
1060 0             GlobusServiceEngineDebugPrintf(
1061                 GLOBUS_L_SERVICE_ENGINE_DEBUG_DEBUG, 
1062                 ("Service request: %s does not "
1063                  "have a SOAPAction header entry\n",
1064                  uri));
1065         }
1066
1067 2424         content_type = (globus_xio_http_header_t *)
1068         globus_hashtable_lookup(&headers, (void *) CONTENT_TYPE_HEADER);
1069 2424         if(!content_type || !content_type->value || 
1070            !strstr(content_type->value, "text/xml"))
1071         {
1072 0             result = GlobusServiceEngineErrorUnsupportedMediaType(
1073                 content_type->value);
1074 0             goto exit;
1075         }
1076 2424         if (http_version != GLOBUS_XIO_HTTP_VERSION_1_0)
1077         {
1078             /*
1079              * Assume persistent connection with HTTP/1.1 unless told 
1080              * otherwise
1081              */
1082 2424             connection = globus_hashtable_lookup(
1083                     &headers,
1084                     (void *) "Connection");
1085 2424             if (connection && connection->value &&
1086                         strstr(connection->value, "close"))
1087             {
1088 0                 result = globus_soap_message_handle_set_attr(
1089                     callback_handle->message,
1090                     GLOBUS_SOAP_MESSAGE_CONNECTION_KEY,
1091                     globus_soap_message_attr_copy_string,
1092                     globus_libc_free,
1093                     (void *) "close");
1094             }
1095         }
1096         else
1097         {
1098 0             result = globus_soap_message_handle_set_attr(
1099                 callback_handle->message,
1100                 GLOBUS_SOAP_MESSAGE_CONNECTION_KEY,
1101                 globus_soap_message_attr_copy_string,
1102                 globus_libc_free,
1103                 (void *) "close");
1104         }
1105 2424         if (result != GLOBUS_SUCCESS)
1106         {
1107 0             goto exit;
1108         }
1109
1110 2424         result = globus_i_service_engine_get_descriptor(uri, callback_handle->message, &service_desc);
1111
1112 2424         if (result != GLOBUS_SUCCESS)
1113         {
1114 91             goto exit;
1115         }
1116 2333         if(soap_action)
1117         {
1118 2333             result = globus_soap_message_handle_set_attr(
1119                 callback_handle->message,
1120                 GLOBUS_SOAP_MESSAGE_SOAP_ACTION_KEY,
1121                 globus_soap_message_attr_copy_string,
1122                 globus_libc_free,
1123                 (void *)soap_action->value);
1124 2333             if(result != GLOBUS_SUCCESS)
1125             {
1126 0                 result = GlobusServiceEngineErrorReadRequestFailed(result);
1127 0                 goto exit;
1128             }
1129         }
1130     }
1131     else
1132     {
1133 0         result = GlobusServiceEngineErrorMethodNotAllowed(method);
1134 0         goto exit;
1135     }
1136
1137     /*
1138      * If we are reading a 2nd message, we'll start the session callback
1139      * immediately and skip the session started callback below.
1140      */
1141 3490     if (callback_handle->state ==
1142             GLOBUS_L_SERVICE_ENGINE_REQUEST_READ_ANOTHER_MESSAGE ||
1143         callback_handle->state ==
1144             GLOBUS_L_SERVICE_ENGINE_RESPONSE_CLOSE)
1145     {
1146 2329         result = globus_callback_register_oneshot(
1147             NULL,
1148             &globus_i_reltime_zero,
1149             globus_l_service_session_callback,
1150             callback_handle);
1151 2329         if(result == GLOBUS_SUCCESS)
1152         {
1153 2329             goto no_callback_exit;
1154         }
1155         else
1156         {
1157 0             result = GlobusServiceEngineErrorFailedRequestProcess(
1158                 result, "Failed to register callback to invoke operation");
1159             goto exit;
1160         }
1161     }
1162  exit:
1163
1164 1252     if(result != GLOBUS_SUCCESS)
1165     {
1166 91         callback_handle->result = result;
1167 91         globus_soap_message_handle_set_attr(
1168             callback_handle->message,
1169             GLOBUS_SOAP_MESSAGE_CONNECTION_KEY,
1170             globus_soap_message_attr_copy_string,
1171             globus_libc_free,
1172             (void *) "close");
1173     }
1174
1175     /*
1176      * Session started callback, which will register a new accept and then
1177      * kick off process session for this session
1178      */
1179 1252     callback_handle->callback(
1180         result, callback_handle->engine,
1181         callback_handle->message, callback_handle->args);
1182
1183 no_callback_exit:
1184
1185 3581     if(service_path)
1186     {
1187 0         free(service_path);
1188     }
1189
1190
1191 3581     GlobusServiceEngineDebugExit();
1192 }
1193
1194 static
1195 void
1196 globus_l_service_engine_accept_callback(
1197     globus_xio_server_t                 server,
1198     globus_xio_handle_t                 new_handle,
1199     globus_result_t                     result,
1200     void *                              user_args)
1201 1396 {
1202 1396     char *                              peer_contact = NULL;
1203 1396     globus_xio_attr_t                   attr;
1204 1396     globus_soap_message_handle_t        message = NULL;
1205 1396     globus_l_session_callback_handle_t * callback_handle;
1206 1396     GlobusFuncName(globus_l_service_engine_accept_callback);
1207 1396     GlobusServiceEngineDebugEnter();
1208     
1209 1396     callback_handle = (globus_l_session_callback_handle_t *) user_args;
1210
1211 1396     if(result != GLOBUS_SUCCESS)
1212     {
1213 144         goto exit;
1214     }
1215
1216 1252     result = globus_soap_message_handle_init(&message, new_handle);
1217 1252     if(result != GLOBUS_SUCCESS)
1218     {
1219 0         result = GlobusServiceEngineErrorFailedRequest(result);
1220 0         goto exit;
1221     }
1222 1252     GlobusServiceEngineLock(callback_handle->engine);
1223 1252     result = globus_soap_message_handle_set_attrs(
1224         message,
1225         callback_handle->engine->attrs);
1226 1252     if(result != GLOBUS_SUCCESS)
1227     {
1228 0         GlobusServiceEngineUnlock(callback_handle->engine);
1229 0         result = GlobusServiceEngineErrorFailedRequest(result);
1230 0         goto exit;
1231     }
1232 1252     result = globus_soap_message_handle_set_attr(
1233         message,
1234         GLOBUS_I_SESSION_HANDLE_KEY,
1235         NULL,
1236         NULL,
1237         callback_handle);
1238 1252     if(result != GLOBUS_SUCCESS)
1239     {
1240 0         GlobusServiceEngineUnlock(callback_handle->engine);
1241 0         result = GlobusServiceEngineErrorFailedRequest(result);
1242 0         goto exit;
1243     }
1244
1245 1252     GlobusServiceEngineUnlock(callback_handle->engine);
1246
1247 1252     callback_handle->message = message;
1248
1249 1252     result = globus_xio_attr_init(&attr);
1250 1252     if(result != GLOBUS_SUCCESS)
1251     {
1252 0         result = GlobusServiceEngineErrorFailedRequest(result);
1253 0         goto exit;
1254     }
1255
1256 1252     result = globus_xio_handle_cntl(
1257         new_handle, globus_i_soap_message_tcp_driver,
1258         GLOBUS_XIO_TCP_GET_REMOTE_CONTACT,
1259         &peer_contact);
1260 1252     if(result != GLOBUS_SUCCESS)
1261     {
1262 0         result = GlobusServiceEngineErrorFailedRequest(result);
1263 0         goto exit;
1264     }
1265
1266 1252     result = globus_xio_register_open(
1267         new_handle, peer_contact, attr, 
1268         globus_l_service_engine_open_callback, callback_handle);
1269 1252     if(result != GLOBUS_SUCCESS)
1270     {
1271 0         result = GlobusServiceEngineErrorFailedRequest(result);
1272         goto exit;
1273     }
1274
1275  exit:
1276 1396     if (peer_contact != NULL)
1277     {
1278 1252         globus_libc_free(peer_contact);
1279     }
1280
1281 1396     if(result != GLOBUS_SUCCESS)
1282     {
1283 144         callback_handle->callback(result, callback_handle->engine, 
1284                                   message, callback_handle->args);
1285 144         free(callback_handle);
1286 144         if(message)
1287         {
1288 0             globus_soap_message_handle_destroy(message);
1289         }
1290     }
1291
1292 1396     GlobusServiceEngineDebugExit();
1293 }
1294
1295 globus_result_t
1296 globus_service_engine_register_session(
1297     globus_service_engine_t                engine,
1298     globus_service_session_callback_func_t callback,
1299     void *                                 user_args)
1300 1402 {
1301 1402     globus_l_session_callback_handle_t * callback_handle = NULL;
1302 1402     globus_result_t                     result = GLOBUS_SUCCESS;
1303 1402     GlobusFuncName(globus_service_engine_register_session);
1304 1402     GlobusServiceEngineDebugEnter();
1305
1306 1402     callback_handle = calloc(1, sizeof(globus_l_session_callback_handle_t));
1307 1402     if(!callback_handle)
1308     {
1309 0         result = GlobusServiceEngineErrorOutOfMemory;
1310 0         goto exit;
1311     }
1312
1313 1402     callback_handle->callback = callback;
1314 1402     callback_handle->args = user_args;
1315 1402     callback_handle->engine = engine;
1316 1402     callback_handle->faulting = GLOBUS_FALSE;
1317
1318 1402     result = globus_xio_server_register_accept(
1319         engine->server,
1320         globus_l_service_engine_accept_callback,
1321         callback_handle);
1322 1402     if(result != GLOBUS_SUCCESS)
1323     {
1324 0         result = GlobusServiceEngineErrorAcceptFailed(result);
1325         goto exit;
1326     }
1327
1328  exit:
1329
1330 1402     GlobusServiceEngineDebugExit();
1331 1402     return result;
1332 }
1333
1334 static
1335 void
1336 globus_l_service_session_result_callback(
1337     globus_result_t                    result,
1338     void *                             args)
1339 36370 {
1340 36370     globus_l_session_callback_handle_t * callback_handle;
1341 36370     GlobusFuncName(globus_l_service_session_result_callback);
1342 36370     GlobusServiceEngineDebugEnter();
1343
1344 36370     callback_handle = (globus_l_session_callback_handle_t *) args;
1345 36370     callback_handle->result = result;
1346
1347 36370     globus_l_service_session_callback(callback_handle);
1348
1349 36370     GlobusServiceEngineDebugExit();
1350 }
1351
1352 static
1353 void
1354 globus_l_service_session_callback(
1355     void *                              args)
1356 42285 {
1357 42285     globus_result_t                      result = GLOBUS_SUCCESS;
1358 42285     globus_service_descriptor_t *        service_desc = NULL;
1359 42285     globus_extension_handle_t            ext;
1360 42285     globus_l_session_callback_handle_t * callback_handle;
1361 42285     globus_service_operation_descriptor_t * op_desc = NULL;
1362 42285     xsd_QName *                          operation_name = NULL;
1363 42285     xsd_QName *                          header_element = NULL;
1364 42285     xsd_int                              must = 0;
1365 42285     char *                               connection;
1366 42285     globus_xio_handle_t                  xio_handle;
1367 42285     static globus_byte_t                 buffer[1];
1368 42285     GlobusFuncName(globus_l_service_session_callback);
1369 42285     GlobusServiceEngineDebugEnter();
1370
1371 42285     callback_handle = (globus_l_session_callback_handle_t *) args;
1372
1373 42285     if(callback_handle->result != GLOBUS_SUCCESS)
1374     {
1375 91         if(!callback_handle->faulting)
1376         {
1377 0             result = callback_handle->result;
1378 0             goto error_send_fault;
1379         }
1380         else
1381         {
1382 91             char * errstr;
1383
1384 91             errstr = globus_error_print_friendly(
1385                     globus_error_peek(
1386                         callback_handle->result));
1387
1388 91             GlobusServiceEngineDebugPrintf(
1389                 GLOBUS_L_SERVICE_ENGINE_DEBUG_DEBUG,
1390                 ("error occurred while sending a fault: %s\n", 
1391                  errstr));
1392
1393 91             free(errstr);
1394
1395 91             callback_handle->result = GLOBUS_SUCCESS;
1396         }
1397     }
1398
1399 42285     GlobusServiceEngineDebugPrintf(
1400         GLOBUS_L_SERVICE_ENGINE_DEBUG_DEBUG,
1401         ("STATE: %s\n", 
1402  globus_l_service_engine_state_strings[callback_handle->state]));
1403
1404 42285     switch(callback_handle->state)
1405     {
1406
1407     case GLOBUS_L_SERVICE_ENGINE_REQUEST_READ_ANOTHER_MESSAGE:
1408 1172         result = globus_soap_message_get_transport_handle(
1409             callback_handle->message,
1410             &xio_handle);
1411 1172         if (result != GLOBUS_SUCCESS)
1412         {
1413 0             goto error_send_fault;
1414         }
1415 1172         result = globus_xio_handle_cntl(
1416                 xio_handle,
1417                 globus_i_soap_message_buffer_driver,
1418                 GLOBUS_XIO_BUFFER_ENABLE_READ_BUFFERING);
1419 1172         if (result != GLOBUS_SUCCESS)
1420         {
1421 0             goto error_send_fault;
1422         }
1423 1172         result = globus_i_soap_message_reset_reader(callback_handle->message);
1424 1172         if (result != GLOBUS_SUCCESS)
1425         {
1426 0             goto error_send_fault;
1427         }
1428         /* FALLSTHROUGH */
1429     case GLOBUS_L_SERVICE_ENGINE_REQUEST_READ_MESSAGE:
1430
1431 2333         callback_handle->state =
1432         GLOBUS_L_SERVICE_ENGINE_REQUEST_INIT_SERVICE_HANDLERS;
1433
1434 2333         if(callback_handle->result != GLOBUS_SUCCESS)
1435         {
1436 0             result = callback_handle->result;
1437 0             goto error_send_fault;
1438         }
1439
1440 2333         result = globus_soap_message_register_read_request(
1441             callback_handle->message,
1442             globus_l_service_session_result_callback,
1443             callback_handle);
1444 2333         if(result != GLOBUS_SUCCESS)
1445         {
1446 0             goto error_send_fault;
1447         }
1448
1449 2333         break;
1450
1451     case GLOBUS_L_SERVICE_ENGINE_REQUEST_INIT_SERVICE_HANDLERS:
1452
1453 2333 callback_handle->state =
1454 GLOBUS_L_SERVICE_ENGINE_REQUEST_INIT_HANDLERS;
1455
1456 2333 if(callback_handle->result != GLOBUS_SUCCESS)
1457 {
1458 0     result = callback_handle->result;
1459 0     goto error_send_fault;
1460 }
1461
1462 2333 ext =
1463         (globus_extension_handle_t)
1464         globus_soap_message_handle_get_attr(
1465             callback_handle->message,
1466             GLOBUS_I_SERVICE_DESCRIPTOR_KEY);
1467 2333         globus_assert_string(
1468             ext, "No SERVICE DESCRIPTOR attribute found!");
1469                 
1470 2333         service_desc = (globus_service_descriptor_t *) 
1471         globus_extension_reference(ext);
1472         
1473 2333         globus_assert_string(
1474             service_desc, "No SERVICE DESCRIPTOR attribute found!");
1475         
1476 2333         GlobusSoapMessageDebugServiceLock(service_desc);
1477 2333         if(service_desc->handlers)
1478         {
1479 0     globus_handler_chain_register_invoke(
1480     service_desc->handlers,
1481     GLOBUS_HANDLER_TYPE_REQUEST_INIT,
1482     callback_handle->message,
1483     globus_l_service_session_result_callback,
1484     callback_handle);
1485         
1486 0             GlobusSoapMessageDebugServiceUnlock(service_desc);
1487 0     service_desc = NULL;
1488 0     globus_extension_release(ext);
1489 0     break;
1490 }
1491 2333         GlobusSoapMessageDebugServiceUnlock(service_desc);
1492 2333 service_desc = NULL;
1493 2333 globus_extension_release(ext);
1494     
1495     case GLOBUS_L_SERVICE_ENGINE_REQUEST_INIT_HANDLERS:
1496
1497 2333 callback_handle->state =
1498 GLOBUS_L_SERVICE_ENGINE_START_DESERIALIZE;
1499
1500 2333 if(callback_handle->result != GLOBUS_SUCCESS)
1501 {
1502 0     result = callback_handle->result;
1503 0     goto error_send_fault;
1504 }
1505
1506 2333         GlobusServiceEngineLock(callback_handle->engine);
1507 2333         if(callback_handle->engine->handlers)
1508         {
1509 2333             globus_handler_chain_register_invoke(
1510                 callback_handle->engine->handlers,
1511 GLOBUS_HANDLER_TYPE_REQUEST_INIT,
1512                 callback_handle->message,
1513                 globus_l_service_session_result_callback,
1514                 callback_handle);
1515 2333             GlobusServiceEngineUnlock(callback_handle->engine);
1516 2333     break;
1517         }
1518 0         GlobusServiceEngineUnlock(callback_handle->engine);
1519
1520     case GLOBUS_L_SERVICE_ENGINE_START_DESERIALIZE:
1521
1522 2333         callback_handle->state = 
1523         GLOBUS_L_SERVICE_ENGINE_TRIGGER_INVOKE_HANDLERS;
1524
1525 2333         if(callback_handle->result != GLOBUS_SUCCESS)
1526         {
1527 0             result = callback_handle->result;
1528 0             goto error_send_fault;
1529         }
1530
1531 2333         result = globus_soap_message_deserialize_envelope(
1532             callback_handle->message);
1533 2333         if(result != GLOBUS_SUCCESS)
1534         {
1535 0             goto error_send_fault;
1536         }
1537
1538 2333         result = globus_soap_message_deserialize_element_begin_close(
1539             callback_handle->message);
1540 2333         if(result != GLOBUS_SUCCESS)
1541         {
1542 0             goto error_send_fault;
1543         }
1544
1545 2333         result = globus_soap_message_deserialize_header(
1546             callback_handle->message);
1547 2333         if(result != GLOBUS_SUCCESS)
1548         {
1549 0             if(GlobusSoapMessageStatusElementNotFoundCheck(result))
1550             {
1551 0                 globus_soap_message_deserialize_push_element(
1552                     callback_handle->message);
1553 0                 result = GLOBUS_SUCCESS;
1554 0                 callback_handle->state = 
1555                 GLOBUS_L_SERVICE_ENGINE_REQUEST_HEADER_FAILED;
1556 0                 callback_handle->result = result;
1557 0                 globus_l_service_session_callback(
1558                     callback_handle);
1559 0                 break;
1560             }
1561
1562 13917             goto error_send_fault;
1563         }
1564
1565     case GLOBUS_L_SERVICE_ENGINE_TRIGGER_INVOKE_HANDLERS:
1566
1567 13917         callback_handle->state = 
1568         GLOBUS_L_SERVICE_ENGINE_TRIGGER_INVOKE_HANDLERS;
1569
1570 13917         if(callback_handle->result != GLOBUS_SUCCESS)
1571         {
1572 0             result = callback_handle->result;
1573 0             goto error_send_fault;
1574         }
1575
1576 13917         xsd_QName_init(&header_element);
1577         
1578 13917         result = globus_soap_message_deserialize_element_unknown(
1579             callback_handle->message,
1580             header_element);
1581 13917         if(result != GLOBUS_SUCCESS)
1582         {
1583 2333             if(!GlobusSoapMessageStatusFailedElementCheck(result))
1584             {
1585 0                 xsd_QName_destroy(header_element);
1586 0                 goto error_send_fault;
1587             }
1588             else
1589             {
1590 2333                 callback_handle->state = 
1591                 GLOBUS_L_SERVICE_ENGINE_REQUEST_DESERIALIZE;
1592 2333                 globus_callback_register_oneshot(
1593                     NULL,
1594                     &globus_i_reltime_zero,
1595                     globus_l_service_session_callback,
1596                     (void *)callback_handle);
1597 2333                 xsd_QName_destroy(header_element);
1598 2333                 break;
1599             }
1600         }
1601
1602 11584         result = globus_soap_message_deserialize_int_attribute(
1603             callback_handle->message,
1604             &soap_mustUnderstand_qname,
1605             &must);
1606 11584         if(result == GLOBUS_SUCCESS && (must == 1))
1607         {
1608 0             globus_soap_message_add_required_header_element(
1609                 callback_handle->message,
1610                 header_element);
1611         }
1612 11584         else if(result != GLOBUS_SUCCESS &&
1613                 !GlobusSoapMessageStatusAttributeNotFoundCheck(result))
1614         {
1615 0             xsd_QName_destroy(header_element);
1616 0             goto error_send_fault;
1617         }
1618
1619 11584         globus_soap_message_deserialize_push_element(callback_handle->message);
1620
1621 11584 ext =
1622         (globus_extension_handle_t)
1623         globus_soap_message_handle_get_attr(
1624             callback_handle->message,
1625             GLOBUS_I_SERVICE_DESCRIPTOR_KEY);
1626 11584         globus_assert_string(
1627             ext, "No SERVICE DESCRIPTOR attribute found!");
1628                 
1629 11584         service_desc = (globus_service_descriptor_t *) 
1630         globus_extension_reference(ext);
1631         
1632 11584         globus_assert_string(
1633             service_desc, "No SERVICE DESCRIPTOR attribute found!");
1634         
1635 11584         GlobusSoapMessageDebugServiceLock(service_desc);
1636 11584         if(service_desc->handlers)
1637         {
1638 0             if(globus_handler_chain_has_trigger(
1639     service_desc->handlers, header_element))
1640     {
1641 0 result = globus_handler_chain_register_trigger(
1642     service_desc->handlers,
1643     callback_handle->message,
1644     header_element,
1645     globus_l_service_session_result_callback,
1646     callback_handle);
1647 0 if(result == GLOBUS_SUCCESS)
1648 {
1649 0     xsd_QName_destroy(header_element);
1650 0                     GlobusSoapMessageDebugServiceUnlock(service_desc);
1651 0     service_desc = NULL;
1652 0     globus_extension_release(ext);
1653 0     break;
1654 }
1655 0 else if(!GlobusHandlerStatusNotTriggeredCheck(result))
1656 {
1657 0     xsd_QName_destroy(header_element);
1658 0                     GlobusSoapMessageDebugServiceUnlock(service_desc);
1659 0     service_desc = NULL;
1660 0     globus_extension_release(ext);
1661 0     goto error_send_fault;
1662 }
1663     }
1664         }
1665 11584         GlobusSoapMessageDebugServiceUnlock(service_desc);
1666 11584         service_desc = NULL;
1667 11584         globus_extension_release(ext);
1668
1669 11584         GlobusServiceEngineLock(callback_handle->engine);
1670 11584         if(callback_handle->engine->handlers)
1671         {
1672 11584             result = globus_handler_chain_register_trigger(
1673                 callback_handle->engine->handlers,
1674                 callback_handle->message,
1675                 header_element,
1676                 globus_l_service_session_result_callback,
1677                 callback_handle);
1678 11584             if(result == GLOBUS_SUCCESS)
1679             {
1680 11584                 xsd_QName_destroy(header_element);
1681 11584                 GlobusServiceEngineUnlock(callback_handle->engine);
1682 11584                 break;
1683             }
1684 0             else if(!GlobusHandlerStatusNotTriggeredCheck(result))
1685             {
1686 0                 xsd_QName_destroy(header_element);
1687 0                 GlobusServiceEngineUnlock(callback_handle->engine);
1688 0                 goto error_send_fault;
1689             }
1690         }
1691 0         GlobusServiceEngineUnlock(callback_handle->engine);
1692         
1693 0         xsd_QName_destroy(header_element);
1694 0         result = globus_soap_message_deserialize_skip(
1695             callback_handle->message);
1696 0         if(result != GLOBUS_SUCCESS)
1697         {
1698 0             goto error_send_fault;
1699         }
1700
1701 0         globus_callback_register_oneshot(
1702             NULL,
1703             &globus_i_reltime_zero,
1704             globus_l_service_session_callback,
1705             (void *)callback_handle);
1706 0         break;
1707
1708     case GLOBUS_L_SERVICE_ENGINE_REQUEST_DESERIALIZE:
1709         
1710 2333         if(callback_handle->result != GLOBUS_SUCCESS)
1711         {
1712 0             result = callback_handle->result;
1713 0             goto error_send_fault;
1714         }
1715
1716 2333 result = globus_soap_message_check_required_headers(
1717     callback_handle->message);
1718 2333 if(result != GLOBUS_SUCCESS)
1719 {
1720 0     goto error_send_fault;
1721 }
1722
1723 2333         result = globus_soap_message_deserialize_header_end(
1724             callback_handle->message);
1725 2333         if(result != GLOBUS_SUCCESS)
1726         {
1727 0             goto error_send_fault;
1728         }
1729
1730     case GLOBUS_L_SERVICE_ENGINE_REQUEST_HEADER_FAILED:
1731
1732 2333         callback_handle->state = 
1733         GLOBUS_L_SERVICE_ENGINE_REQUEST_INVOKE_HANDLERS;
1734
1735 2333         if(callback_handle->result != GLOBUS_SUCCESS)
1736         {
1737 0             result = callback_handle->result;
1738 0             goto error_send_fault;
1739         }
1740
1741 2333         result = globus_soap_message_deserialize_body(
1742             callback_handle->message);
1743 2333         if(result != GLOBUS_SUCCESS)
1744         {
1745 0             goto error_send_fault;
1746         }
1747
1748 2333         xsd_QName_init(&operation_name);
1749
1750 2333         result = globus_soap_message_deserialize_element_unknown(
1751             callback_handle->message, operation_name);
1752 2333         if(result != GLOBUS_SUCCESS)
1753         {
1754 0             goto error_send_fault;
1755         }
1756
1757 2333         result = globus_soap_message_handle_set_attr(
1758             callback_handle->message,
1759             GLOBUS_I_SERVICE_OPERATION_QNAME_KEY,
1760             xsd_QName_copy_wrapper,
1761             xsd_QName_destroy_wrapper,
1762             operation_name);
1763 2333         if(result != GLOBUS_SUCCESS)
1764         {
1765 0             goto error_send_fault;
1766         }
1767
1768 2333         globus_soap_message_deserialize_push_element(
1769             callback_handle->message);
1770 2333         if(result != GLOBUS_SUCCESS)
1771         {
1772 0             goto error_send_fault;
1773         }
1774
1775 2333         ext = 
1776         (globus_extension_handle_t)
1777         globus_soap_message_handle_get_attr(
1778             callback_handle->message,
1779             GLOBUS_I_SERVICE_DESCRIPTOR_KEY);
1780 2333         globus_assert_string(
1781             ext, "No SERVICE DESCRIPTOR attribute found!");
1782
1783 2333         service_desc = (globus_service_descriptor_t *) 
1784         globus_extension_reference(ext);
1785
1786 2333         globus_assert_string(
1787             service_desc, "No SERVICE DESCRIPTOR attribute found!");
1788
1789         /* we use qn to map to operation deserialize function */
1790 2333         GlobusSoapMessageDebugServiceLock(service_desc);
1791 2333         if(service_desc->op_mapper)
1792         {
1793 2333             op_desc = (globus_service_operation_descriptor_t *)
1794             globus_hashtable_lookup(
1795                 &service_desc->op_mapper, 
1796                 (void *)operation_name);
1797         }
1798
1799 2333         if(!op_desc)
1800         {
1801 1             result = GlobusServiceEngineErrorOperationLookupFailed(
1802                 service_desc->name, operation_name);
1803 1             GlobusSoapMessageDebugServiceUnlock(service_desc);
1804 1             service_desc = NULL;
1805 1             globus_extension_release(ext);
1806 1             goto error_send_fault;
1807         }
1808
1809 2332         result = op_desc->deserialize(
1810             callback_handle->engine,
1811             callback_handle->message,
1812             globus_l_service_session_result_callback,
1813             callback_handle);
1814 2332         if(result != GLOBUS_SUCCESS)
1815         {
1816 0             result = GlobusServiceEngineErrorOpDeserializeFailed(
1817                 result, operation_name);
1818 0             GlobusSoapMessageDebugServiceUnlock(service_desc);
1819 0             goto error_send_fault;
1820         }
1821
1822 2332         GlobusSoapMessageDebugServiceUnlock(service_desc);
1823 2332         service_desc = NULL;
1824 2332         globus_extension_release(ext);
1825
1826 2332         xsd_QName_destroy(operation_name);
1827 2332         break;
1828
1829     case GLOBUS_L_SERVICE_ENGINE_REQUEST_INVOKE_HANDLERS:
1830
1831 2332         callback_handle->state = 
1832         GLOBUS_L_SERVICE_ENGINE_REQUEST_INVOKE_SERVICE_HANDLERS;
1833
1834 2332         if(callback_handle->result != GLOBUS_SUCCESS)
1835         {
1836 0             result = callback_handle->result;
1837 0             goto error_send_fault;
1838         }
1839
1840 2332         result = globus_soap_message_deserialize_body_end(
1841             callback_handle->message);
1842 2332         if(result != GLOBUS_SUCCESS)
1843         {
1844 0             goto error_send_fault;
1845         }
1846
1847 2332         result = globus_soap_message_deserialize_envelope_end(
1848             callback_handle->message);
1849 2332         if(result != GLOBUS_SUCCESS)
1850         {
1851 0             goto error_send_fault;
1852         }
1853
1854 2332         GlobusServiceEngineLock(callback_handle->engine);
1855 2332         if(callback_handle->engine->handlers)
1856         {        
1857 2332             globus_handler_chain_register_invoke(
1858                 callback_handle->engine->handlers,
1859                 GLOBUS_HANDLER_TYPE_REQUEST,
1860                 callback_handle->message,
1861                 globus_l_service_session_result_callback,
1862                 callback_handle);
1863 2332             GlobusServiceEngineUnlock(callback_handle->engine);
1864 2332             break;
1865         }
1866 0         GlobusServiceEngineUnlock(callback_handle->engine);
1867
1868     case GLOBUS_L_SERVICE_ENGINE_REQUEST_INVOKE_SERVICE_HANDLERS:
1869
1870 2332         callback_handle->state = 
1871         GLOBUS_L_SERVICE_ENGINE_REQUEST_DESTROY_HANDLERS;
1872
1873 2332         if(callback_handle->result != GLOBUS_SUCCESS)
1874         {
1875 0             result = callback_handle->result;
1876 0             goto error_send_fault;
1877         }
1878
1879 2332         ext =
1880         (globus_extension_handle_t)
1881         globus_soap_message_handle_get_attr(
1882             callback_handle->message,
1883             GLOBUS_I_SERVICE_DESCRIPTOR_KEY);
1884 2332         globus_assert_string(
1885             ext, "No SERVICE DESCRIPTOR attribute found!");
1886         
1887 2332         service_desc = (globus_service_descriptor_t *) 
1888         globus_extension_reference(ext);
1889         
1890 2332         globus_assert_string(
1891             service_desc, "No SERVICE DESCRIPTOR attribute found!");
1892         
1893 2332         GlobusSoapMessageDebugServiceLock(service_desc);
1894 2332         if(service_desc->handlers)
1895         {
1896 0             globus_handler_chain_register_invoke(
1897                 service_desc->handlers,
1898                 GLOBUS_HANDLER_TYPE_REQUEST,
1899                 callback_handle->message,
1900                 globus_l_service_session_result_callback,
1901                 callback_handle);
1902 0             GlobusSoapMessageDebugServiceUnlock(service_desc);
1903 0             service_desc = NULL;
1904 0             globus_extension_release(ext);
1905 0             break;
1906         }
1907 2332         GlobusSoapMessageDebugServiceUnlock(service_desc);
1908 2332         service_desc = NULL;
1909 2332         globus_extension_release(ext);
1910
1911     case GLOBUS_L_SERVICE_ENGINE_REQUEST_DESTROY_HANDLERS:
1912
1913 2332 callback_handle->state = 
1914     GLOBUS_L_SERVICE_ENGINE_REQUEST_DESTROY_SERVICE_HANDLERS;
1915
1916 2332 if(callback_handle->result != GLOBUS_SUCCESS)
1917 {
1918 0     result = callback_handle->result;
1919 0     goto error_send_fault;
1920 }
1921
1922 2332         GlobusServiceEngineLock(callback_handle->engine);
1923 2332         if(callback_handle->engine->handlers)
1924         {
1925 2332             globus_handler_chain_register_invoke(
1926                 callback_handle->engine->handlers,
1927 GLOBUS_HANDLER_TYPE_REQUEST_DESTROY,
1928                 callback_handle->message,
1929                 globus_l_service_session_result_callback,
1930                 callback_handle);
1931 2332             GlobusServiceEngineUnlock(callback_handle->engine);
1932 2332     break;
1933         }
1934 0         GlobusServiceEngineUnlock(callback_handle->engine);
1935
1936     case GLOBUS_L_SERVICE_ENGINE_REQUEST_DESTROY_SERVICE_HANDLERS:
1937
1938 2332         callback_handle->state = 
1939         GLOBUS_L_SERVICE_ENGINE_RESPONSE_INIT_SERVICE_HANDLERS;
1940
1941 2332         if(callback_handle->result != GLOBUS_SUCCESS)
1942         {
1943 0             result = callback_handle->result;
1944 0             goto error_send_fault;
1945 }
1946
1947 2332 ext =
1948         (globus_extension_handle_t)
1949         globus_soap_message_handle_get_attr(
1950             callback_handle->message,
1951             GLOBUS_I_SERVICE_DESCRIPTOR_KEY);
1952 2332         globus_assert_string(
1953             ext, "No SERVICE DESCRIPTOR attribute found!");
1954                 
1955 2332         service_desc = (globus_service_descriptor_t *) 
1956         globus_extension_reference(ext);
1957         
1958 2332         globus_assert_string(
1959             service_desc, "No SERVICE DESCRIPTOR attribute found!");
1960         
1961 2332         GlobusSoapMessageDebugServiceLock(service_desc);
1962 2332         if(service_desc->handlers)
1963         {
1964 0     globus_handler_chain_register_invoke(
1965     service_desc->handlers,
1966     GLOBUS_HANDLER_TYPE_REQUEST_DESTROY,
1967     callback_handle->message,
1968     globus_l_service_session_result_callback,
1969     callback_handle);
1970         
1971 0             GlobusSoapMessageDebugServiceUnlock(service_desc);
1972 0     service_desc = NULL;
1973 0     globus_extension_release(ext);
1974 0     break;
1975 }
1976 2332         GlobusSoapMessageDebugServiceUnlock(service_desc);
1977 2332 service_desc = NULL;
1978 2332 globus_extension_release(ext); 
1979
1980     case GLOBUS_L_SERVICE_ENGINE_RESPONSE_INIT_SERVICE_HANDLERS:
1981
1982 2332 if(callback_handle->result != GLOBUS_SUCCESS)
1983 {
1984 0     result = callback_handle->result;
1985 0     goto callback_exit;
1986 }
1987
1988 2332 callback_handle->state =
1989     GLOBUS_L_SERVICE_ENGINE_RESPONSE_INIT_HANDLERS;
1990
1991 2332         ext =
1992         (globus_extension_handle_t)
1993         globus_soap_message_handle_get_attr(
1994             callback_handle->message,
1995             GLOBUS_I_SERVICE_DESCRIPTOR_KEY);
1996 2332         globus_assert_string(
1997             ext, "No SERVICE DESCRIPTOR attribute found!");
1998
1999 2332         service_desc = 
2000         (globus_service_descriptor_t *) 
2001         globus_extension_reference(ext);
2002         
2003 2332         globus_assert_string(
2004             service_desc, "No SERVICE DESCRIPTOR attribute found!");
2005
2006 2332         GlobusSoapMessageDebugServiceLock(service_desc);
2007 2332         if(service_desc->handlers)
2008         {
2009 0             globus_handler_chain_register_invoke(
2010                 service_desc->handlers,
2011                 GLOBUS_HANDLER_TYPE_RESPONSE_INIT,
2012                 callback_handle->message,
2013                 globus_l_service_session_result_callback,
2014                 callback_handle);
2015 0             GlobusSoapMessageDebugServiceUnlock(service_desc);
2016 0             service_desc = NULL;
2017 0             globus_extension_release(ext);
2018 0             break;
2019         }
2020 2332         GlobusSoapMessageDebugServiceUnlock(service_desc);
2021
2022 2332         service_desc = NULL;
2023 2332         globus_extension_release(ext);
2024
2025     case GLOBUS_L_SERVICE_ENGINE_RESPONSE_INIT_HANDLERS:
2026
2027 2332 if(callback_handle->result != GLOBUS_SUCCESS)
2028 {
2029 0     result = callback_handle->result;
2030 0     goto callback_exit;
2031 }
2032
2033 2332 callback_handle->state =
2034     GLOBUS_L_SERVICE_ENGINE_REQUEST_INVOKE_OPERATION;
2035
2036 2332         GlobusServiceEngineLock(callback_handle->engine);
2037 2332         if(callback_handle->engine->handlers)
2038         {
2039 2332             globus_handler_chain_register_invoke(
2040                 callback_handle->engine->handlers,
2041                 GLOBUS_HANDLER_TYPE_RESPONSE_INIT,
2042                 callback_handle->message,
2043                 globus_l_service_session_result_callback,
2044                 callback_handle);
2045 2332             GlobusServiceEngineUnlock(callback_handle->engine);
2046 2332             break;
2047         }
2048 0         GlobusServiceEngineUnlock(callback_handle->engine);
2049
2050
2051     case GLOBUS_L_SERVICE_ENGINE_REQUEST_INVOKE_OPERATION:
2052         
2053 2332         if(callback_handle->result != GLOBUS_SUCCESS)
2054         {
2055 0             result = callback_handle->result;
2056 0             goto error_send_fault;
2057         }
2058
2059 2332         callback_handle->state = 
2060         GLOBUS_L_SERVICE_ENGINE_RESPONSE_INVOKE_SERVICE_HANDLERS;
2061
2062 2332         operation_name = globus_soap_message_handle_get_attr(
2063             callback_handle->message,
2064             GLOBUS_I_SERVICE_OPERATION_QNAME_KEY);
2065 2332         globus_assert(operation_name);
2066
2067 2332         ext = 
2068         (globus_extension_handle_t)
2069         globus_soap_message_handle_get_attr(
2070             callback_handle->message,
2071             GLOBUS_I_SERVICE_DESCRIPTOR_KEY);
2072 2332         globus_assert_string(
2073             ext, "No SERVICE DESCRIPTOR attribute found!");
2074
2075 2332         service_desc = (globus_service_descriptor_t *) 
2076         globus_extension_reference(ext);
2077
2078 2332         globus_assert_string(
2079             service_desc, "No SERVICE DESCRIPTOR attribute found!");
2080
2081         /* we use qn to map to operation deserialize function */
2082 2332         GlobusSoapMessageDebugServiceLock(service_desc);
2083 2332         if(service_desc->op_mapper)
2084         {
2085 2332             op_desc = (globus_service_operation_descriptor_t *)
2086             globus_hashtable_lookup(
2087                 &service_desc->op_mapper, 
2088                 (void *)operation_name);
2089         }
2090
2091 2332         if(!op_desc)
2092         {
2093 0             result = GlobusServiceEngineErrorOperationLookupFailed(
2094                 service_desc->name, operation_name);
2095 0             GlobusSoapMessageDebugServiceUnlock(service_desc);
2096 0             service_desc = NULL;
2097 0             globus_extension_release(ext);
2098 0             goto error_send_fault;
2099         }
2100
2101 2332         result = op_desc->invoke(
2102             callback_handle->engine,
2103             callback_handle->message,
2104             &callback_handle->response,
2105             globus_l_service_session_result_callback,
2106             callback_handle);
2107 2332         if(result != GLOBUS_SUCCESS)
2108         {
2109 0             result = GlobusServiceEngineErrorOpInvokeFailed(
2110                 result, 
2111                 operation_name);
2112 0             GlobusSoapMessageDebugServiceUnlock(service_desc);
2113 0             goto error_send_fault;
2114         }
2115
2116 2332         if(callback_handle->response == GLOBUS_SERVICE_NO_RESPONSE)
2117         {
2118 30             callback_handle->state = GLOBUS_L_SERVICE_ENGINE_RESPONSE_SEND;
2119         }
2120
2121 2332         GlobusSoapMessageDebugServiceUnlock(service_desc);
2122 2332         service_desc = NULL;
2123 2332         globus_extension_release(ext);
2124
2125 2332         break;
2126
2127     case GLOBUS_L_SERVICE_ENGINE_RESPONSE_INVOKE_SERVICE_HANDLERS:
2128      
2129 2302         if(callback_handle->result != GLOBUS_SUCCESS)
2130         {
2131 0             result = callback_handle->result;
2132 0             goto callback_exit;
2133         }
2134         
2135 2302         callback_handle->state = 
2136         GLOBUS_L_SERVICE_ENGINE_RESPONSE_INVOKE_HANDLERS;
2137         
2138 2302         result = globus_soap_message_set_write_position_to_marker(
2139             callback_handle->message, 
2140             GLOBUS_SOAP_MESSAGE_MARKER_HEADER_CONTENT);
2141 2302         if(result != GLOBUS_SUCCESS)
2142         {
2143 0             goto callback_exit;
2144         }
2145
2146 2302         ext =
2147         (globus_extension_handle_t)
2148         globus_soap_message_handle_get_attr(
2149             callback_handle->message,
2150             GLOBUS_I_SERVICE_DESCRIPTOR_KEY);
2151 2302         globus_assert_string(
2152             ext, "No SERVICE DESCRIPTOR attribute found!");
2153
2154 2302         service_desc = 
2155         (globus_service_descriptor_t *) 
2156         globus_extension_reference(ext);
2157         
2158 2302         globus_assert_string(
2159             service_desc, "No SERVICE DESCRIPTOR attribute found!");
2160
2161 2302         GlobusSoapMessageDebugServiceLock(service_desc);
2162 2302         if(service_desc->handlers)
2163         {
2164 0             globus_handler_chain_register_invoke(
2165                 service_desc->handlers,
2166                 GLOBUS_HANDLER_TYPE_RESPONSE,
2167                 callback_handle->message,
2168                 globus_l_service_session_result_callback,
2169                 callback_handle);
2170 0             GlobusSoapMessageDebugServiceUnlock(service_desc);
2171 0             service_desc = NULL;
2172 0             globus_extension_release(ext);
2173 0             break;
2174         }
2175 2302         GlobusSoapMessageDebugServiceUnlock(service_desc);
2176
2177 2302         service_desc = NULL;
2178 2302         globus_extension_release(ext);
2179
2180     case GLOBUS_L_SERVICE_ENGINE_RESPONSE_INVOKE_HANDLERS:
2181         
2182 2394         callback_handle->state =
2183         GLOBUS_L_SERVICE_ENGINE_RESPONSE_DESTROY_SERVICE_HANDLERS;
2184             
2185 2394         if(callback_handle->result != GLOBUS_SUCCESS)
2186         {
2187 0             result = callback_handle->result;
2188 0             goto callback_exit;
2189         }
2190
2191 2394         GlobusServiceEngineLock(callback_handle->engine);
2192 2394         if(callback_handle->engine->handlers)
2193         {
2194 2394             globus_handler_chain_register_invoke(
2195                 callback_handle->engine->handlers,
2196                 GLOBUS_HANDLER_TYPE_RESPONSE,
2197                 callback_handle->message,
2198                 globus_l_service_session_result_callback,
2199                 callback_handle);
2200 2394             GlobusServiceEngineUnlock(callback_handle->engine);
2201 2394             break;
2202         }
2203 0         GlobusServiceEngineUnlock(callback_handle->engine);
2204         
2205     case GLOBUS_L_SERVICE_ENGINE_RESPONSE_DESTROY_SERVICE_HANDLERS:
2206
2207 2394 if(callback_handle->result != GLOBUS_SUCCESS)
2208 {
2209 0     result = callback_handle->result;
2210 0     goto callback_exit;
2211 }
2212
2213 2394 callback_handle->state =
2214     GLOBUS_L_SERVICE_ENGINE_RESPONSE_DESTROY_HANDLERS;
2215
2216 2394         if(callback_handle->response == GLOBUS_SERVICE_NO_RESPONSE)
2217         {
2218 0             result = globus_soap_message_setup_writer(
2219                 callback_handle->message);
2220 0             if(result != GLOBUS_SUCCESS)
2221             {
2222 0                 goto callback_exit;
2223             }
2224         }
2225
2226 2394         ext =
2227         (globus_extension_handle_t)
2228         globus_soap_message_handle_get_attr(
2229             callback_handle->message,
2230             GLOBUS_I_SERVICE_DESCRIPTOR_KEY);
2231
2232         /* If the user passes in an invalid service name, the extension
2233          * handle will be NULL. We'll just skip service-specific handler
2234          * invocation in this case.
2235          */
2236 2394         if (ext != NULL)
2237         {
2238 2303             service_desc = 
2239             (globus_service_descriptor_t *) 
2240             globus_extension_reference(ext);
2241             
2242 2303             globus_assert_string(
2243                 service_desc, "No SERVICE DESCRIPTOR attribute found!");
2244
2245 2303             GlobusSoapMessageDebugServiceLock(service_desc);
2246 2303             if(service_desc->handlers)
2247             {
2248 0                 globus_handler_chain_register_invoke(
2249                     service_desc->handlers,
2250                     GLOBUS_HANDLER_TYPE_RESPONSE_DESTROY,
2251                     callback_handle->message,
2252                     globus_l_service_session_result_callback,
2253                     callback_handle);
2254 0                 GlobusSoapMessageDebugServiceUnlock(service_desc);
2255 0                 service_desc = NULL;
2256 0                 globus_extension_release(ext);
2257 0                 break;
2258             }
2259 2303             GlobusSoapMessageDebugServiceUnlock(service_desc);
2260
2261 2303             service_desc = NULL;
2262 2303             globus_extension_release(ext);
2263         }
2264
2265     case GLOBUS_L_SERVICE_ENGINE_RESPONSE_DESTROY_HANDLERS:
2266
2267 2394 if(callback_handle->result != GLOBUS_SUCCESS)
2268 {
2269 0     result = callback_handle->result;
2270 0     goto callback_exit;
2271 }
2272
2273 2394 callback_handle->state =
2274     GLOBUS_L_SERVICE_ENGINE_RESPONSE_SEND;
2275
2276 2394         GlobusServiceEngineLock(callback_handle->engine);
2277 2394         if(callback_handle->engine->handlers)
2278         {
2279 2394             globus_handler_chain_register_invoke(
2280                 callback_handle->engine->handlers,
2281                 GLOBUS_HANDLER_TYPE_RESPONSE_DESTROY,
2282                 callback_handle->message,
2283                 globus_l_service_session_result_callback,
2284                 callback_handle);
2285 2394             GlobusServiceEngineUnlock(callback_handle->engine);
2286 2394             break;
2287         }
2288 0         GlobusServiceEngineUnlock(callback_handle->engine);
2289
2290     case GLOBUS_L_SERVICE_ENGINE_RESPONSE_SEND:
2291
2292 2424         callback_handle->state = 
2293         GLOBUS_L_SERVICE_ENGINE_RESPONSE_CLOSE;
2294
2295         /* If there's no response, we setup the writer to clear the
2296          * buffer state so that we don't send the request back as
2297          * the unwanted response
2298          */
2299 2424         if(callback_handle->response == GLOBUS_SERVICE_NO_RESPONSE)
2300         {
2301 30             result = globus_soap_message_setup_writer(
2302                 callback_handle->message);
2303 30             if(result != GLOBUS_SUCCESS)
2304             {
2305 0                 goto callback_exit;
2306             }
2307         }
2308 2424         result = globus_soap_message_register_write_response(
2309             callback_handle->message,
2310             globus_l_service_session_result_callback,
2311             callback_handle);
2312 2424         if(result != GLOBUS_SUCCESS)
2313         {
2314 0             goto callback_exit;
2315         }
2316
2317 3581         break;
2318
2319     case GLOBUS_L_SERVICE_ENGINE_RESPONSE_CLOSE:
2320 3581         connection = globus_soap_message_handle_get_attr(
2321             callback_handle->message,
2322             GLOBUS_SOAP_MESSAGE_CONNECTION_KEY);
2323
2324 3581         if (callback_handle->result == GLOBUS_SUCCESS
2325             && ((!connection) || (strcmp(connection, "close"))))
2326         {
2327 2333             callback_handle->state =
2328                 GLOBUS_L_SERVICE_ENGINE_REQUEST_READ_ANOTHER_MESSAGE;
2329
2330 2333             result = globus_soap_message_handle_reset(
2331                 callback_handle->message);
2332
2333 2333             if (result != GLOBUS_SUCCESS)
2334             {
2335 0                 goto close_it;
2336             }
2337             /* Register a new metadata read */
2338 2333             result = globus_soap_message_get_transport_handle(
2339                 callback_handle->message,
2340                 &xio_handle);
2341
2342 2333             if (result != GLOBUS_SUCCESS)
2343             {
2344 0                 goto close_it;
2345             }
2346 2333             result = globus_xio_handle_cntl(
2347                     xio_handle,
2348                     globus_i_soap_message_buffer_driver,
2349                     GLOBUS_XIO_BUFFER_CLEAR);
2350 2333             if (result != GLOBUS_SUCCESS)
2351             {
2352 0                 goto close_it;
2353             }
2354
2355 2333             result = globus_xio_register_read(
2356                     xio_handle,
2357                     buffer,
2358                     0,
2359                     0,
2360                     NULL,
2361                     globus_l_service_engine_request_ready_callback,
2362                     callback_handle);
2363 2333             if (result == GLOBUS_SUCCESS)
2364             {
2365 2333                 break;
2366             }
2367         }
2368 close_it:
2369 1248         callback_handle->state = 
2370             GLOBUS_L_SERVICE_ENGINE_RESPONSE_DONE;
2371         
2372 1248         if(callback_handle->result != GLOBUS_SUCCESS)
2373         {
2374 0             result = callback_handle->result;
2375 0             goto exit;
2376         }
2377
2378 1248         result = globus_soap_message_register_close(
2379             callback_handle->message,
2380             globus_l_service_session_result_callback,
2381             callback_handle);
2382
2383 1248         if(result != GLOBUS_SUCCESS)
2384         {
2385 0             goto callback_exit;
2386         }
2387 1248         break;
2388
2389     case GLOBUS_L_SERVICE_ENGINE_RESPONSE_DONE:
2390
2391 1248         if(callback_handle->result != GLOBUS_SUCCESS)
2392         {
2393 0             result = callback_handle->result;
2394 0             goto exit;
2395         }
2396
2397 1         goto callback_exit;
2398     }
2399
2400 1     goto exit;
2401
2402  error_send_fault:
2403
2404 1     if(service_desc)
2405     {
2406 0         service_desc = NULL;
2407 0         globus_extension_release(ext);
2408     }
2409
2410 1     if (operation_name)
2411     {
2412 1         xsd_QName_destroy(operation_name);
2413     }
2414 1     if(result != GLOBUS_SUCCESS)
2415     {
2416 1         char *                          error_str;
2417
2418 1         error_str = globus_error_print_chain(
2419             globus_error_peek(result));
2420 1         GlobusServiceEngineDebugPrintf(
2421             GLOBUS_L_SERVICE_ENGINE_DEBUG_ERROR,
2422             ("SOAP message processing failed:\n%s\n",
2423              error_str));
2424 1         globus_free(error_str);
2425
2426 1         callback_handle->result = result;
2427         /* need to send client FAULT as response */
2428 1         result = globus_callback_register_oneshot(
2429             NULL,
2430             &globus_i_reltime_zero,
2431             globus_l_service_engine_send_client_fault,
2432             callback_handle);
2433 1         if(result != GLOBUS_SUCCESS)
2434         {
2435 0             result = GlobusServiceEngineErrorFailedRequestProcess(
2436                 result, 
2437                 "Failed to register callback "
2438                 "to send client fault response");
2439         }
2440     }
2441
2442 0     goto exit;
2443
2444  callback_exit:
2445
2446 1248     if(result != GLOBUS_SUCCESS)
2447     {
2448 0         ext =
2449         (globus_extension_handle_t)
2450         globus_soap_message_handle_get_attr(
2451             callback_handle->message,
2452             GLOBUS_I_SERVICE_DESCRIPTOR_KEY);
2453 0         if(ext)
2454         {
2455 0             service_desc = 
2456             (globus_service_descriptor_t *) 
2457             globus_extension_reference(ext);
2458
2459 0             globus_assert_string(service_desc,
2460                                  "No SERVICE DESCRIPTOR attribute found!");
2461
2462 0             GlobusSoapMessageDebugServiceLock(service_desc);
2463 0             result = GlobusServiceEngineErrorSessionFailed(
2464                 result, service_desc->name);
2465 0             GlobusSoapMessageDebugServiceUnlock(service_desc);
2466
2467 0             service_desc = NULL;
2468 0             globus_extension_release(ext);
2469         }
2470     }
2471
2472 1248     callback_handle->process_callback(
2473         result ? result : callback_handle->callback_result,
2474         callback_handle->engine,
2475         callback_handle->message,
2476         callback_handle->process_args);
2477     
2478 1248     globus_l_service_session_callback_handle_destroy(callback_handle);
2479
2480  exit:
2481 42285     GlobusServiceEngineDebugExit();
2482 }
2483
2484 globus_result_t
2485 globus_service_session_begin_response(
2486     globus_soap_message_handle_t        message)
2487 2394 {
2488 2394     globus_result_t                     result = GLOBUS_SUCCESS;
2489 2394     GlobusFuncName(globus_service_session_begin_response);
2490 2394     GlobusServiceEngineDebugEnter();
2491
2492 2394     result = globus_soap_message_setup_writer(message);
2493 2394     if(result != GLOBUS_SUCCESS)
2494     {
2495 0         result = GlobusServiceEngineErrorTransportFailed(
2496             result, "Failed to setup message writer");
2497 0         goto exit;
2498     }
2499
2500 2394     result = globus_soap_message_serialize_envelope(message);
2501 2394     if(result != GLOBUS_SUCCESS)
2502     {
2503 0         result = GlobusServiceEngineErrorFailedResponse(result);
2504 0         goto exit;
2505     }
2506
2507 2394     result = globus_soap_message_serialize_header(message);
2508 2394     if(result != GLOBUS_SUCCESS)
2509     {
2510 0         result = GlobusServiceEngineErrorFailedResponse(result);
2511 0         goto exit;
2512     }
2513
2514 2394     result = globus_soap_message_serialize_header_begin_close(message);
2515 2394     if(result != GLOBUS_SUCCESS)
2516     {
2517 0         result = GlobusServiceEngineErrorFailedResponse(result);
2518 0         goto exit;
2519     }
2520
2521 2394     result = globus_soap_message_set_marker(
2522         message,
2523         GLOBUS_SOAP_MESSAGE_MARKER_HEADER_CONTENT);
2524 2394     if(result != GLOBUS_SUCCESS)
2525     {
2526 0         result = GlobusServiceEngineErrorFailedResponse(result);
2527 0         goto exit;
2528     }
2529
2530 2394     result = globus_soap_message_serialize_header_end(message);
2531 2394     if(result != GLOBUS_SUCCESS)
2532     {
2533 0         result = GlobusServiceEngineErrorFailedResponse(result);
2534 0         goto exit;
2535     }
2536
2537 2394     result = globus_soap_message_serialize_body(message);
2538 2394     if(result != GLOBUS_SUCCESS)
2539     {
2540 0         result = GlobusServiceEngineErrorFailedResponse(result);
2541 0         goto exit;
2542     }
2543
2544 2394     result = globus_soap_message_serialize_body_begin_close(
2545 message);
2546 2394     if(result != GLOBUS_SUCCESS)
2547     {
2548 0 result = GlobusServiceEngineErrorFailedResponse(result);
2549 goto exit;
2550     }
2551     
2552  exit:
2553
2554 2394     GlobusServiceEngineDebugExit();
2555 2394     return result;
2556 }
2557
2558 globus_result_t
2559 globus_service_session_end_response(
2560     globus_soap_message_handle_t        message)
2561 2394 {
2562 2394     globus_result_t                     result = GLOBUS_SUCCESS;
2563 2394     GlobusFuncName(globus_service_session_end_response);
2564 2394     GlobusServiceEngineDebugEnter();
2565     
2566 2394     result = globus_soap_message_serialize_body_end(message);
2567 2394     if(result != GLOBUS_SUCCESS)
2568     {
2569 0         result = GlobusServiceEngineErrorFailedResponse(result);
2570 0         goto exit;
2571     }
2572
2573 2394     result = globus_soap_message_serialize_envelope_end(message);
2574 2394     if(result != GLOBUS_SUCCESS)
2575     {
2576 0         result = GlobusServiceEngineErrorFailedResponse(result);
2577         goto exit;
2578     }
2579     
2580  exit:
2581
2582 2394     GlobusServiceEngineDebugExit();
2583 2394     return result;
2584 }
2585
2586 globus_result_t
2587 globus_service_session_serialize_fault_response(
2588     globus_soap_message_handle_t        message,
2589     globus_soap_message_fault_t         fault)
2590 168 {
2591 168     globus_result_t                     result = GLOBUS_SUCCESS;
2592 168     GlobusFuncName(globus_service_serialize_fault_response);
2593 168     GlobusServiceEngineDebugEnter();
2594
2595 168     result = globus_soap_message_serialize_fault(message, fault);
2596 168     if(result != GLOBUS_SUCCESS)
2597     {
2598 0         result = GlobusServiceEngineErrorSendingFault(result);
2599 0         goto exit;
2600     }
2601
2602 168     result = globus_service_session_end_response(message);
2603 168     if(result != GLOBUS_SUCCESS)
2604     {
2605 0         result = GlobusServiceEngineErrorSendingFault(result);
2606         goto exit;
2607     }
2608
2609  exit:
2610
2611 168     GlobusServiceEngineDebugExit();
2612 168     return result;
2613 }
2614
2615 static
2616 void
2617 globus_l_service_engine_send_client_fault(
2618     void *                              args)
2619 92 {
2620 92     globus_result_t                      result = GLOBUS_SUCCESS;
2621 92     globus_xio_handle_t                  xio_handle;
2622 92     globus_l_session_callback_handle_t * callback_handle;
2623 92     char *                               error_string;
2624 92     struct globus_soap_message_fault_s   fault;
2625 92     int                                  status_code = 200;
2626 92     GlobusFuncName(globus_l_service_engine_send_client_fault);
2627 92     GlobusServiceEngineDebugEnter();
2628
2629 92     callback_handle = (globus_l_session_callback_handle_t *) args;
2630 92     callback_handle->faulting = GLOBUS_TRUE;
2631
2632 92     fault.faultcode = "Client";
2633
2634 92     error_string = globus_error_print_friendly(
2635         globus_error_peek(
2636             callback_handle->result));
2637 92     callback_handle->callback_result = callback_handle->result;
2638 92     callback_handle->result = GLOBUS_SUCCESS;
2639 92     fault.faultstring = error_string;
2640 92     fault.faultactor = NULL;
2641 92     fault.detail = NULL;
2642  
2643 92     result = globus_service_session_begin_response(
2644                 callback_handle->message);
2645 92     if(result != GLOBUS_SUCCESS)
2646     {
2647 0         goto error_exit;
2648     }
2649
2650 92     result = globus_service_session_serialize_fault_response(
2651         callback_handle->message, &fault);
2652 92     if(result != GLOBUS_SUCCESS)
2653     {
2654 0         goto error_exit;
2655     }
2656
2657 92     if(GlobusServiceEngineErrorCheckMethodNotAllowed(
2658            callback_handle->result))
2659     {
2660 0         status_code = 405;
2661     }
2662 92     else if(GlobusServiceEngineErrorCheckUnsupportedMediaType(
2663                 callback_handle->result))
2664     {
2665 0         status_code = 415;
2666     }
2667     else
2668     {
2669 92         status_code = 400;
2670     }
2671
2672 92     result = globus_soap_message_get_transport_handle(
2673         callback_handle->message,
2674         &xio_handle);
2675 92     if(result != GLOBUS_SUCCESS)
2676     {
2677 0         goto error_exit;
2678     }
2679
2680 92     result = globus_xio_handle_cntl(
2681         xio_handle,
2682         globus_i_soap_message_http_driver,
2683         GLOBUS_XIO_HTTP_HANDLE_SET_RESPONSE_STATUS_CODE,
2684         status_code);
2685 92     if(result != GLOBUS_SUCCESS)
2686     {
2687 0         goto error_exit;
2688     }
2689
2690 92     result = globus_soap_message_set_write_position_to_marker(
2691         callback_handle->message, 
2692         GLOBUS_SOAP_MESSAGE_MARKER_HEADER_CONTENT);
2693 92     if(result != GLOBUS_SUCCESS)
2694     {
2695 0         goto error_exit;
2696     }
2697
2698 92     result = globus_soap_message_handle_set_attr(
2699         callback_handle->message, 
2700         WSADDR_REQUEST_ENDPOINT_KEY,
2701         globus_soap_message_attr_copy_string,
2702         globus_libc_free,
2703         WSADDRESSING_ANON_NS);
2704 92     if(result != GLOBUS_SUCCESS)
2705     {
2706 0         goto error_exit;
2707     }
2708
2709 92     result = globus_soap_message_handle_set_attr(
2710         callback_handle->message,
2711         WSADDR_ACTION_RESPONSE_KEY,
2712         globus_soap_message_attr_copy_string,
2713         globus_libc_free,
2714         WSADDRESSING_FAULT_NS);
2715 92     if(result != GLOBUS_SUCCESS)
2716     {
2717 0         goto error_exit;
2718     }
2719
2720 92     callback_handle->state = GLOBUS_L_SERVICE_ENGINE_RESPONSE_INVOKE_HANDLERS;
2721
2722 92     result = globus_callback_register_oneshot(
2723         NULL,
2724         &globus_i_reltime_zero,
2725         globus_l_service_session_callback,
2726         callback_handle);
2727 92     if(result != GLOBUS_SUCCESS)
2728     {
2729 0         goto error_exit;
2730     }
2731     
2732 0     goto exit;
2733
2734  error_exit:
2735
2736 0     GlobusServiceEngineLock(callback_handle->engine);
2737 0     callback_handle->callback(result,
2738                               callback_handle->engine,
2739                               callback_handle->message,
2740                               callback_handle->args);
2741 0     GlobusServiceEngineUnlock(callback_handle->engine);
2742 0     globus_l_service_session_callback_handle_destroy(callback_handle);
2743     
2744  exit:
2745
2746 92     GlobusServiceEngineDebugExit();
2747 }
2748
2749 globus_result_t
2750 globus_service_engine_register_process(
2751     globus_service_engine_t                engine,
2752     globus_soap_message_handle_t           message,
2753     globus_result_t                        fault_result,
2754     globus_service_session_callback_func_t callback,
2755     void *                                 user_args)
2756 1252 {
2757 1252     globus_result_t                     result = GLOBUS_SUCCESS;
2758 1252     globus_l_session_callback_handle_t * callback_handle;
2759
2760 1252     if(!message)
2761     {
2762 0         callback(fault_result, engine, NULL, user_args);
2763 0         goto exit;
2764     }
2765
2766 1252     callback_handle = globus_soap_message_handle_get_attr(
2767         message,
2768         GLOBUS_I_SESSION_HANDLE_KEY);
2769 1252     globus_assert_string(
2770         callback_handle, "Session handle lookup failed for callback handle");
2771
2772 1252     callback_handle->process_callback = callback;
2773 1252     callback_handle->process_args = user_args;
2774
2775 1252     if(fault_result != GLOBUS_SUCCESS)
2776     {
2777 91         char *                          error_str;
2778
2779 91         error_str = globus_error_print_chain(
2780             globus_error_peek(fault_result));
2781 91         GlobusServiceEngineDebugPrintf(
2782             GLOBUS_L_SERVICE_ENGINE_DEBUG_ERROR,
2783             ("Error occurred during session accept:\n%s\n",
2784              error_str));
2785 91         globus_free(error_str);
2786
2787 91         callback_handle->result = fault_result;
2788
2789         /* need to send client FAULT as response */
2790 91         result = globus_callback_register_oneshot(
2791             NULL,
2792             &globus_i_reltime_zero,
2793             globus_l_service_engine_send_client_fault,
2794             callback_handle);
2795 91         if(result != GLOBUS_SUCCESS)
2796         {
2797 0             result = GlobusServiceEngineErrorFailedRequestProcess(
2798                 result, 
2799                 "Failed to register callback "
2800                 "to send client fault response");
2801 0             goto exit;
2802         }
2803         
2804 1161         goto exit;
2805     }
2806     else
2807     {
2808 1161         callback_handle->state = 
2809         GLOBUS_L_SERVICE_ENGINE_REQUEST_READ_MESSAGE;
2810         
2811 1161         result = globus_callback_register_oneshot(
2812             NULL,
2813             &globus_i_reltime_zero,
2814             globus_l_service_session_callback,
2815             callback_handle);
2816 1161         if(result != GLOBUS_SUCCESS)
2817         {
2818 0             result = GlobusServiceEngineErrorFailedRequestProcess(
2819                 result, "Failed to register callback to invoke operation");
2820             goto exit;
2821         }
2822     }
2823     
2824  exit:
2825     
2826 1252     GlobusServiceEngineDebugExit();
2827 1252     return result;
2828 }
2829
2830 globus_result_t
2831 globus_service_engine_set_handlers(
2832     globus_service_engine_t             engine,
2833     globus_handler_chain_t              chain)
2834 0 {
2835 0     GlobusFuncName(globus_service_engine_set_handlers);
2836 0     GlobusServiceEngineDebugEnter();
2837
2838 0     if(engine->handlers)
2839     {
2840 0         globus_handler_chain_destroy(engine->handlers);
2841     }
2842
2843 0     engine->handlers = chain;
2844
2845 0     GlobusServiceEngineDebugExit();
2846 0     return GLOBUS_SUCCESS;
2847 }
2848
2849 static
2850 void 
2851 globus_l_service_engine_session_complete_callback(
2852     globus_result_t                     result,
2853     globus_service_engine_t             engine,
2854     globus_soap_message_handle_t        session,
2855     void *                              args)
2856 26 {
2857 26     globus_l_service_engine_callback_handle_t * callback_handle;
2858 26     GlobusFuncName(globus_l_service_engine_session_complete_callback);
2859 26     GlobusServiceEngineDebugEnter();
2860
2861 26     callback_handle = (globus_l_service_engine_callback_handle_t *) args;
2862
2863 26     if(result != GLOBUS_SUCCESS)
2864     {
2865 0         char *                          endpoint = NULL; 
2866 0         char *                          action = NULL;
2867
2868 0         if(session)
2869         {
2870 0             endpoint = globus_soap_message_handle_get_attr(
2871                 session,
2872                 GLOBUS_SOAP_MESSAGE_SERVICE_ENDPOINT_KEY);
2873             
2874 0             action = globus_soap_message_handle_get_attr(
2875                 session,
2876                 GLOBUS_SOAP_MESSAGE_SOAP_ACTION_KEY);
2877         }
2878
2879 0         GlobusServiceEngineDebugPrintError(result, endpoint, action);
2880     }
2881
2882 26     GlobusServiceEngineLock(engine);
2883 26     engine->session_count--;
2884 26     if(engine->stop_sessions && engine->session_count <= 0)
2885     {
2886 0         GlobusServiceEngineUnlock(engine);
2887
2888 0         callback_handle->callback(
2889             GLOBUS_SUCCESS, engine, callback_handle->args);
2890
2891 0         globus_free(callback_handle);
2892     }
2893     else
2894     {
2895 26         GlobusServiceEngineUnlock(engine);
2896     }
2897
2898 26     globus_soap_message_handle_destroy(session);
2899
2900 26     GlobusServiceEngineDebugExit();
2901 }
2902
2903 static
2904 void
2905 globus_l_service_engine_session_started_callback(
2906     globus_result_t                     result,
2907     globus_service_engine_t             engine,
2908     globus_soap_message_handle_t        session,
2909     void *                              args)
2910 43 {
2911 43     globus_result_t                     fault_result = GLOBUS_SUCCESS;
2912 43     globus_l_service_engine_callback_handle_t * callback_handle;
2913 43     GlobusFuncName(globus_l_service_engine_session_started_callback);
2914 43     GlobusServiceEngineDebugEnter();
2915
2916 43     callback_handle = (globus_l_service_engine_callback_handle_t *) args;
2917
2918 43     GlobusServiceEngineLock(engine);
2919
2920 43     if(result != GLOBUS_SUCCESS)
2921     {
2922 13         result = GlobusServiceEngineErrorSessionStartFailed(result);
2923 13         goto error_exit;
2924     }
2925
2926 30     if(callback_handle->result != GLOBUS_SUCCESS)
2927     {
2928 0         fault_result = callback_handle->result;
2929     }
2930         
2931 30     engine->session_count++;
2932 30     if(!engine->stop_sessions)
2933     {
2934 30         result = globus_service_engine_register_session(
2935             engine,
2936             globus_l_service_engine_session_started_callback,
2937             callback_handle);
2938 30         if(result != GLOBUS_SUCCESS)
2939         {
2940 0             GlobusServiceEngineUnlock(engine);
2941             /* no more sessions started */
2942 0             goto error_exit;
2943         }
2944     }
2945     
2946 30     GlobusServiceEngineUnlock(engine);
2947
2948 30     result = globus_service_engine_register_process(
2949         engine,
2950         session,
2951         fault_result,
2952         globus_l_service_engine_session_complete_callback,
2953         args);
2954
2955 30     goto exit;
2956
2957  error_exit:
2958
2959 13     if(result != GLOBUS_SUCCESS)
2960     {
2961 13         char *                          endpoint = NULL; 
2962 13         char *                          action = NULL;
2963
2964 13         if(session)
2965         {
2966 0             endpoint = globus_soap_message_handle_get_attr(
2967                 session,
2968                 GLOBUS_SOAP_MESSAGE_SERVICE_ENDPOINT_KEY);
2969             
2970 0             action = globus_soap_message_handle_get_attr(
2971                 session,
2972                 GLOBUS_SOAP_MESSAGE_SOAP_ACTION_KEY);
2973         }
2974
2975 13         GlobusServiceEngineDebugPrintError(result, endpoint, action);
2976     }
2977
2978 13     if (globus_xio_error_is_canceled(result))
2979     {
2980 13         result = GLOBUS_SUCCESS;
2981     }
2982 13     callback_handle->callback(result,
2983                               engine, 
2984                               callback_handle->args);
2985     
2986 13     if(engine->session_count <= 0)
2987     {
2988 13         free(callback_handle);
2989     }
2990 13     GlobusServiceEngineUnlock(engine);
2991     
2992  exit:
2993
2994 43     GlobusServiceEngineDebugExit();
2995 }
2996
2997
2998 globus_result_t
2999 globus_service_engine_register_start(
3000     globus_service_engine_t               engine,
3001     globus_service_engine_callback_func_t stop_callback,
3002     void *                                args)
3003 19 {
3004 19     globus_l_service_engine_callback_handle_t * callback_handle;
3005 19     globus_result_t                     result = GLOBUS_SUCCESS;
3006 19     GlobusFuncName(globus_service_engine_register_start);
3007 19     GlobusServiceEngineDebugEnter();
3008
3009 19     if (stop_callback == NULL)
3010     {
3011 0         result = GlobusSoapMessageErrorNullParam;
3012
3013 0         goto exit;
3014     }
3015 19     if(engine->stop_sessions)
3016     {
3017 0         result = GlobusServiceEngineErrorAlreadyStarted();
3018 0         goto exit;
3019     }
3020
3021 19     callback_handle = globus_malloc(
3022         sizeof(globus_l_service_engine_callback_handle_t));
3023 19     if(!callback_handle)
3024     {
3025 0         result = GlobusServiceEngineErrorOutOfMemory;
3026 0         goto exit;
3027     }
3028 19     memset(callback_handle, 0, sizeof(globus_l_service_engine_callback_handle_t));
3029
3030 19     callback_handle->engine = engine;
3031 19     callback_handle->callback = stop_callback;
3032 19     callback_handle->args = args;
3033
3034 19     result = globus_service_engine_register_session(
3035         engine,
3036         globus_l_service_engine_session_started_callback,
3037         callback_handle);
3038 19     if(result != GLOBUS_SUCCESS)
3039     {
3040 0         result = GlobusServiceEngineErrorFailedStart(result);
3041     }
3042
3043  exit:
3044
3045 19     GlobusServiceEngineDebugExit();
3046 19     return result;
3047 }
3048
3049 globus_result_t
3050 globus_service_engine_register_stop(
3051     globus_service_engine_t               engine)
3052 3 {
3053 3     globus_result_t                     result = GLOBUS_SUCCESS;
3054 3     GlobusFuncName(globus_service_engine_register_stop);
3055 3     GlobusServiceEngineDebugEnter();
3056
3057 3     GlobusServiceEngineLock(engine);
3058 3     engine->stop_sessions = 1;
3059 3     globus_xio_server_cancel_accept(engine->server);
3060 3     GlobusServiceEngineUnlock(engine);
3061
3062 3     GlobusServiceEngineDebugExit();
3063 3     return result;
3064 }
3065
3066 static
3067 int
3068 globus_l_service_engine_is_equal(
3069     void *                              datum,
3070     void *                              arg)
3071 572 {
3072 572     globus_service_engine_t             engine = datum;
3073 572     globus_url_t *                      url = arg;
3074 572     globus_url_t                        engine_url;
3075 572     int                                 rc;
3076
3077 572     rc = globus_url_parse(engine->contact, &engine_url);
3078
3079 572     if (rc != GLOBUS_SUCCESS)
3080     {
3081 0         rc = GLOBUS_FALSE;
3082     }
3083     else
3084     {
3085 572         if (engine_url.port == url->port)
3086         {
3087 453             rc = GLOBUS_TRUE;
3088         }
3089         else
3090         {
3091 119             rc = GLOBUS_FALSE;
3092         }
3093
3094 572         globus_url_destroy(&engine_url);
3095     }
3096 572     return rc;
3097 }
3098 /* globus_l_service_engine_is_equal() */
3099
3100 globus_result_t
3101 globus_i_service_engine_get_descriptor(
3102     char *                              uri,
3103     globus_soap_message_handle_t        message,
3104     globus_service_descriptor_t **      service_desc_p)
3105 2877 {
3106 2877     globus_result_t                     result = GLOBUS_SUCCESS;
3107 2877     char *                              uriref;
3108 2877     char *                              service_path;
3109 2877     globus_service_descriptor_t *       service_desc = NULL;
3110 2877     globus_extension_handle_t           ext;
3111 2877     globus_bool_t                       free_service_path = GLOBUS_TRUE;
3112
3113 2877     uriref = uri;
3114 5754     while (*uriref == '/')
3115     {
3116 2877         uriref++;
3117     }
3118 2877     service_path = globus_common_create_string(
3119         GLOBUS_SERVICE_ENGINE_MODULE_PATH_PREFIX "/%s", uriref);
3120
3121 2877     if (service_path == NULL)
3122     {
3123 0         result = GlobusSoapMessageErrorOutOfMemory;
3124
3125 0         goto out;
3126     }
3127 2877     service_desc = globus_extension_lookup(
3128         &ext,
3129         GLOBUS_SERVICE_REGISTRY,
3130         service_path);
3131 2877     if(!service_desc)
3132     {
3133 164         int                             res;
3134
3135 164         res = globus_extension_activate(service_path);
3136
3137 164         if(res != GLOBUS_SUCCESS)
3138         {
3139 91             globus_object_t *           tmp_err = globus_error_get((globus_result_t) res);
3140 91             if(GlobusServiceEngineDebug(GLOBUS_L_SERVICE_ENGINE_DEBUG_DEBUG))
3141             {
3142 0                 char * serror = globus_error_print_chain(
3143 0                     tmp_err);
3144 0                 GlobusServiceEngineDebugPrintf(
3145                     GLOBUS_L_SERVICE_ENGINE_DEBUG_DEBUG,
3146                     ("Module Activation Failed:\n\n%s\n",
3147                     serror));
3148 0                 globus_free(serror);
3149             }
3150
3151 91             result = GlobusServiceEngineErrorServiceLoadFailed(uri, tmp_err);
3152 91             goto free_service_path_out;
3153         }
3154
3155 73         GlobusServiceEngineExtensionLock();
3156 73         globus_list_insert(&globus_l_service_engine_extensions,
3157                            service_path);
3158 73         free_service_path = GLOBUS_FALSE;
3159 73         GlobusServiceEngineExtensionUnlock();
3160
3161 73         service_desc = globus_extension_lookup(
3162                 &ext,
3163                 GLOBUS_SERVICE_REGISTRY, 
3164                 service_path);
3165 73         if(!service_desc)
3166         {
3167 0             result = GlobusServiceEngineErrorServiceLoadFailed(uri, NULL);
3168 0             goto remove_extension_from_list_out;
3169         }
3170     }
3171
3172 2786     result = globus_soap_message_handle_set_attr(
3173         message,
3174         GLOBUS_SOAP_MESSAGE_SERVICE_ENDPOINT_KEY,
3175         globus_soap_message_attr_copy_string,
3176         globus_libc_free,
3177         (void *)uri);
3178 2786     if(result != GLOBUS_SUCCESS)
3179     {
3180 0         result = GlobusServiceEngineErrorReadRequestFailed(result);
3181
3182 0         goto remove_extension_from_list_out;
3183     }
3184
3185 2786     result = globus_soap_message_handle_set_attr(
3186         message,
3187         GLOBUS_I_SERVICE_DESCRIPTOR_KEY,
3188         globus_l_service_engine_service_module_copy,
3189         globus_l_service_engine_service_module_destroy,
3190         (void *)ext);
3191 2786     if(result != GLOBUS_SUCCESS)
3192     {
3193 0         result = GlobusServiceEngineErrorReadRequestFailed(result);
3194
3195 0         goto remove_service_endpoint_attr;
3196     }
3197 2786     if (result != GLOBUS_SUCCESS)
3198     {
3199 0         globus_list_t *                 tmp;
3200
3201 remove_service_endpoint_attr:
3202 0         globus_soap_message_handle_remove_attr(
3203                 message,
3204                 GLOBUS_SOAP_MESSAGE_SERVICE_ENDPOINT_KEY);
3205
3206 remove_extension_from_list_out:
3207 0         GlobusServiceEngineExtensionLock();
3208 0         tmp = globus_list_search(globus_l_service_engine_extensions,
3209                            service_path);
3210
3211 0         if (tmp != NULL)
3212         {
3213 0             globus_list_remove(&globus_l_service_engine_extensions, tmp);
3214         }
3215 0         GlobusServiceEngineExtensionUnlock();
3216 0         globus_extension_deactivate(service_path);
3217     }
3218 free_service_path_out:
3219 2877     if (result != GLOBUS_SUCCESS || free_service_path)
3220     {
3221 2804         free(service_path);
3222     }
3223 out:
3224 2877     *service_desc_p = service_desc;
3225
3226 2877     return result;
3227 }