1 /*
2  * Copyright 1999-2006 University of Chicago
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * 
8  * http://www.apache.org/licenses/LICENSE-2.0
9  * 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18 #include "globus_common.h"
19 #include "globus_xio_buffer.h"
20 #include "globus_xio_tcp_driver.h"
21 #include "globus_xio_http.h"
22 #include "globus_soap_message_handle.h"
23 #include "globus_i_soap_message.h"
24 #include "globus_soap_message.h"
25 #include "globus_soap_message_attrs.h"
26 #include "globus_xio_gsi.h"
27
28 static
29 void
30 globus_l_soap_message_response_ready_callback(
31     globus_xio_handle_t                 handle,
32     globus_result_t                     result,
33     globus_byte_t *                     buffer,
34     globus_size_t                       len,
35     globus_size_t                       nbytes,
36     globus_xio_data_descriptor_t        data_desc,
37     void *                              user_arg);
38
39 typedef struct
40 {
41     struct globus_soap_message_handle_s * message;
42     int                                   no_response;
43     globus_soap_message_callback_func_t   callback;
44     void *                                args;
45     enum 
46     {
47         GLOBUS_SOAP_MESSAGE_REQUEST_CALLBACK,
48         GLOBUS_SOAP_MESSAGE_RESPONSE_CALLBACK
49     } type;
50 } globus_l_soap_message_callback_handle_t;
51
52
53 void
54 globus_l_soap_message_error_callback(
55     void *                              arg,
56     const char *                        msg,
57     xmlParserSeverities                 severity,
58     xmlTextReaderLocatorPtr             locator)
59 0 {
60 0     globus_soap_message_handle_t        handle;
61 0     int                                 lno;
62 0     xmlChar *                           baseuri;
63 0     GlobusFuncName(globus_i_soap_message_error_callback);
64 0     GlobusSoapMessageDebugEnter();
65
66 0     handle = (globus_soap_message_handle_t) arg;
67 0     if(handle->result != GLOBUS_SUCCESS)
68     {
69 0         return;
70     }
71
72 0     if(handle->result != GLOBUS_SUCCESS)
73     {
74 0         return;
75     }
76
77 0     if(locator)
78     {
79 0         lno = xmlTextReaderLocatorLineNumber(locator);
80 0         baseuri = xmlTextReaderLocatorBaseURI(locator);
81     }
82     
83 0     switch(severity)
84     {
85     case XML_PARSER_SEVERITY_ERROR:
86     case XML_PARSER_SEVERITY_VALIDITY_ERROR:
87     
88 0         handle->result = GlobusSoapMessageErrorParserFailed(msg, lno, baseuri);
89 0         break;
90
91     case XML_PARSER_SEVERITY_WARNING:
92     case XML_PARSER_SEVERITY_VALIDITY_WARNING:
93
94 0         GlobusSoapMessageDebugPrintf(GLOBUS_SOAP_MESSAGE_DEBUG_WARN,
95                                      ("%s:%d: %s", baseuri, lno, msg));
96
97     default:
98 0         break;
99     }
100
101 0     GlobusSoapMessageDebugExit();
102 }
103
104 void
105 globus_l_soap_message_structured_error_callback(
106     void *                              userdata,
107     xmlErrorPtr                         error)
108 11 {
109 11     globus_soap_message_handle_t        handle;
110 11     GlobusFuncName(globus_i_soap_message_structured_error_callback);
111 11     GlobusSoapMessageDebugEnter();
112
113 11     handle = (globus_soap_message_handle_t) userdata;
114    
115 11     if(handle->result != GLOBUS_SUCCESS)
116     {
117 4         return;
118     }
119  
120 7     handle->result = GlobusSoapMessageErrorParserFailed(
121         error->message, error->line, error->file);
122
123 7     GlobusSoapMessageDebugExit();
124 }
125
126 static
127 int
128 globus_l_soap_message_handle_libxml_io_read_callback(
129     void *                              context,
130     char *                              buffer,
131     int                                 length)
132 81179 {
133 81179     globus_size_t                       read_length = 0;
134 81179     globus_soap_message_handle_t        handle;
135 81179     globus_result_t                     result = GLOBUS_SUCCESS;
136 81179     GlobusFuncName(
137         globus_l_soap_message_handle_libxml_io_read_callback);
138 81179     GlobusSoapMessageDebugEnter();
139
140 81179     handle = (globus_soap_message_handle_t) context;
141 81179     globus_assert_string(handle, "NULL handle passed to function");
142
143 81179     if(handle->buffer_eof)
144     {
145 5580         goto exit;
146     }
147
148 75599     result = globus_xio_read(
149         handle->xio_handle, (globus_byte_t *)buffer,
150         length, 1, &read_length, NULL);
151 75599     if(result != GLOBUS_SUCCESS && 
152        globus_xio_driver_error_match(
153            globus_i_soap_message_buffer_driver, 
154            globus_error_peek(result),
155            GLOBUS_XIO_BUFFER_ERROR_EOF))
156     {
157 5580         handle->result = GLOBUS_SUCCESS;
158 5580         handle->buffer_eof = 1;
159     }
160 70019     else if(result != GLOBUS_SUCCESS)
161     {
162 64         handle->result = result;
163     }
164
165   exit:
166     
167 81179     GlobusSoapMessageDebugExit();
168 81179     return read_length;
169 }
170
171 static
172 int
173 globus_l_soap_message_handle_libxml_io_write_callback(
174     void *                              context,
175     const char *                        buffer,
176     int                                 length)
177 86610 {
178 86610     globus_size_t                       bytes_written = 0;
179 86610     globus_result_t                     result = GLOBUS_SUCCESS;
180 86610     globus_soap_message_handle_t        handle;
181 86610     GlobusFuncName(
182         globus_l_soap_message_handle_libxml_io_write_callback);
183 86610     GlobusSoapMessageDebugEnter();
184
185 86610     handle = (globus_soap_message_handle_t) context;
186 86610     globus_assert_string(handle, "NULL handle passed to function");
187
188 86610     result = globus_xio_write(
189         handle->xio_handle, (globus_byte_t *) buffer, 
190         length, length, &bytes_written, NULL);
191 86610     if(result != GLOBUS_SUCCESS)
192     {
193 0         handle->result = result;
194     }
195
196 86610     GlobusSoapMessageDebugExit();
197 86610     return bytes_written;
198 }
199
200 static
201 int
202 globus_l_soap_message_handle_libxml_io_close_callback(
203     void *                              context)
204 12507 {
205 12507     globus_soap_message_handle_t             handle;
206 12507     GlobusFuncName(
207         globus_l_soap_message_handle_libxml_io_close_callback);
208 12507     GlobusSoapMessageDebugEnter();
209
210 12507     handle = (globus_soap_message_handle_t) context;
211 12507     globus_assert_string(handle, "NULL handle passed to function");
212
213     /* do nothing.  close should be done async. */
214     
215 12507     GlobusSoapMessageDebugExit();
216 12507     return 0;
217 }
218
219 static
220 void
221 globus_l_soap_message_open_callback(
222     globus_xio_handle_t                 handle,
223     globus_result_t                     result,
224     void *                              user_args)
225 3267 {
226 3267     globus_l_soap_message_callback_handle_t * callback_handle;
227
228 3267     callback_handle = (globus_l_soap_message_callback_handle_t *) user_args;
229
230 3267     if(result == GLOBUS_SUCCESS)
231     {
232 3267         result = globus_soap_message_setup_writer(
233             callback_handle->message);
234 3267         if(result != GLOBUS_SUCCESS)
235         {
236 0             goto exit;
237         }
238     }
239     else
240     {
241 0         callback_handle->message->result = result;
242     }
243     
244
245  exit:
246     
247 3267     callback_handle->callback(result, callback_handle->args);
248 3267     free(callback_handle);
249 }
250
251 globus_result_t
252 globus_i_soap_message_setup_unbuffered_writer(
253     globus_soap_message_handle_t        message)
254 0 {
255 0     xmlOutputBufferPtr                  output_buffer = NULL;
256 0     globus_result_t                     result = GLOBUS_SUCCESS;
257 0     GlobusFuncName(globus_i_soap_message_setup_unbuffered_writer);
258 0     GlobusSoapMessageDebugEnter();
259
260 0     output_buffer = xmlOutputBufferCreateIO(
261         globus_l_soap_message_handle_libxml_io_write_callback,
262         globus_l_soap_message_handle_libxml_io_close_callback,
263         message,
264         0);
265 0     if(!output_buffer)
266     {
267 0         result = GlobusSoapMessageErrorInitFailed(
268             "Failed to initialize output buffer");
269 0         goto exit;
270     }
271     
272 0     message->writer = xmlNewTextWriter(output_buffer);
273 0     if(!message->writer)
274     {
275 0         result = GlobusSoapMessageErrorInitFailed(
276             "Failed to initialize xmlWriter");
277         goto free_output;
278     }
279
280 0     goto exit;
281
282  free_output:
283
284 0     xmlOutputBufferClose(output_buffer);
285
286  exit:
287
288 0     GlobusSoapMessageDebugExit();
289 0     return result;
290 }
291     
292
293 globus_result_t
294 globus_soap_message_setup_writer(
295     globus_soap_message_handle_t        message)
296 5691 {
297 5691     xmlOutputBufferPtr                  output_buffer = NULL;
298 5691     globus_result_t                     result = GLOBUS_SUCCESS;
299 5691     GlobusFuncName(globus_soap_message_setup_writer);
300 5691     GlobusSoapMessageDebugEnter();
301
302 5691     globus_assert(message);
303
304 5691     result = globus_xio_handle_cntl(
305         message->xio_handle,
306         globus_i_soap_message_buffer_driver,
307         GLOBUS_XIO_BUFFER_CLEAR);
308 5691     if(result != GLOBUS_SUCCESS)
309     {
310 0         result = GlobusSoapMessageErrorFailedTransport(
311             result, "Failed to enable buffering for message write");
312 0         goto exit;
313     }
314
315 5691     result = globus_xio_handle_cntl(
316         message->xio_handle, 
317         globus_i_soap_message_buffer_driver,
318         GLOBUS_XIO_BUFFER_ENABLE_WRITE_BUFFERING);
319 5691     if(result != GLOBUS_SUCCESS)
320     {
321 0         result = GlobusSoapMessageErrorFailedTransport(
322             result, "Failed to enable buffering for message write");
323 0         goto exit;
324     }
325     
326 5691     output_buffer = xmlOutputBufferCreateIO(
327         globus_l_soap_message_handle_libxml_io_write_callback,
328         globus_l_soap_message_handle_libxml_io_close_callback,
329         message,
330         0);
331 5691     if(!output_buffer)
332     {
333 0         result = GlobusSoapMessageErrorInitFailed(
334             "Failed to initialize output buffer");
335 0         goto exit;
336     }
337     
338 5691     message->writer = xmlNewTextWriter(output_buffer);
339 5691     if(!message->writer)
340     {
341 0         result = GlobusSoapMessageErrorInitFailed(
342             "Failed to initialize xmlWriter");
343         goto free_output;
344     }
345
346 0     goto exit;
347
348  free_output:
349
350 0     xmlOutputBufferClose(output_buffer);
351
352  exit:
353
354 5691     GlobusSoapMessageDebugExit();
355 5691     return result;
356 }
357
358 static
359 void
360 globus_l_soap_message_flush_callback(
361     globus_xio_handle_t                 handle,
362     globus_result_t                     result,
363     globus_byte_t *                     buffer,
364     globus_size_t                       len,
365     globus_size_t                       nbytes,
366     globus_xio_data_descriptor_t        data_desc,
367     void *                              user_args)
368 5661 {
369 5661     globus_result_t                     internal_result = GLOBUS_SUCCESS;
370 5661     static globus_byte_t                fake_buffer[1];
371 5661     globus_l_soap_message_callback_handle_t * callback_handle;
372
373 5661     callback_handle = (globus_l_soap_message_callback_handle_t *) user_args;
374 5661     callback_handle->message->result = result;
375
376 5661     if(nbytes > 0)
377     {
378 5661         internal_result = globus_xio_handle_cntl(
379             callback_handle->message->xio_handle,
380             globus_i_soap_message_http_driver,
381             GLOBUS_XIO_HTTP_HANDLE_SET_END_OF_ENTITY);
382 5661         if(internal_result != GLOBUS_SUCCESS)
383         {
384 0             internal_result = GlobusSoapMessageErrorFailedTransport(
385                 internal_result, 
386                 "Failed to flush message");
387 0             goto error;
388         }
389     }
390
391 5661     internal_result = globus_xio_handle_cntl(
392         callback_handle->message->xio_handle,
393         globus_i_soap_message_buffer_driver,
394         GLOBUS_XIO_BUFFER_CLEAR);
395 5661     if(internal_result != GLOBUS_SUCCESS)
396     {
397 0         internal_result = GlobusSoapMessageErrorFailedTransport(
398             internal_result, 
399             "Failed to flush message");
400 0         goto error;
401     }
402
403 5661     callback_handle->callback(result, callback_handle->args);
404
405 5661     if (callback_handle->type == GLOBUS_SOAP_MESSAGE_REQUEST_CALLBACK &&
406 callback_handle->no_response == 0)
407     {
408 3247         result = globus_xio_register_read(handle,
409             fake_buffer,
410             0,
411             0,
412             NULL,
413             globus_l_soap_message_response_ready_callback,
414             callback_handle->message);
415
416 3247         if(result != GLOBUS_SUCCESS)
417         {
418 0             globus_l_soap_message_response_ready_callback(
419                     handle,
420                     result,
421                     fake_buffer,
422                     0,
423                     0,
424                     NULL,
425                     callback_handle->message);
426         }
427     }
428     else
429     {
430 2414         globus_assert(
431             callback_handle->type == GLOBUS_SOAP_MESSAGE_RESPONSE_CALLBACK ||
432     callback_handle->no_response);
433     }
434
435 0     goto exit;
436     
437 error:
438 0     callback_handle->callback(internal_result, callback_handle->args);
439     
440 exit:
441 5661     free(callback_handle);
442 }
443
444 static
445 void
446 globus_l_soap_message_read_callback(
447     globus_xio_handle_t                 handle,
448     globus_result_t                     result,
449     globus_byte_t *                     buffer,
450     globus_size_t                       len,
451     globus_size_t                       nbytes,
452     globus_xio_data_descriptor_t        data_desc,
453     void *                              user_arg)
454 562074 {
455 562074     globus_l_soap_message_callback_handle_t * callback_handle;
456 562074     globus_result_t                     local_result = GLOBUS_SUCCESS;
457 562074     GlobusFuncName(globus_l_soap_message_read_callback);
458 562074     GlobusSoapMessageDebugEnter();
459
460 562074     callback_handle = (globus_l_soap_message_callback_handle_t *) user_arg; 
461 562074     callback_handle->message->result = result;
462    
463 562074     if(result != GLOBUS_SUCCESS)
464     {
465 5580         if(globus_xio_error_is_eof(result) ||
466            globus_xio_driver_error_match(
467                globus_i_soap_message_http_driver,
468                globus_error_peek(result), GLOBUS_XIO_HTTP_ERROR_EOF) ||
469            globus_xio_driver_error_match(
470                globus_i_soap_message_buffer_driver,
471                globus_error_peek(result), GLOBUS_XIO_BUFFER_ERROR_EOF))
472         {
473 5580             result = GLOBUS_SUCCESS;
474
475 5580             if(GlobusSoapMessageDebug(GLOBUS_SOAP_MESSAGE_DEBUG_MESSAGES))
476             {
477 0                 char *                          buffer;
478 0                 int                             read_length;
479                 
480 0                 globus_xio_handle_cntl(
481                     callback_handle->message->xio_handle,
482                     globus_i_soap_message_buffer_driver,
483                     GLOBUS_XIO_BUFFER_GET_MARKED_BUFFERS,
484                     NULL, NULL, &buffer, &read_length);
485
486 0                 GlobusSoapMessageDebugPrintf(
487                     GLOBUS_SOAP_MESSAGE_DEBUG_MESSAGES,
488                     ("----------------READING--------------\n%.*s\n"
489                      "=====================================\n\n",
490                      read_length, buffer));
491
492 0                 free(buffer);
493             }
494
495 5580             local_result = globus_xio_handle_cntl(
496                 callback_handle->message->xio_handle,
497                 globus_i_soap_message_buffer_driver,
498                 GLOBUS_XIO_BUFFER_RESET_READ_POSITION);
499 5580             if(local_result != GLOBUS_SUCCESS)
500             {
501 0                 local_result = GlobusSoapMessageErrorFailedTransport(
502                     local_result,
503                     "failed to reset buffer read position to start");
504 0                 goto exit;
505             }
506
507 5580             if (callback_handle->message->reader != NULL)
508             {
509 1172                 xmlFreeTextReader(callback_handle->message->reader);
510             }
511 5580             if (callback_handle->message->doc_to_free != NULL)
512             {
513 0                 xmlFreeDoc(callback_handle->message->doc_to_free);
514 0                 callback_handle->message->doc_to_free = NULL;
515             }
516 5580             callback_handle->message->reader = xmlReaderForIO(
517                 globus_l_soap_message_handle_libxml_io_read_callback,
518                 globus_l_soap_message_handle_libxml_io_close_callback,
519                 callback_handle->message,
520                 NULL,
521                 NULL,
522                 0);
523 5580             if(!callback_handle->message->reader)
524             {
525 0                 result = GlobusSoapMessageErrorInitFailed(
526                     "Failed to initialize xmlReader");
527 0                 goto exit;
528             }
529             
530 5580             xmlTextReaderSetErrorHandler(callback_handle->message->reader, 
531                                          globus_l_soap_message_error_callback, 
532                                          callback_handle->message);
533             
534 5580             xmlTextReaderSetStructuredErrorHandler(
535                 callback_handle->message->reader,
536                 globus_l_soap_message_structured_error_callback,
537                 callback_handle->message);
538             
539 5580             callback_handle->callback(result, callback_handle->args);
540 5580             free(callback_handle);
541         }
542         else
543         {
544 0             local_result = result;
545         }
546         
547 0         goto exit;
548     }
549     
550 556494     local_result = globus_xio_register_read(
551         callback_handle->message->xio_handle,
552         (globus_byte_t *)callback_handle->message->readbuf,
553         GLOBUS_I_SOAP_MESSAGE_READBUF_SIZE,
554         1,
555         NULL,
556         globus_l_soap_message_read_callback,
557         callback_handle);
558 556494     if(local_result != GLOBUS_SUCCESS)
559     {
560 0         local_result = GlobusSoapMessageErrorFailedTransport(
561             local_result, "Failed to begin reading SOAP message");
562         goto exit;
563     }
564     
565  exit:
566
567 562074     if(local_result != GLOBUS_SUCCESS)
568     {
569 0         callback_handle->message->result = local_result;
570 0         callback_handle->callback(result, callback_handle->args);
571     }
572
573 562074     GlobusSoapMessageDebugExit();
574 562074     return;
575 }
576
577 static
578 void
579 globus_l_soap_message_response_callback(
580     void *                              args)
581 3247 {
582 3247     globus_result_t                     result = GLOBUS_SUCCESS;
583 3247     globus_l_soap_message_callback_handle_t * callback_handle;
584 3247     GlobusFuncName(globus_l_soap_message_response_callback);
585 3247     GlobusSoapMessageDebugEnter();
586
587 3247     callback_handle = (globus_l_soap_message_callback_handle_t *) args;
588
589 3247     if(callback_handle->message->response_semaphore >= 2)
590     {
591 3247         globus_mutex_lock(&callback_handle->message->mutex);
592 3247         callback_handle->message->response_semaphore = 0;
593 3247         globus_mutex_unlock(&callback_handle->message->mutex);
594
595 3247         if(callback_handle->message->result != GLOBUS_SUCCESS)
596         {
597 4             if (globus_error_match
598                         (globus_error_peek(
599                                 callback_handle->message->result),
600                         GLOBUS_SOAP_MESSAGE_MODULE,
601                         GLOBUS_SOAP_MESSAGE_ERROR_TYPE_FAILED_TRANSPORT))
602             {
603 0                 result = callback_handle->message->result;
604 0                 goto exit;
605             }
606         }
607 3247         result = globus_xio_handle_cntl(
608             callback_handle->message->xio_handle,
609             globus_i_soap_message_buffer_driver,
610             GLOBUS_XIO_BUFFER_ENABLE_READ_BUFFERING);
611 3247         if(result != GLOBUS_SUCCESS)
612         {
613 0             result = GlobusSoapMessageErrorFailedTransport(
614                 result, "Failed to enable read buffering in buffer driver");
615 0             goto exit;
616         }
617
618 3247         result = globus_xio_register_read(
619             callback_handle->message->xio_handle,
620             (globus_byte_t *)callback_handle->message->readbuf,
621             GLOBUS_I_SOAP_MESSAGE_READBUF_SIZE,
622             1,
623             NULL,
624             globus_l_soap_message_read_callback,
625             callback_handle);
626 3247         if(result != GLOBUS_SUCCESS)
627         {
628 0             result = GlobusSoapMessageErrorFailedTransport(
629                 result, "Failed to begin reading SOAP message");
630             goto exit;
631         }
632     }
633
634  exit:
635
636 3247     if(result != GLOBUS_SUCCESS)
637     {
638             
639 0         callback_handle->callback(result, callback_handle->args);
640 0         free(callback_handle);
641     }
642
643 3247     GlobusSoapMessageDebugExit();
644 3247     return;
645 }
646
647 static
648 void
649 globus_l_soap_message_response_ready_callback(
650     globus_xio_handle_t                 handle,
651     globus_result_t                     result,
652     globus_byte_t *                     buffer,
653     globus_size_t                       len,
654     globus_size_t                       nbytes,
655     globus_xio_data_descriptor_t        data_desc,
656     void *                              user_arg)
657 3247 {
658 3247     globus_soap_message_handle_t        message_handle;
659 3247     int                                 response_code;
660 3247     const char *                        message;
661 3247     globus_xio_http_version_t           version;
662 3247     globus_hashtable_t                  headers;
663 3247     GlobusFuncName(globus_l_soap_message_response_ready_callback);
664 3247     GlobusSoapMessageDebugEnter();
665
666 3247     message_handle = (globus_soap_message_handle_t) user_arg;
667
668 3247     if (result == GLOBUS_SUCCESS)
669     {
670 3247         result = globus_xio_data_descriptor_cntl(
671             data_desc,
672             globus_i_soap_message_http_driver,
673             GLOBUS_XIO_HTTP_GET_RESPONSE,
674             &response_code,
675             &message,
676             &version,
677             &headers);
678     }
679
680 3247     if(result != GLOBUS_SUCCESS)
681     {
682 0         message_handle->result = GlobusSoapMessageErrorFailedTransport(
683             result, "Error in HTTP response");
684 0         response_code = -1;
685 0         GlobusSoapMessageDebugError(message_handle->result);
686     }
687 3247     GlobusSoapMessageDebugPrintf(GLOBUS_SOAP_MESSAGE_DEBUG_DEBUG,
688                                  ("response code: %d\n", response_code));
689     
690
691 3247     if(response_code > 299)
692     {
693 4         if(response_code > 399 && response_code < 500)
694         {
695 2             message_handle->result = GlobusSoapMessageErrorBadRequest(
696                 response_code, message);
697         }
698
699 4         if(response_code > 499)
700         {
701 2             message_handle->result = GlobusSoapMessageErrorFailedResponse(
702                 response_code, message);
703         }
704     }
705
706 3247     globus_mutex_lock(&message_handle->mutex);
707 3247     message_handle->response_semaphore++;
708
709 3247     if(message_handle->response_semaphore > 1 &&
710        message_handle->response_handle)
711     {
712 3247         globus_l_soap_message_callback_handle_t * response_handle =
713         (globus_l_soap_message_callback_handle_t *)
714 3247         message_handle->response_handle;
715
716 3247         globus_mutex_unlock(&message_handle->mutex);
717
718 3247         message_handle->response_handle = NULL;
719
720 3247         globus_l_soap_message_response_callback(
721             response_handle);
722     }
723     else
724     {
725 0         globus_mutex_unlock(&message_handle->mutex);
726     }
727
728 3247     GlobusSoapMessageDebugExit();
729 3247     return;
730 }    
731
732 static
733 globus_bool_t
734 globus_l_soap_message_timeout_callback(
735     globus_xio_handle_t                 handle,
736     globus_xio_operation_type_t         type,
737     void *                              user_arg)
738 0 {
739 0     return GLOBUS_TRUE;
740 }
741
742
743 globus_result_t
744 globus_soap_message_register_open(
745     globus_soap_message_handle_t        handle,
746     char *                              endpoint,
747     globus_soap_message_callback_func_t callback,
748     void *                              args)
749 3267 {
750 3267     globus_soap_message_auth_method_t   sectype;
751 3267     globus_xio_attr_t                   attr = NULL;
752 3267     globus_l_soap_message_callback_handle_t * callback_handle;
753 3267     globus_result_t                     result = GLOBUS_SUCCESS;
754 3267     char *                              soap_action;
755 3267     char *                              http_version = NULL;
756 3267     char *                              connection = NULL;
757 3267     void *                              timeout = NULL;
758 3267     char *                              quoted_soap_action = NULL;
759 3267     GlobusFuncName(globus_soap_message_register_open);
760 3267     GlobusSoapMessageDebugEnter();
761
762 3267     globus_mutex_lock(&handle->cancel_mutex);
763 3267     handle->cancelled = 0;
764 3267     globus_mutex_unlock(&handle->cancel_mutex);
765
766 3267     callback_handle = (globus_l_soap_message_callback_handle_t *) 
767     globus_malloc(sizeof(globus_l_soap_message_callback_handle_t));
768 3267     if(!callback_handle)
769     {
770 0         result = GlobusSoapMessageErrorOutOfMemory;
771 0         goto exit;
772     }
773 3267     memset(callback_handle, 0, 
774            (sizeof(globus_l_soap_message_callback_handle_t)));
775
776 3267     if(handle->xio_handle)
777     {
778 0         result = GlobusSoapMessageErrorFailedTransport(
779             result, "Session already opened");
780 0         goto exit;
781     }
782
783 3267     callback_handle->callback = callback;
784 3267     callback_handle->args = args;
785 3267     callback_handle->message = handle;
786
787 3267     if(strncmp(endpoint, "https://", 8) == 0)
788     {
789 1396         result = globus_xio_handle_create(
790             &handle->xio_handle,
791             globus_i_soap_message_xio_https_stack);
792 1396         if(result != GLOBUS_SUCCESS)
793         {
794 0             result = GlobusSoapMessageErrorFailedTransport(
795                 result, "Failed to create xio handle with https stack");
796 0             goto exit;
797         }
798
799 1396         result = globus_xio_attr_init(&attr);
800 1396         if(result != GLOBUS_SUCCESS)
801         {
802 0             result = GlobusSoapMessageErrorFailedTransport(
803                 result, "Failed to initialize xio attr");
804 0             goto exit;
805         }
806
807 1396         result = globus_i_soap_message_setup_transport_security(
808             handle->attrs,
809             attr);
810 1396         if(result != GLOBUS_SUCCESS)
811         {
812 0             result = GlobusSoapMessageErrorFailedTransport(
813                 result, "Failed to initialize xio attributes for https");
814 0             goto exit;
815         }
816     }
817     else
818     {
819 1871         sectype = (globus_soap_message_auth_method_t)
820             globus_soap_message_handle_get_attr(
821                 handle,
822                 GLOBUS_SOAP_MESSAGE_AUTHENTICATION_METHOD_KEY);
823         
824 1871         if(sectype && (sectype == GLOBUS_SOAP_MESSAGE_AUTH_SECURE))
825         {
826             /* XXX may not be a good idea if users can 'set attrs' on this
827              * handle while it is open
828              */
829 0             globus_soap_message_handle_set_attr(
830                 handle,
831                 GLOBUS_SOAP_MESSAGE_AUTHENTICATION_METHOD_KEY,
832                 NULL,
833                 NULL,
834                 (void *) GLOBUS_SOAP_MESSAGE_AUTH_SECURE_MESSAGE);
835         }
836         
837 1871         result = globus_xio_handle_create(&handle->xio_handle, 
838                                           globus_i_soap_message_xio_stack);
839
840 1871         result = globus_xio_attr_init(&attr);
841 1871         if(result != GLOBUS_SUCCESS)
842         {
843 0             result = GlobusSoapMessageErrorFailedTransport(
844                 result, "Failed to initialize xio attr");
845 0             goto exit;
846         }
847     }
848
849 3267     timeout = globus_soap_message_handle_get_attr(
850         handle, GLOBUS_SOAP_MESSAGE_TIMEOUT_KEY);
851 3267     if(timeout)
852     {
853 0         result = globus_xio_attr_cntl(
854             attr,
855             GLOBUS_NULL,
856             GLOBUS_XIO_ATTR_SET_TIMEOUT_ALL,
857             globus_l_soap_message_timeout_callback,
858             timeout,
859             GLOBUS_NULL);
860 0         if(result != GLOBUS_SUCCESS)
861         {
862 0             result = GlobusSoapMessageErrorFailedTransport(
863                 result, "Failed to set timeout for xio handle");
864 0             goto exit;
865         }
866     }
867
868 3267     http_version = globus_soap_message_handle_get_attr(
869         handle, GLOBUS_SOAP_MESSAGE_HTTP_VERSION_KEY);
870 3267     if(http_version && !strcmp(http_version, "1.0"))
871     {
872 0         result = globus_xio_attr_cntl(
873             attr, 
874             globus_i_soap_message_http_driver, 
875             GLOBUS_XIO_HTTP_ATTR_SET_REQUEST_HTTP_VERSION, 
876             GLOBUS_XIO_HTTP_VERSION_1_0); 
877 0         if(result != GLOBUS_SUCCESS) 
878         { 
879 0             result = GlobusSoapMessageErrorFailedTransport( 
880                 result, "Failed to set HTTP version to 1.0"); 
881 0             goto exit; 
882         } 
883
884 0         result = globus_xio_attr_cntl( 
885             attr, 
886             globus_i_soap_message_http_driver, 
887             GLOBUS_XIO_HTTP_ATTR_DELAY_WRITE_HEADER); 
888 0         if(result != GLOBUS_SUCCESS) 
889         { 
890 0             result = GlobusSoapMessageErrorFailedTransport( 
891                 result, "Failed to set delay write of HTTP Header"); 
892 0             goto exit; 
893         } 
894     }
895
896 3267     result = globus_xio_attr_cntl(
897         attr, globus_i_soap_message_http_driver,
898         GLOBUS_XIO_HTTP_ATTR_SET_REQUEST_HEADER,
899         "Content-Type",
900         "text/xml; charset=utf-8");
901 3267     if(result != GLOBUS_SUCCESS)
902     {
903 0         result = GlobusSoapMessageErrorFailedTransport(
904             result, "Failed to set HTTP request header: Content-Type");
905 0         goto exit;
906     }
907
908 3267     result = globus_xio_attr_cntl(
909         attr, globus_i_soap_message_http_driver,
910         GLOBUS_XIO_HTTP_ATTR_SET_REQUEST_HEADER,
911         "Accept",
912         "text/xml");
913 3267     if(result != GLOBUS_SUCCESS)
914     {
915 0         result = GlobusSoapMessageErrorFailedTransport(
916             result, "Failed to set HTTP request header: Accept");
917 0         goto exit;
918     }
919
920 3267     connection = (char *) globus_soap_message_handle_get_attr(
921                 handle,
922                 GLOBUS_SOAP_MESSAGE_CONNECTION_KEY);
923 3267     if (connection && !strcmp(connection, "close"))
924     {
925 1982         result = globus_xio_attr_cntl(
926             attr, globus_i_soap_message_http_driver,
927             GLOBUS_XIO_HTTP_ATTR_SET_REQUEST_HEADER,
928             "Connection",
929             "close");
930 1982         if(result != GLOBUS_SUCCESS)
931         {
932 0             result = GlobusSoapMessageErrorFailedTransport(
933                 result, "Failed to set HTTP request header: Connection");
934 0             goto exit;
935         }
936     }
937
938 3267     soap_action = globus_soap_message_handle_get_attr(
939         handle, GLOBUS_SOAP_MESSAGE_SOAP_ACTION_KEY);
940 3267     if(!soap_action)
941     {
942 0         result = GlobusSoapMessageErrorFailedTransport(
943             result, "SOAPAction not set in message attributes");
944 0         goto exit;
945     }
946
947 3267     if (soap_action[0] != '"')
948     {
949         /* WS-I BP requires that SOAPAction be quoted */
950 3267         size_t                          soap_action_len;
951
952 3267         soap_action_len = strlen(soap_action);
953
954 3267         quoted_soap_action = malloc(soap_action_len + 3);
955
956 3267         memcpy(quoted_soap_action + 1, soap_action, soap_action_len);
957 3267         quoted_soap_action[0] = '"';
958 3267         quoted_soap_action[soap_action_len+1] = '"';
959 3267         quoted_soap_action[soap_action_len+2] = '\0';
960
961 3267         soap_action = quoted_soap_action;
962     }
963
964 3267     result = globus_xio_attr_cntl(
965         attr,
966         globus_i_soap_message_http_driver,
967         GLOBUS_XIO_HTTP_ATTR_SET_REQUEST_HEADER,
968         "SOAPAction",
969         soap_action);
970 3267     if(result != GLOBUS_SUCCESS)
971     {
972 0         result = GlobusSoapMessageErrorFailedTransport(
973             result, "Failed to set request method in http driver");
974 0         goto exit;
975     }
976     
977 3267     result = globus_xio_attr_cntl(
978         attr, globus_i_soap_message_http_driver,
979         GLOBUS_XIO_HTTP_ATTR_SET_REQUEST_METHOD,
980         "POST");
981 3267     if(result != GLOBUS_SUCCESS)
982     {
983 0         result = GlobusSoapMessageErrorFailedTransport(
984             result, "Failed to set request method in http driver");
985 0         goto exit;
986     }
987
988 3267     result = globus_xio_attr_cntl(attr,
989                                   globus_i_soap_message_tcp_driver,
990                                   GLOBUS_XIO_TCP_SET_NODELAY,
991                                   GLOBUS_TRUE);
992 3267     if(result != GLOBUS_SUCCESS)
993     {
994 0         result = GlobusSoapMessageErrorFailedTransport(
995             result, "Failed to set tcp nodelay.");
996 0         goto exit;
997     }
998
999
1000 3267     result = globus_xio_register_open(
1001         handle->xio_handle,
1002         endpoint,
1003         attr,
1004         globus_l_soap_message_open_callback,
1005         callback_handle);
1006 3267     if(result != GLOBUS_SUCCESS)
1007     {
1008 0         result = GlobusSoapMessageErrorFailedTransport(
1009             result, "Failed to connect to server");
1010 0         goto exit;
1011     }
1012
1013 3267     if(attr)
1014     {
1015 3267         globus_xio_attr_destroy(attr);
1016 3267         attr = NULL;
1017     }
1018
1019  exit:
1020
1021 3267     if(result != GLOBUS_SUCCESS)
1022     {
1023 0         free(callback_handle);
1024 0         if(attr)
1025         {
1026 0             globus_xio_attr_destroy(attr);
1027         }
1028     }
1029 3267     if (quoted_soap_action != NULL)
1030     {
1031 3267         free(quoted_soap_action);
1032     }
1033
1034 3267     GlobusSoapMessageDebugExit();
1035 3267     return result;
1036 }
1037
1038 globus_bool_t
1039 globus_soap_message_is_cancelled(
1040     globus_soap_message_handle_t        handle)
1041 3700 {
1042 3700     globus_bool_t                       cancelled;
1043
1044 3700     globus_mutex_lock(&handle->cancel_mutex);
1045 3700     cancelled = handle->cancelled;
1046 3700     globus_mutex_unlock(&handle->cancel_mutex);
1047
1048 3700     return cancelled;
1049 }
1050
1051 globus_result_t
1052 globus_soap_message_cancel_message(
1053     globus_soap_message_handle_t        handle)
1054 0 {
1055 0     globus_result_t                     result = GLOBUS_SUCCESS;
1056 0     GlobusFuncName(globus_soap_message_operations_cancel);
1057 0     GlobusSoapMessageDebugEnter();
1058
1059 0     globus_xio_handle_cancel_operations(
1060         handle->xio_handle, 
1061         GLOBUS_XIO_CANCEL_OPEN|
1062         GLOBUS_XIO_CANCEL_CLOSE|
1063         GLOBUS_XIO_CANCEL_READ|
1064         GLOBUS_XIO_CANCEL_WRITE);
1065     
1066 0     globus_mutex_lock(&handle->cancel_mutex);
1067 0     handle->cancelled = 1;
1068 0     globus_mutex_unlock(&handle->cancel_mutex);
1069     
1070 0     return result;
1071 }
1072
1073 globus_result_t
1074 globus_soap_message_register_write_request(
1075     globus_soap_message_handle_t        handle,
1076     globus_soap_message_callback_func_t callback,
1077     void *                              args,
1078     globus_bool_t                       response)
1079 3267 {
1080 3267     char                                content_length_buffer[100];
1081 3267     int                                 buffer_length;
1082 3267     static unsigned char                dummy_buffer[1];
1083 3267     globus_l_soap_message_callback_handle_t * callback_handle;
1084 3267     globus_result_t                     result = GLOBUS_SUCCESS;
1085 3267     globus_xio_data_descriptor_t        dd;
1086 3267     GlobusFuncName(globus_soap_message_register_write_request);
1087 3267     GlobusSoapMessageDebugEnter();
1088
1089 3267     callback_handle = (globus_l_soap_message_callback_handle_t *) 
1090     globus_malloc(sizeof(globus_l_soap_message_callback_handle_t));
1091 3267     if(!callback_handle)
1092     {
1093 0         result = GlobusSoapMessageErrorOutOfMemory;
1094 0         goto exit;
1095     }
1096 3267     memset(callback_handle, 0, 
1097            (sizeof(globus_l_soap_message_callback_handle_t)));
1098
1099 3267     callback_handle->callback = callback;
1100 3267     callback_handle->args = args;
1101 3267     callback_handle->message = handle;
1102 3267     callback_handle->type = (response ? GLOBUS_SOAP_MESSAGE_REQUEST_CALLBACK:
1103       GLOBUS_SOAP_MESSAGE_RESPONSE_CALLBACK);
1104
1105 3267     if(callback_handle->message->writer)
1106     {
1107 3267         xmlFreeTextWriter(callback_handle->message->writer);
1108 3267         callback_handle->message->writer = NULL;
1109     }
1110
1111 3267     result = globus_xio_handle_cntl(
1112         handle->xio_handle,
1113         globus_i_soap_message_buffer_driver,
1114         GLOBUS_XIO_BUFFER_GET_LENGTH,
1115         &buffer_length);
1116 3267     if(result != GLOBUS_SUCCESS)
1117     {
1118 0         result = GlobusSoapMessageErrorFailedTransport(
1119             result, "Failed to set get length of message");
1120 0         goto exit;
1121     }
1122
1123 3267     memset(content_length_buffer, 0, 100);
1124 3267     sprintf(content_length_buffer, "%d", buffer_length);
1125
1126 3267     result = globus_xio_handle_cntl(
1127         handle->xio_handle,
1128         globus_i_soap_message_http_driver,
1129         GLOBUS_XIO_HTTP_HANDLE_SET_REQUEST_HEADER,
1130         "Content-Length",
1131         content_length_buffer);
1132 3267     if(result != GLOBUS_SUCCESS)
1133     {
1134 0         result = GlobusSoapMessageErrorFailedTransport(
1135             result, "Failed to set Content-Length in HTTP header");
1136 0         goto exit;
1137     }
1138
1139 3267     if(GlobusSoapMessageDebug(GLOBUS_SOAP_MESSAGE_DEBUG_MESSAGES))
1140     {
1141 0         char *                          buffer;
1142 0         int                             read_length;
1143         
1144 0         globus_xio_handle_cntl(
1145             callback_handle->message->xio_handle,
1146             globus_i_soap_message_buffer_driver,
1147             GLOBUS_XIO_BUFFER_GET_MARKED_BUFFERS,
1148             NULL, NULL, &buffer, &read_length);
1149         
1150 0         GlobusSoapMessageDebugPrintf(
1151             GLOBUS_SOAP_MESSAGE_DEBUG_MESSAGES,
1152             ("----------------WRITING--------------\n%.*s\n"
1153              "=====================================\n\n",
1154              read_length, buffer));
1155         
1156 0         free(buffer);
1157     }
1158
1159 3267     result = globus_xio_data_descriptor_init(
1160             &dd,
1161             handle->xio_handle);
1162
1163 3267     if(result != GLOBUS_SUCCESS)
1164     {
1165 0         result = GlobusSoapMessageErrorFailedTransport(
1166             result, "Failed to init data descriptor");
1167 0         goto exit;
1168     }        
1169
1170 3267     result = globus_xio_data_descriptor_cntl(
1171             dd,
1172             globus_i_soap_message_buffer_driver,
1173             GLOBUS_XIO_BUFFER_FLUSH);
1174
1175 3267     if(result != GLOBUS_SUCCESS)
1176     {
1177 0         result = GlobusSoapMessageErrorFailedTransport(
1178             result, "Failed to set data descriptor to flush.");
1179 0         goto exit;
1180     }        
1181
1182 3267     result = globus_xio_register_write(
1183         handle->xio_handle, 
1184         dummy_buffer,
1185         0,
1186         0,
1187         dd,
1188         globus_l_soap_message_flush_callback,
1189         callback_handle);
1190
1191 3267     if(result != GLOBUS_SUCCESS)
1192     {
1193 0         result = GlobusSoapMessageErrorFailedTransport(
1194             result, "Failed to write message");
1195 0         goto exit;
1196     }        
1197 3267     globus_xio_data_descriptor_destroy(dd);
1198
1199  exit:
1200
1201 3267     if(result != GLOBUS_SUCCESS)
1202     {
1203 0         free(callback_handle);
1204     }
1205
1206 3267     GlobusSoapMessageDebugExit();
1207 3267     return result;
1208 }
1209
1210 globus_result_t
1211 globus_soap_message_register_write_response(
1212     globus_soap_message_handle_t        handle,
1213     globus_soap_message_callback_func_t callback,
1214     void *                              args)
1215 2424 {
1216 2424     char                                content_length_buffer[100];
1217 2424     char *                              connection;
1218 2424     int                                 buffer_length;
1219 2424     static unsigned char                dummy_buffer[1];
1220 2424     globus_l_soap_message_callback_handle_t * callback_handle;
1221 2424     globus_result_t                     result = GLOBUS_SUCCESS;
1222 2424     GlobusFuncName(globus_soap_message_register_write_response);
1223 2424     GlobusSoapMessageDebugEnter();
1224
1225 2424     callback_handle = (globus_l_soap_message_callback_handle_t *) 
1226     globus_malloc(sizeof(globus_l_soap_message_callback_handle_t));
1227 2424     if(!callback_handle)
1228     {
1229 0         result = GlobusSoapMessageErrorOutOfMemory;
1230 0         goto exit;
1231     }
1232 2424     memset(callback_handle, 0, 
1233            (sizeof(globus_l_soap_message_callback_handle_t)));
1234
1235 2424     callback_handle->callback = callback;
1236 2424     callback_handle->args = args;
1237 2424     callback_handle->message = handle;
1238 2424     callback_handle->type = GLOBUS_SOAP_MESSAGE_RESPONSE_CALLBACK;
1239
1240 2424     if(callback_handle->message->writer)
1241     {
1242 2424         xmlFreeTextWriter(callback_handle->message->writer);
1243 2424         callback_handle->message->writer = NULL;
1244     }
1245
1246 2424     result = globus_xio_handle_cntl(
1247         handle->xio_handle,
1248         globus_i_soap_message_buffer_driver,
1249         GLOBUS_XIO_BUFFER_GET_LENGTH,
1250         &buffer_length);
1251 2424     if(result != GLOBUS_SUCCESS)
1252     {
1253 0         result = GlobusSoapMessageErrorFailedTransport(
1254             result, "Failed to set get length of message");
1255 0         goto exit;
1256     }
1257
1258 2424     memset(content_length_buffer, 0, 100);
1259 2424     sprintf(content_length_buffer, "%d", buffer_length);
1260
1261 2424     result = globus_xio_handle_cntl(
1262         handle->xio_handle,
1263         globus_i_soap_message_http_driver,
1264         GLOBUS_XIO_HTTP_HANDLE_SET_RESPONSE_HEADER,
1265         "Content-Length",
1266         content_length_buffer);
1267 2424     if(result != GLOBUS_SUCCESS)
1268     {
1269 0         result = GlobusSoapMessageErrorFailedTransport(
1270             result, "Failed to set Content-Length in HTTP header");
1271 0         goto exit;
1272     }
1273
1274 2424     connection = globus_soap_message_handle_get_attr(
1275         handle,
1276         GLOBUS_SOAP_MESSAGE_CONNECTION_KEY);
1277
1278 2424     if (connection && !strcmp(connection, "close"))
1279     {
1280 91         result = globus_xio_handle_cntl(
1281             handle->xio_handle,
1282             globus_i_soap_message_http_driver,
1283             GLOBUS_XIO_HTTP_HANDLE_SET_RESPONSE_HEADER,
1284             "Connection",
1285             "close");
1286
1287 91         if(result != GLOBUS_SUCCESS)
1288         {
1289 0             result = GlobusSoapMessageErrorFailedTransport(
1290                 result, "Failed to set Connection in HTTP header");
1291 0             goto exit;
1292         }
1293     }
1294
1295 2424     if(GlobusSoapMessageDebug(GLOBUS_SOAP_MESSAGE_DEBUG_MESSAGES))
1296     {
1297 0         char *                          buffer;
1298 0         int                             read_length;
1299         
1300 0         globus_xio_handle_cntl(
1301             callback_handle->message->xio_handle,
1302             globus_i_soap_message_buffer_driver,
1303             GLOBUS_XIO_BUFFER_GET_MARKED_BUFFERS,
1304             NULL, NULL, &buffer, &read_length);
1305         
1306 0         GlobusSoapMessageDebugPrintf(
1307             GLOBUS_SOAP_MESSAGE_DEBUG_MESSAGES,
1308             ("----------------WRITING--------------\n%.*s\n"
1309              "=====================================\n\n",
1310              read_length, buffer));
1311         
1312 0         free(buffer);
1313     }
1314
1315 2424     if(buffer_length > 0)
1316     {
1317 2394         globus_xio_data_descriptor_t    dd;
1318
1319 2394         result = globus_xio_data_descriptor_init(
1320                 &dd,
1321                 handle->xio_handle);
1322
1323 2394         if(result != GLOBUS_SUCCESS)
1324         {
1325 0             result = GlobusSoapMessageErrorFailedTransport(
1326                 result, "Failed to init data descriptor");
1327 0             goto exit;
1328         }        
1329
1330 2394         result = globus_xio_data_descriptor_cntl(
1331                 dd,
1332                 globus_i_soap_message_buffer_driver,
1333                 GLOBUS_XIO_BUFFER_FLUSH);
1334
1335 2394         if(result != GLOBUS_SUCCESS)
1336         {
1337 0             result = GlobusSoapMessageErrorFailedTransport(
1338                 result, "Failed to set data descriptor to flush.");
1339 0             goto exit;
1340         }        
1341
1342 2394         result = globus_xio_register_write(
1343             handle->xio_handle, 
1344             dummy_buffer,
1345             0,
1346             0,
1347             dd,
1348             globus_l_soap_message_flush_callback,
1349             callback_handle);
1350
1351 2394         if(result != GLOBUS_SUCCESS)
1352         {
1353 0             result = GlobusSoapMessageErrorFailedTransport(
1354                 result, "Failed to write message");
1355 0             goto exit;
1356         }        
1357     }
1358     else
1359     {
1360 30         globus_xio_handle_cntl(
1361             handle->xio_handle,
1362             globus_i_soap_message_http_driver,
1363             GLOBUS_XIO_HTTP_HANDLE_SET_END_OF_ENTITY);
1364
1365 30         callback_handle->callback(result, callback_handle->args);
1366
1367 30         free(callback_handle);
1368 30         callback_handle = NULL;
1369     }        
1370
1371  exit:
1372
1373 2424     if(result != GLOBUS_SUCCESS && callback_handle != NULL)
1374     {
1375 0         free(callback_handle);
1376     }
1377
1378 2424     GlobusSoapMessageDebugExit();
1379 2424     return result;
1380 }
1381
1382 globus_result_t
1383 globus_soap_message_register_read_response(
1384     globus_soap_message_handle_t        handle,
1385     globus_soap_message_callback_func_t callback,
1386     void *                              args)
1387 3247 {
1388 3247     globus_l_soap_message_callback_handle_t *  callback_handle;
1389 3247     globus_result_t                     result = GLOBUS_SUCCESS;
1390 3247     GlobusFuncName(globus_soap_message_register_read_response);
1391 3247     GlobusSoapMessageDebugEnter();
1392
1393
1394 3247     callback_handle = globus_malloc(
1395         sizeof(globus_l_soap_message_callback_handle_t));
1396 3247     if(!callback_handle)
1397     {
1398 0         result = GlobusSoapMessageErrorOutOfMemory;
1399 0         goto exit;
1400     }
1401 3247     memset(callback_handle, 0, 
1402            (sizeof(globus_l_soap_message_callback_handle_t)));
1403
1404 3247     callback_handle->callback = callback;
1405 3247     callback_handle->args = args;
1406 3247     callback_handle->message = handle;
1407
1408 3247     globus_mutex_lock(&handle->mutex);
1409 3247     handle->response_semaphore++;
1410
1411 3247     if(handle->response_semaphore > 1)
1412     {
1413 0         globus_mutex_unlock(&handle->mutex);
1414 0         result = globus_callback_register_oneshot(
1415             NULL,
1416             &globus_i_reltime_zero,
1417             globus_l_soap_message_response_callback,
1418             callback_handle);
1419 0         if(result != GLOBUS_SUCCESS)
1420         {
1421 0             result = GlobusSoapMessageErrorFailedTransport(
1422                 result, "Failed to register periodic callbcak for response");
1423 0             goto exit;
1424         }
1425     }
1426     else
1427     {
1428 3247         globus_mutex_unlock(&handle->mutex);
1429 3247         handle->response_handle = (void *)callback_handle;
1430     }
1431
1432  exit:
1433
1434 3247     GlobusSoapMessageDebugExit();
1435 3247     return result;
1436 }
1437
1438 globus_result_t
1439 globus_soap_message_register_read_request(
1440     globus_soap_message_handle_t        handle,
1441     globus_soap_message_callback_func_t callback,
1442     void *                              args)
1443 2333 {
1444 2333     globus_l_soap_message_callback_handle_t *  callback_handle;
1445 2333     globus_result_t                     result = GLOBUS_SUCCESS;
1446 2333     GlobusFuncName(globus_soap_message_register_read_request);
1447 2333     GlobusSoapMessageDebugEnter();
1448
1449 2333     callback_handle = globus_malloc(
1450         sizeof(globus_l_soap_message_callback_handle_t));
1451 2333     if(!callback_handle)
1452     {
1453 0         result = GlobusSoapMessageErrorOutOfMemory;
1454 0         goto exit;
1455     }
1456 2333     memset(callback_handle, 0, 
1457            (sizeof(globus_l_soap_message_callback_handle_t)));
1458
1459 2333     callback_handle->callback = callback;
1460 2333     callback_handle->args = args;
1461 2333     callback_handle->message = handle;
1462             
1463 2333     result = globus_xio_handle_cntl(
1464         callback_handle->message->xio_handle,
1465         globus_i_soap_message_buffer_driver,
1466         GLOBUS_XIO_BUFFER_ENABLE_READ_BUFFERING);
1467 2333     if(result != GLOBUS_SUCCESS)
1468     {
1469 0         result = GlobusSoapMessageErrorFailedTransport(
1470             result, "Failed to enable read buffering in buffer driver");
1471 0         goto exit;
1472     }
1473
1474 2333     result = globus_xio_register_read(
1475         handle->xio_handle,
1476         (globus_byte_t *)handle->readbuf,
1477         GLOBUS_I_SOAP_MESSAGE_READBUF_SIZE,
1478         1,
1479         NULL,
1480         globus_l_soap_message_read_callback,
1481         callback_handle);
1482 2333     if(result != GLOBUS_SUCCESS)
1483     {
1484 0         result = GlobusSoapMessageErrorFailedTransport(
1485             result, "Failed to begin reading SOAP message");
1486         goto exit;
1487     }
1488
1489  exit:
1490
1491 2333     GlobusSoapMessageDebugExit();
1492 2333     return result;
1493 }
1494
1495 typedef struct
1496 {
1497     globus_soap_message_callback_func_t callback;
1498     void *                              args;
1499 } globus_l_soap_message_close_callback_t;
1500
1501 void
1502 globus_l_soap_message_register_close_callback(
1503     globus_xio_handle_t                 handle,
1504     globus_result_t                     result,
1505     void *                              args)
1506 4495 {
1507 4495     globus_l_soap_message_close_callback_t * callback_handle;
1508
1509 4495     callback_handle = (globus_l_soap_message_close_callback_t *) args;
1510
1511 4495     callback_handle->callback(result, callback_handle->args);
1512
1513 4495     free(callback_handle);
1514 }
1515
1516 globus_result_t
1517 globus_soap_message_register_close(
1518     globus_soap_message_handle_t        handle,
1519     globus_soap_message_callback_func_t callback,
1520     void *                              args)
1521 4495 {
1522 4495     globus_result_t                     result = GLOBUS_SUCCESS;
1523 4495     globus_l_soap_message_close_callback_t * callback_handle;
1524 4495     GlobusFuncName(globus_soap_message_register_close);
1525 4495     GlobusSoapMessageDebugEnter();
1526
1527 4495     if(handle->reader)
1528     {
1529 3247         xmlFreeTextReader(handle->reader);
1530     }
1531 4495     handle->reader = NULL;
1532 4495     if (handle->doc_to_free)
1533     {
1534 3003         xmlFreeDoc(handle->doc_to_free);
1535 3003         handle->doc_to_free = NULL;
1536     }
1537
1538 4495     callback_handle = globus_malloc(
1539         sizeof(globus_l_soap_message_close_callback_t));
1540 4495     if(!callback_handle)
1541     {
1542 0         result = GlobusSoapMessageErrorOutOfMemory;
1543 0         goto exit;
1544     }
1545 4495     callback_handle->callback = callback;
1546 4495     callback_handle->args = args;
1547
1548 4495     globus_xio_register_close(
1549         handle->xio_handle,
1550         NULL,
1551         globus_l_soap_message_register_close_callback,
1552         callback_handle);
1553
1554 4495     handle->xio_handle = NULL;
1555
1556  exit:
1557 4495     GlobusSoapMessageDebugExit();
1558 4495     return result;
1559 }
1560
1561 globus_result_t
1562 globus_i_soap_message_reset_reader(
1563     globus_soap_message_handle_t        handle)
1564 1236 {
1565 1236     globus_result_t                     result = GLOBUS_SUCCESS;
1566 1236     GlobusFuncName(globus_i_soap_message_reset_reader);
1567 1236     GlobusSoapMessageDebugEnter();
1568
1569 1236     if(handle->reader)
1570     {
1571 0         xmlFreeTextReader(handle->reader);
1572     }
1573 1236     if (handle->doc_to_free)
1574     {
1575 0         xmlFreeDoc(handle->doc_to_free);
1576 0         handle->doc_to_free = NULL;
1577     }
1578
1579 1236     handle->buffer_eof = 0;
1580     
1581 1236     handle->reader = xmlReaderForIO(
1582         globus_l_soap_message_handle_libxml_io_read_callback,
1583         globus_l_soap_message_handle_libxml_io_close_callback,
1584         handle,
1585         NULL,
1586         NULL,
1587         0);
1588 1236     if(!handle->reader)
1589     {
1590 0         result = GlobusSoapMessageErrorInitFailed(
1591             "Failed to initialize xmlReader");
1592 0         goto exit;
1593     }
1594
1595 1236     xmlTextReaderSetErrorHandler(handle->reader, 
1596                                  globus_l_soap_message_error_callback, 
1597                                  handle);
1598     
1599 1236     xmlTextReaderSetStructuredErrorHandler(
1600         handle->reader,
1601         globus_l_soap_message_structured_error_callback,
1602         handle);
1603     
1604  exit:
1605
1606 1236     GlobusSoapMessageDebugExit();
1607 1236     return result;
1608 }
1609
1610 globus_result_t
1611 globus_i_soap_message_setup_transport_security(
1612     globus_soap_message_attr_t          attrs,
1613     globus_xio_attr_t                   xio_attr)
1614 1398 {
1615 1398     globus_xio_gsi_authorization_mode_t         gsi_authz;
1616 1398     globus_soap_message_auth_protection_level_t protect;
1617 1398     globus_soap_message_authz_method_t          authz;
1618 1398     void *                                      credential;
1619 1398     void *                                      target_name;
1620 1398     globus_result_t                             result = GLOBUS_SUCCESS;
1621 1398     GlobusFuncName(globus_l_soap_message_setup_transport_security);
1622 1398     GlobusSoapMessageDebugEnter();
1623
1624 1398     credential = globus_soap_message_attr_get(
1625         attrs,
1626         GLOBUS_SOAP_MESSAGE_USER_CREDENTIAL_KEY);
1627 1398     if(credential)
1628     {
1629 0         result = globus_xio_attr_cntl(
1630             xio_attr,
1631             globus_i_soap_message_gsi_driver,
1632             GLOBUS_XIO_GSI_SET_CREDENTIAL,
1633             credential);
1634 0         if(result != GLOBUS_SUCCESS)
1635         {
1636 0             result = GlobusSoapMessageErrorFailedTransport(
1637                 result, "Failed to set credential for gsi driver");
1638 0             goto exit;
1639         }
1640     }
1641
1642 1398     result = globus_xio_attr_cntl(
1643         xio_attr,
1644         globus_i_soap_message_gsi_driver,
1645         GLOBUS_XIO_GSI_SET_DELEGATION_MODE,
1646         GLOBUS_XIO_GSI_DELEGATION_MODE_NONE);
1647 1398     if(result != GLOBUS_SUCCESS)
1648     {
1649 0         result = GlobusSoapMessageErrorFailedTransport(
1650             result, "Failed to set delegation mode for gsi driver");
1651 0         goto exit;
1652     }        
1653
1654 1398     result = globus_xio_attr_cntl(
1655         xio_attr,
1656         globus_i_soap_message_gsi_driver,
1657         GLOBUS_XIO_GSI_SET_SSL_COMPATIBLE,
1658         1);
1659 1398     if(result != GLOBUS_SUCCESS)
1660     {
1661 0         result = GlobusSoapMessageErrorFailedTransport(
1662             result, "Failed to set delegation mode for gsi driver");
1663 0         goto exit;
1664     }        
1665
1666 1398     protect = 
1667     (globus_soap_message_auth_protection_level_t)
1668     globus_soap_message_attr_get(
1669         attrs,
1670         GLOBUS_SOAP_MESSAGE_AUTH_PROTECTION_KEY);
1671 1398     if(protect != GLOBUS_SOAP_MESSAGE_AUTH_PROTECTION_NOT_SET)
1672     {
1673 0         result = globus_xio_attr_cntl(
1674             xio_attr,
1675             globus_i_soap_message_gsi_driver,
1676             GLOBUS_XIO_GSI_SET_PROTECTION_LEVEL,
1677             ((protect == GLOBUS_SOAP_MESSAGE_AUTH_PROTECTION_INTEGRITY) ?
1678              GLOBUS_XIO_GSI_PROTECTION_LEVEL_INTEGRITY :
1679              GLOBUS_XIO_GSI_PROTECTION_LEVEL_PRIVACY));
1680 0         if(result != GLOBUS_SUCCESS)
1681         {
1682 0             result = GlobusSoapMessageErrorFailedTransport(
1683                 result, "Failed to set delegation mode for gsi driver");
1684 0             goto exit;
1685         }        
1686     }
1687
1688 1398     authz = 
1689     (globus_soap_message_authz_method_t)
1690     globus_soap_message_attr_get(
1691         attrs,
1692         GLOBUS_SOAP_MESSAGE_AUTHZ_METHOD_KEY);
1693     
1694 1398     switch(authz)
1695     {
1696     case GLOBUS_SOAP_MESSAGE_AUTHZ_SELF:
1697 1398         gsi_authz = GLOBUS_XIO_GSI_SELF_AUTHORIZATION;
1698 1398         break;
1699     case GLOBUS_SOAP_MESSAGE_AUTHZ_IDENTITY:
1700 0         gsi_authz = GLOBUS_XIO_GSI_IDENTITY_AUTHORIZATION;
1701 0         break;
1702     case GLOBUS_SOAP_MESSAGE_AUTHZ_HOST:
1703 0         gsi_authz = GLOBUS_XIO_GSI_HOST_AUTHORIZATION;
1704 0         break;
1705     case GLOBUS_SOAP_MESSAGE_AUTHZ_NONE:
1706 0         gsi_authz = GLOBUS_XIO_GSI_NO_AUTHORIZATION;
1707 0         break;
1708     default:
1709 0         gsi_authz = GLOBUS_XIO_GSI_SELF_AUTHORIZATION;
1710     }
1711
1712 1398     result = globus_xio_attr_cntl(
1713         xio_attr,
1714         globus_i_soap_message_gsi_driver,
1715         GLOBUS_XIO_GSI_SET_AUTHORIZATION_MODE,
1716         gsi_authz);
1717 1398     if(result != GLOBUS_SUCCESS)
1718     {
1719 0         result = GlobusSoapMessageErrorFailedTransport(
1720             result, "Failed to set delegation mode for gsi driver");
1721 0         goto exit;
1722     }        
1723
1724 1398     target_name = globus_soap_message_attr_get(
1725         attrs,
1726         GLOBUS_SOAP_MESSAGE_AUTHZ_TARGET_NAME_KEY);
1727 1398     if(target_name)
1728     {
1729 0         result = globus_xio_attr_cntl(
1730             xio_attr,
1731             globus_i_soap_message_gsi_driver,
1732             GLOBUS_XIO_GSI_SET_TARGET_NAME,
1733             target_name);
1734 0         if(result != GLOBUS_SUCCESS)
1735         {
1736 0             result = GlobusSoapMessageErrorFailedTransport(
1737                 result, "Failed to set target name on gsi driver");
1738 0             goto exit;
1739         }
1740     }
1741
1742 1398     if (globus_soap_message_attr_get(attrs, GLOBUS_SOAP_MESSAGE_AUTH_ANONYMOUS_KEY))
1743     {
1744 0         result = globus_xio_attr_cntl(
1745                 xio_attr,
1746                 globus_i_soap_message_gsi_driver,
1747                 GLOBUS_XIO_GSI_SET_ANON);
1748 0         if(result != GLOBUS_SUCCESS)
1749         {
1750 0             result = GlobusSoapMessageErrorFailedTransport(
1751                 result, "Failed to set target name on gsi driver");
1752             goto exit;
1753         }
1754     }
1755
1756 exit:
1757
1758 1398     GlobusSoapMessageDebugExit();
1759 1398     return result;