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 #include "globus_soap_message.h"
18 #include "globus_wsrf_resource.h"
19 #include "globus_service_engine.h"
20 #include "globus_operation_provider.h"
21 #include "globus_service_registry.h"
22 #include "globus_wsrf_core_tools.h"
23
24 #include "xsd_dateTime.h"
25
26 #include "wsrl_SetTerminationTimeType.h"
27 #include "wsrl_SetTerminationTimeResponseType.h"
28
29 #include "wsrl_TerminationTime.h"
30 #include "wsrl_CurrentTime.h"
31
32 #include "wsr_ResourceUnknownFault.h"
33 #include "wsrl_UnableToSetTerminationTimeFault.h"
34
35 #include "version.h"
36
37
38 /**
39 * @page wsrl_ScheduledResourceTermination_provider ScheduledResourceTermination Provider
40 *
41 * <h2>Provider Usage Overview</h2>
42 * This operation provider implements the ScheduledResourceTermination portType
43 * defined in http://docs.oasis-open.org/wsrf/rlw-2
44 .
45 * This portType consists of the @a SetTerminationTime operation, @a
46 * TerminationTime and @a CurrentTime resource properties, and
47 * related faults.
48 *
49 * The WSRF service engine will automatically register this provider to handle
50 * the SetTerminationTime operation for services which use the port type.
51 *
52 * <h2>Notes</h2>
53 * - The CurrentTime and TerminationTime resource properties are stored in GMT.
54 *
55 * <h2>Limitations</h2>
56 * - This provider does not implement any policies regarding what is an
57 * acceptable change of the TerminationTime. The
58 * TerminationTimeChangeRejectedFaultType is never issued by this provider.
59 */
60
61 /* Prototypes */
62 static
63 globus_result_t
64 wsrl_ScheduledResourceTermination_init_resource(
65 const struct wsa_EndpointReferenceType_s * epr);
66
67 static
68 globus_result_t
69 wsrl_SetTerminationTime_provider(
70 globus_service_engine_t engine,
71 globus_soap_message_handle_t handle,
72 globus_service_descriptor_t * service,
73 wsrl_SetTerminationTimeType * SetTerminationTime,
74 wsrl_SetTerminationTimeResponseType *
75 SetTerminationTimeResponse,
76 xsd_any * fault);
77
78 static
79 globus_bool_t
80 wsrl_deny_callback(
81 void * arg,
82 const xsd_QName * qname,
83 void * property);
84
85 static
86 void
87 wsrl_CurrentTime_callback(
88 void * arg,
89 const xsd_QName * qname,
90 void ** property);
91
92 static
93 time_t
94 wsrl_l_timegm(
95 const struct tm * tm);
96
97 static
98 int
99 wsrl_ScheduledResourceTermination_activate(void);
100
101 static
102 int
103 wsrl_ScheduledResourceTermination_deactivate(void);
104
105 /* Local Variables */
106 static xsd_QName wsrl_SetTerminationTime_qname =
107 {
108 "http://docs.oasis-open.org/wsrf/rlw-2/providers",
109 "SetTerminationTime"
110 };
111
112 static
113 globus_operation_provider_descriptor_t
114 wsrl_SetTerminationTime_descriptor =
115 {
116 &wsrl_SetTerminationTime_qname,
117 "SetTerminationTime",
118 (void *)wsrl_SetTerminationTime_provider,
119 wsrl_ScheduledResourceTermination_init_resource
120 };
121
122 GlobusExtensionDefineModule(globus_wsrl_ScheduledResourceTermination_provider) =
123 {
124 "globus_wsrl_ScheduledResourceTermination_provider",
125 wsrl_ScheduledResourceTermination_activate,
126 wsrl_ScheduledResourceTermination_deactivate,
127 NULL,
128 NULL,
129 &local_version
130 };
131
132 /* Implementation */
133 static
134 globus_result_t
135 wsrl_ScheduledResourceTermination_init_resource(
136 const struct wsa_EndpointReferenceType_s * epr)
137 292 {
138 globus_resource_t resource;
139 globus_result_t result;
140 globus_abstime_t destroy_time;
141 292 xsd_dateTime * destroy_time_value = NULL;
142 time_t destroy_time_t;
143 struct tm * tm_res;
144
145 292 result = globus_wsrf_core_get_resource_from_epr(epr, &resource);
146
147 292 if (result != GLOBUS_SUCCESS)
148 {
149 0 goto out;
150 }
151
152 /* Check if the destroy time was set before this provider was initialized.
153 * If so, we'll initialize our resource property to match that time.
154 */
155 292 result = globus_resource_get_destroy_time(
156 resource,
157 &destroy_time);
158
159 292 if (result != GLOBUS_SUCCESS)
160 {
161 0 goto finish_out;
162 }
163
164 292 if (destroy_time.tv_sec != 0 || destroy_time.tv_nsec != 0)
165 {
166 6 result = xsd_dateTime_init(&destroy_time_value);
167
168 6 if (result != GLOBUS_SUCCESS)
169 {
170 0 goto finish_out;
171 }
172
173 6 destroy_time_t = (time_t) destroy_time.tv_sec;
174
175 6 tm_res = globus_libc_gmtime_r(
176 &destroy_time_t,
177 destroy_time_value);
178
179 6 if (tm_res == NULL)
180 {
181 0 result = globus_error_put(GLOBUS_ERROR_NO_INFO);
182
183 0 goto finish_out;
184 }
185 }
186
187 292 result = globus_resource_create_property(
188 resource,
189 &wsrl_TerminationTime_qname,
190 &xsd_dateTime_info,
191 destroy_time_value);
192
193 292 if (result != GLOBUS_SUCCESS)
194 {
195 0 goto finish_out;
196 }
197
198 /* Current time property is created as a callback property so that
199 * each attempt to read the property will get the current time.
200 */
201 292 result = globus_resource_create_property_callback(
202 resource,
203 &wsrl_CurrentTime_qname,
204 &xsd_dateTime_info,
205 wsrl_CurrentTime_callback,
206 wsrl_deny_callback,
207 NULL);
208
209 292 finish_out:
210 292 globus_resource_finish(resource);
211 292 out:
212 292 return result;
213 }
214 /* wsrl_ScheduledResourceTermination_init_resource() */
215
216
217 static
218 globus_result_t
219 wsrl_SetTerminationTime_provider(
220 globus_service_engine_t engine,
221 globus_soap_message_handle_t handle,
222 globus_service_descriptor_t * service,
223 wsrl_SetTerminationTimeType * SetTerminationTime,
224 wsrl_SetTerminationTimeResponseType *
225 SetTerminationTimeResponse,
226 xsd_any * fault)
227 76 {
228 76 globus_result_t result = GLOBUS_SUCCESS;
229 globus_resource_t resource;
230 xsd_dateTime computed_termination_time;
231 globus_abstime_t termination_time;
232 time_t now;
233 76 xsd_dateTime * termination_time_rp = NULL;
234
235 76 result = globus_wsrf_core_get_resource(handle, service, &resource);
236
237 76 if (result != GLOBUS_SUCCESS || resource == NULL)
238 {
239 0 result = globus_wsrf_core_create_fault(
240 fault,
241 &wsr_ResourceUnknownFault_qname);
242 0 goto out;
243 }
244
245 76 switch (SetTerminationTime->choice_value.type)
246 {
247 case wsrl_SetTerminationTimeType_RequestedTerminationTime:
248 76 if(!SetTerminationTime->choice_value.value.RequestedTerminationTime)
249 {
250 0 goto out;
251 }
252 76 termination_time.tv_sec = wsrl_l_timegm(
253 SetTerminationTime->
254 choice_value.value.RequestedTerminationTime);
255 76 termination_time.tv_nsec = 0;
256 76 break;
257 case wsrl_SetTerminationTimeType_RequestedLifetimeDuration:
258 0 now = time(NULL);
259
260 0 globus_libc_gmtime_r(&now, &computed_termination_time);
261 0 result = globus_wsrf_core_add_duration(
262 &computed_termination_time,
263 &SetTerminationTime->
264 choice_value.value.RequestedLifetimeDuration);
265 0 if (result != GLOBUS_SUCCESS)
266 {
267 0 goto out;
268 }
269 0 termination_time.tv_sec = wsrl_l_timegm(&computed_termination_time);
270 0 termination_time.tv_nsec = 0;
271 0 break;
272 default:
273 0 result = globus_wsrf_core_create_fault(
274 fault,
275 &wsrl_UnableToSetTerminationTimeFault_qname);
276 break;
277 }
278
279
280 76 result = globus_resource_set_destroy_time(resource, &termination_time);
281 76 if (result != GLOBUS_SUCCESS)
282 {
283 0 result = globus_wsrf_core_create_fault(
284 fault,
285 &wsrl_UnableToSetTerminationTimeFault_qname);
286
287 0 goto finish_out;
288 }
289
290 76 globus_libc_gmtime_r(
291 &termination_time.tv_sec,
292 &computed_termination_time);
293
294 76 now = time(NULL);
295 76 result = xsd_dateTime_copy(
296 &SetTerminationTimeResponse->NewTerminationTime,
297 &computed_termination_time);
298 76 if (result != GLOBUS_SUCCESS)
299 {
300 0 result = globus_wsrf_core_create_fault(
301 fault,
302 &wsrl_UnableToSetTerminationTimeFault_qname);
303
304 0 goto finish_out;
305 }
306
307 76 globus_libc_gmtime_r(&now, &SetTerminationTimeResponse->CurrentTime);
308
309 76 result = xsd_dateTime_copy(&termination_time_rp,
310 &computed_termination_time);
311 76 if (result != GLOBUS_SUCCESS)
312 {
313 0 result = globus_wsrf_core_create_fault(
314 fault,
315 &wsrl_UnableToSetTerminationTimeFault_qname);
316
317 0 goto finish_out;
318 }
319
320 76 result = globus_resource_set_property(
321 resource,
322 &wsrl_TerminationTime_qname,
323 termination_time_rp);
324
325 76 if (result != GLOBUS_SUCCESS)
326 {
327 0 result = globus_wsrf_core_create_fault(
328 fault,
329 &wsrl_UnableToSetTerminationTimeFault_qname);
330
331 0 goto finish_out;
332 }
333
334 76 result = globus_resource_finish(resource);
335
336 76 if (result != GLOBUS_SUCCESS)
337 {
338 0 goto out;
339 }
340 76 return GLOBUS_SUCCESS;
341
342 0 finish_out:
343 0 globus_resource_finish(resource);
344 0 out:
345 0 return result;
346 }
347 /* wsrl_SetTerminationTime_provider() */
348
349
350 static
351 globus_bool_t
352 wsrl_deny_callback(
353 void * arg,
354 const xsd_QName * qname,
355 void * property)
356 0 {
357 0 return GLOBUS_FALSE;
358 }
359 /* wsrl_deny_callback() */
360
361 static
362 void
363 wsrl_CurrentTime_callback(
364 void * arg,
365 const xsd_QName * qname,
366 void ** property)
367 15 {
368 time_t now_time;
369 xsd_dateTime * now;
370
371 15 globus_assert(
372 strcmp(qname->Namespace,
373 wsrl_CurrentTime_qname.Namespace) == 0);
374 15 globus_assert(
375 strcmp(qname->local,
376 wsrl_CurrentTime_qname.local) == 0);
377
378 15 now_time = time(NULL);
379
380 15 xsd_dateTime_init((xsd_dateTime **) property);
381 15 now = *property;
382
383 15 globus_libc_gmtime_r(&now_time, now);
384
385 return;
386 }
387 /* wsrl_CurrentTime_callback() */
388
389 /**
390 * Convert a struct tm to a time_t without accounting for the local timezone
391 * or modifying the struct tm contents.
392 *
393 * This may get a little kooky when the TZ shift occurs near the DST change.
394 */
395 static
396 time_t
397 wsrl_l_timegm(
398 const struct tm * tm)
399 76 {
400 struct tm tmp;
401 struct tm local_tm;
402 time_t local_time;
403 time_t shifted_time;
404
405 76 memcpy(&tmp, tm, sizeof(struct tm));
406
407 /* convert the tm to time_t in the local timezone */
408 76 local_time = mktime(&tmp);
409
410 /* create a new tm with this time (but without the TZ-related parts of the
411 * tm set) */
412 76 globus_libc_gmtime_r(&local_time, &local_tm);
413
414 /* convert the time to local time again, causing it to be shifted by
415 * time zone twice
416 */
417 76 shifted_time = mktime(&local_tm);
418
419 /*
420 * The difference between shifted_time and local_time is the TZ correction.
421 */
422 76 return local_time + (local_time - shifted_time);
423 }
424 /* wsrl_l_timegm() */
425
426 static
427 int
428 wsrl_ScheduledResourceTermination_activate(void)
429 334 {
430 334 int res = 0;
431 GlobusFuncName(wsrl_ScheduledResourceTermination_activate);
432
433 334 res = globus_extension_registry_add(
434 GLOBUS_OPERATION_PROVIDER_REGISTRY,
435 &wsrl_SetTerminationTime_qname,
436 GlobusExtensionMyModule(globus_wsrl_ScheduledResourceTermination_provider),
437 &wsrl_SetTerminationTime_descriptor);
438
439 334 return res;
440 }
441 /* wsrl_ScheduledResourceTermination_activate() */
442
443 static
444 int
445 wsrl_ScheduledResourceTermination_deactivate(void)
446 63 {
447 GlobusFuncName(wsrl_ScheduledResourceTermination_deactivate);
448
449 63 globus_extension_registry_remove(
450 GLOBUS_OPERATION_PROVIDER_REGISTRY,
451 &wsrl_SetTerminationTime_qname);
452
453 63 return 0;
454 }