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