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
19 #ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
20
21 #include "globus_i_soap_client.h"
22
23 static
24 void
25 globus_l_soap_client_blocking_request_callback(
26     globus_soap_client_handle_t         request,
27     void *                              arg,
28     globus_result_t                     result);
29
30 static
31 void
32 globus_l_soap_client_blocking_response_callback(
33     globus_soap_client_handle_t         request,
34     void *                              arg,
35     globus_result_t                     result,
36     void *                              output,
37     int                                 fault_type,
38     xsd_any *                           fault);
39 #endif /* GLOBUS_DONT_DOCUMENT_INTERNAL */
40
41 /**
42  * Invoke a SOAP operation in a nonblocking way.
43  * @ingroup globus_soap_client
44  *
45  * Begins processing a SOAP operation and will handle both the message
46  * request and (if applicable) the server's response to the operation
47  * request. The @a callback function will be invoked once the operation
48  * has completed.
49  *
50  * @param handle
51  *     The SOAP client handle to use for state while processing this
52  *     request.
53  * @param endpoint
54  *     The URI of the endpoint to send the SOAP operation request to.
55  * @param operation
56  *     The description of the operation and its serializers and deserializers.
57  *     This must not be modified until the operation and its response have
58  *     been processed by the client handle.
59  * @param input
60  *     The operation's input element value. A copy of this value will be made
61  *     by this function, so this parameter's value may be freed or otherwise
62  *     modified by the caller after this function returns.
63  * @param callback
64  *     Callback function to invoke once the operation response has been handled.
65  * @param user_args
66  *     Application-specific argument to the callback function.
67  *
68  * @retval GLOBUS_SUCCESS
69  *     Processing of this operation has begun successfully.
70  * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_CLIENT_ALREADY_INVOKED
71  *     Processing the operation failed because the client is already actively
72  *     handling a request or response.
73  * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_INIT_FAILED
74  *     Processing the operation failed because the client could not initialize
75  *     some part of its data.
76  * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_CLIENT_REQUEST_FAILED
77  *     Processing the operation failed because the client could not initialize
78  *     some part of its data.
79  */
80 globus_result_t
81 globus_soap_client_operation_register(
82     globus_soap_client_handle_t         handle,
83     const char *                        endpoint,
84     const globus_soap_client_operation_t *
85                                         operation,
86     void *                              input,
87     globus_soap_client_response_callback_func_t
88                                         callback,
89     void *                              user_args)
90 3700 {
91 3700     globus_result_t                     result = GLOBUS_SUCCESS;
92
93 3700     handle->response.callback = callback;
94 3700     handle->response.args = user_args;
95
96 3700     result = globus_soap_client_register_request(
97         handle,
98         endpoint,
99         operation,
100         input,
101         globus_l_soap_client_blocking_request_callback,
102         handle);
103
104 3700     return result;
105 }
106 /* globus_soap_client_operation_register() */
107
108 /**
109  * Invoke a SOAP operation in a blocking way.
110  * @ingroup globus_soap_client
111  *
112  * Process a SOAP operation and will handle both the message
113  * request and (if applicable) the server's response to the operation
114  * request. This function will not return until both are handled. When this
115  * function returns, the @a output, @a fault, and @a fault_type parameters
116  * will be modified to point to values returned from the service. The
117  * @a output and @a fault must be freed by the caller.
118  *
119  * @param handle
120  *     The SOAP client handle to use for state while processing this
121  *     request.
122  * @param endpoint
123  *     The URI of the endpoint to send the SOAP operation request to.
124  * @param operation
125  *     The description of the operation and its serializers and deserializers.
126  *     This must not be modified until the operation and its response have
127  *     been processed by the client handle.
128  * @param input
129  *     The operation's input element value. 
130  * @param output
131  *     A pointer to be set to the operation's output elmeent value. The value
132  *     which this is set to must be freed by the caller.
133  * @param fault_type
134  *     A pointer to be set to the enumeration value of the fault type if a fault
135  *     was detected by the service while processing the operation.
136  * @param fault
137  *     A pointer to be set to the value of the fault which occurred. This will
138  *     be set to NULL if no fault occurred. If this is set to a non-NULL value,
139  *     the value must be freed by the caller.
140  *
141  * @retval GLOBUS_SUCCESS
142  *     Processing of this operation has begun successfully.
143  * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_CLIENT_ALREADY_INVOKED
144  *     Processing the operation failed because the client is already actively
145  *     handling a request or response.
146  * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_INIT_FAILED
147  *     Processing the operation failed because the client could not initialize
148  *     some part of its data.
149  * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_CLIENT_REQUEST_FAILED
150  *     Processing the operation failed because the client could not initialize
151  *     some part of its data.
152  */
153 globus_result_t
154 globus_soap_client_operation(
155     globus_soap_client_handle_t         handle,
156     const char *                        endpoint,
157     const globus_soap_client_operation_t *
158                                         operation,
159     void *                              input,
160     void **                             output,
161     int *                               fault_type,
162     xsd_any **                          fault)
163 3700 {
164 3700     globus_result_t                     result = GLOBUS_SUCCESS;
165
166 3700     if (output != NULL)
167     {
168 3700         *output = NULL;
169     }
170 3700     if (fault_type != NULL)
171     {
172 3700         *fault_type = 0;
173     }
174
175 3700     if (fault != NULL)
176     {
177 3700         *fault = NULL;
178     }
179     
180 3700     result = globus_soap_client_operation_register(
181         handle, 
182         endpoint,
183         operation,
184         input,
185         globus_l_soap_client_blocking_response_callback,
186         NULL);
187
188 3700     if(result != GLOBUS_SUCCESS)
189     {
190 0         goto exit;
191     }
192
193 3700     globus_mutex_lock(&handle->mutex);
194 19047     while(!handle->done)
195     {
196 15347         globus_cond_wait(&handle->cond, &handle->mutex);
197     }
198 3700     handle->done = GLOBUS_FALSE;
199 3700     globus_mutex_unlock(&handle->mutex);
200
201 3700     result = handle->response.result;
202 3700     if(result != GLOBUS_SUCCESS)
203     {
204 80         if (fault_type)
205         {
206 80             *fault_type = handle->response.fault_type;
207         }
208 80         if (fault)
209         {
210 80             *fault = handle->response.fault;
211         }
212
213 80         handle->response.fault = NULL;
214 80         handle->response.fault_type = 0;
215 80         handle->response.result = GLOBUS_SUCCESS;
216
217 80         goto exit;
218     }
219
220
221 3620     if (output != NULL &&
222         operation->output_type_info != NULL &&
223         handle->response.output != NULL)
224     {
225 3620         *output = handle->response.output;
226
227 3620         handle->response.output = NULL;
228     }
229
230  exit:
231 3700     return result;
232 }
233 /* globus_soap_client_operation() */
234
235 #ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
236 static
237 void
238 globus_l_soap_client_blocking_request_callback(
239     globus_soap_client_handle_t         handle,
240     void *                              arg,
241     globus_result_t                     error)
242 3700 {
243 3700     globus_result_t                     result = GLOBUS_SUCCESS;
244
245 3700     if(error != GLOBUS_SUCCESS ||
246        globus_soap_message_is_cancelled(handle->message))
247     {
248 0         handle->response.callback(
249             handle,
250             handle->response.args,
251             error,
252             NULL,
253             0,
254             NULL);
255     }
256     else
257     {
258 3700         result = globus_soap_client_register_response(
259             handle,
260             handle->response.callback,
261             handle->response.args);
262
263 3700         if(result != GLOBUS_SUCCESS)
264         {
265 0             handle->response.callback(
266                 handle,
267                 handle->response.args,
268                 result,
269                 NULL,
270                 0,
271                 NULL);
272         }
273
274     }
275 }
276 /* globus_l_soap_client_blocking_request_callback() */
277
278 static
279 void
280 globus_l_soap_client_blocking_response_callback(
281     globus_soap_client_handle_t         handle,
282     void *                              arg,
283     globus_result_t                     error,
284     void *                              output,
285     int                                 fault_type,
286     xsd_any *                           fault)
287 3700 {
288 3700     globus_mutex_lock(&handle->mutex);
289 3700     handle->response.result = error;
290 3700     handle->done = GLOBUS_TRUE;
291 3700     globus_cond_signal(&handle->cond); 
292 3700     globus_mutex_unlock(&handle->mutex);
293 }
294 /* globus_l_soap_client_blocking_response_callback() */