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 #include "globus_soap_message.h"
13 #include "globus_wsrf_resource.h"
14 #include "globus_service_engine.h"
15 #include "globus_operation_provider.h"
16 #include "globus_service_registry.h"
17 #include "globus_wsrf_core_tools.h"
18
19 #include "xsd_dateTime.h"
20
21 #include "wsrl_SetTerminationTimeType.h"
22 #include "wsrl_SetTerminationTimeResponseType.h"
23
24 #include "version.h"
25
26 /*
27  * This define causes the wsrl_i_faults.h to define faults relevant to this
28  * port type.
29  */
30 #define WSRL_SCHEDULED_RESOURCE_TERMINATION 1
31 /* We don't implement any sort of change policy, so we don't use this fault
32  * type.
33  */
34 #define NEED_TERMINATION_TIME_CHANGE_REJECTED_FAULT 0
35
36 #include "wsrl_i_faults.h"
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
44  * http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.wsdl .
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 GlobusExtensionDeclareModule(wsrl_ScheduledResourceTermination);
61
62 /* Prototypes */
63 static
64 globus_result_t
65 wsrl_ScheduledResourceTermination_init_resource(
66     const char *                        resource_id);
67
68 static
69 globus_result_t
70 wsrl_SetTerminationTime_init_provider(
71     globus_service_engine_t             engine,
72     globus_soap_message_handle_t        handle,
73     wsrl_SetTerminationTimeType *       SetTerminationTime);
74
75 static
76 globus_result_t
77 wsrl_SetTerminationTime_provider(
78     globus_service_engine_t             engine,
79     globus_soap_message_handle_t        handle,
80     globus_service_descriptor_t *       service,
81     wsrl_SetTerminationTimeType *       SetTerminationTime,
82     wsrl_SetTerminationTimeResponseType *
83                                         SetTerminationTimeResponse,
84     char **                             fault_name,
85     void **                             fault);
86
87 static
88 void
89 wsrl_CurrentTime_callback(
90     void *                              arg,
91     const xsd_QName *                   qname,
92     void **                             property);
93
94 static
95 time_t
96 wsrl_l_timegm(
97     const struct tm *                   tm);
98
99 static
100 int
101 wsrl_ScheduledResourceTermination_activate(void);
102
103 static
104 int
105 wsrl_ScheduledResourceTermination_deactivate(void);
106
107 /* Local Variables */
108 static xsd_QName wsrl_SetTerminationTime_qname =
109 {
110     "http://www.globus.org/docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.wsdl",
111     "SetTerminationTime"
112 };
113
114 static xsd_QName wsrl_CurrentTime_qname =
115 {
116     "http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd",
117     "CurrentTime"
118 };
119
120 static xsd_QName wsrl_TerminationTime_qname =
121 {
122     "http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd",
123     "TerminationTime"
124 };
125
126 static
127 globus_operation_provider_descriptor_t
128 wsrl_SetTerminationTime_descriptor =
129 {
130     &wsrl_SetTerminationTime_qname,
131     "SetTerminationTime",
132     (void *)wsrl_SetTerminationTime_init_provider,
133     (void *)wsrl_SetTerminationTime_provider,
134     wsrl_ScheduledResourceTermination_init_resource
135 };
136
137 GlobusExtensionDefineModule(wsrl_ScheduledResourceTermination) =
138 {
139     "wsrl_ScheduledResourceTermination",
140     wsrl_ScheduledResourceTermination_activate,
141     wsrl_ScheduledResourceTermination_deactivate,
142     NULL,
143     NULL,
144     &local_version
145 };
146
147 /* Implementation */
148 static
149 globus_result_t
150 wsrl_ScheduledResourceTermination_init_resource(
151     const char *                        resource_id)
152 25 {
153 25     globus_resource_t                   resource;
154 25     globus_result_t                     result;
155
156 25     result = globus_resource_find(resource_id, &resource);
157
158 25     if (result != GLOBUS_SUCCESS)
159     {
160 0         goto out;
161     }
162
163 25     result = globus_resource_create_property(
164         resource,
165         &wsrl_TerminationTime_qname,
166         &xsd_dateTime_info,
167         NULL);
168
169 25     if (result != GLOBUS_SUCCESS)
170     {
171 0         goto finish_out;
172     }
173
174 25     result = globus_resource_create_property_callback(
175         resource,
176         &wsrl_CurrentTime_qname,
177         &xsd_dateTime_info,
178         wsrl_CurrentTime_callback,
179         NULL);
180
181 finish_out:
182 25     globus_resource_finish(resource);
183 out:
184 25     return result;
185 }
186 /* wsrl_ScheduledResourceTermination_init_resource() */
187
188
189 static
190 globus_result_t
191 wsrl_SetTerminationTime_init_provider(
192     globus_service_engine_t             engine,
193     globus_soap_message_handle_t        handle,
194     wsrl_SetTerminationTimeType *       SetTerminationTime)
195 15 {
196     /* NOOP */
197 15     return GLOBUS_SUCCESS;
198 }
199
200 static
201 globus_result_t
202 wsrl_SetTerminationTime_provider(
203     globus_service_engine_t             engine,
204     globus_soap_message_handle_t        handle,
205     globus_service_descriptor_t *       service,
206     wsrl_SetTerminationTimeType *       SetTerminationTime,
207     wsrl_SetTerminationTimeResponseType *
208                                         SetTerminationTimeResponse,
209     char **                             fault_name,
210     void **                             fault)
211 15 {
212 15     globus_result_t                     result;
213 15     globus_resource_t                   resource;
214 15     globus_abstime_t                    termination_time;
215 15     time_t                              now;
216 15     xsd_dateTime *                      termination_time_rp;
217
218 15     result = globus_wsrf_core_get_resource(handle, service, &resource);
219
220 15     if (result != GLOBUS_SUCCESS || resource == NULL)
221     {
222 0         result = wsrl_l_ResourceUnknownFaultType_create(
223                 fault_name,
224                 (wsrl_ResourceUnknownFaultType **) fault);
225
226 0         goto out;
227     }
228
229 15     termination_time.tv_sec = wsrl_l_timegm(
230             &SetTerminationTime->RequestedTerminationTime);
231
232 15     termination_time.tv_nsec = 0;
233
234 15     result = globus_resource_set_destroy_time(resource, &termination_time);
235
236 15     if (result != GLOBUS_SUCCESS)
237     {
238 0         result = wsrl_l_UnableToSetTerminationTimeFaultType_create(
239                 fault_name,
240                 (wsrl_UnableToSetTerminationTimeFaultType **) fault);
241
242
243 0         goto finish_out;
244     }
245
246 15     now = time(NULL);
247
248 15     memcpy(&SetTerminationTimeResponse->NewTerminationTime,
249            &SetTerminationTime->RequestedTerminationTime,
250            sizeof(xsd_dateTime));
251
252 15     globus_libc_gmtime_r(&now, &SetTerminationTimeResponse->CurrentTime);
253
254 15     xsd_dateTime_init(&termination_time_rp);
255
256 15     memcpy(termination_time_rp,
257            &SetTerminationTime->RequestedTerminationTime,
258            sizeof(xsd_dateTime));
259
260 15     result = globus_resource_set_property(
261             resource,
262             &wsrl_TerminationTime_qname,
263             termination_time_rp);
264
265 15     if (result != GLOBUS_SUCCESS)
266     {
267 0         goto finish_out;
268     }
269
270 15     result = globus_resource_finish(resource);
271
272 15     if (result != GLOBUS_SUCCESS)
273     {
274 0         goto out;
275     }
276 15     return GLOBUS_SUCCESS;
277
278 finish_out:
279 0     globus_resource_finish(resource);
280 out:
281 0     return result;
282 }
283 /* wsrl_SetTerminationTime_provider() */
284
285
286 static
287 void
288 wsrl_CurrentTime_callback(
289     void *                              arg,
290     const xsd_QName *                   qname,
291     void **                             property)
292 1 {
293 1     time_t                              now_time;
294 1     xsd_dateTime *                      now;
295
296 1     globus_assert(
297             strcmp(qname->Namespace,
298                     wsrl_CurrentTime_qname.Namespace) == 0);
299 1     globus_assert(
300             strcmp(qname->local,
301                     wsrl_CurrentTime_qname.local) == 0);
302
303 1     now_time = time(NULL);
304
305 1     xsd_dateTime_init((xsd_dateTime **) property);
306 1     now = *property;
307
308 1     globus_libc_gmtime_r(&now_time, now);
309
310     return;
311 }
312 /* wsrl_CurrentTime_callback() */
313
314 /**
315  * Convert a struct tm to a time_t without accounting for the local timezone
316  * or modifying the struct tm contents.
317  *
318  * This may get a little kooky when the TZ shift occurs near the DST change.
319  */
320 static
321 time_t
322 wsrl_l_timegm(
323     const struct tm *                   tm)
324 15 {
325 15     struct tm                           tmp;
326 15     struct tm                           local_tm;
327 15     time_t                              local_time;
328 15     time_t                              shifted_time;
329
330 15     memcpy(&tmp, tm, sizeof(struct tm));
331
332     /* convert the tm to time_t in the local timezone */
333 15     local_time = mktime(&tmp);
334
335     /* create a new tm with this time (but without the TZ-related parts of the
336      * tm set) */
337 15     globus_libc_gmtime_r(&local_time, &local_tm);
338
339     /* convert the time to local time again, causing it to be shifted by
340      * time zone twice
341      */
342 15     shifted_time = mktime(&local_tm);
343
344     /*
345      * The difference between shifted_time and local_time is the TZ correction.
346      */
347 15     return local_time + (local_time - shifted_time);
348
349     /*
350      * This snippet is based on the timegm manpage, but is not thread safe
351      * 
352      * tz = globus_libc_getenv("TZ");
353      * setenv("TZ", "", 1);
354      * tzset();
355      * termination_time.tv_sec = mktime(
356      *         &SetTerminationTime->RequestedTerminationTime);
357      * if (tz != NULL)
358      * {
359      *     globus_libc_setenv("TZ", tz, 1);
360      * }
361      * else
362      * {
363      *     globus_libc_unsetenv("TZ");
364      * }
365      * tzset();
366      */
367 }
368 /* wsrl_l_timegm() */
369
370 static
371 int
372 wsrl_ScheduledResourceTermination_activate(void)
373 28 {
374 28     int                                 res = 0;
375 28     GlobusFuncName(wsrl_ScheduledResourceTermination_activate);
376     
377 28     res = globus_extension_registry_add(
378         GLOBUS_OPERATION_PROVIDER_REGISTRY,
379         &wsrl_SetTerminationTime_qname,
380         GlobusExtensionMyModule(wsrl_ScheduledResourceTermination),
381         &wsrl_SetTerminationTime_descriptor);
382
383 28     return res;
384 }
385 /* wsrl_ScheduledResourceTermination_activate() */
386
387 static
388 int
389 wsrl_ScheduledResourceTermination_deactivate(void)
390 0 {
391 0     GlobusFuncName(wsrl_ScheduledResourceTermination_deactivate);
392
393 0     globus_extension_registry_remove(
394         GLOBUS_OPERATION_PROVIDER_REGISTRY,
395         &wsrl_SetTerminationTime_qname);
396
397 0     return 0;
398 }