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