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 "wsnt_RenewType.h"
27 #include "wsnt_RenewResponseType.h"
28
29 #include "wsnt_UnsubscribeType.h"
30 #include "wsnt_UnsubscribeResponseType.h"
31
32
33 #include "wsr_ResourceUnknownFault.h"
34 #include "wsnt_UnacceptableTerminationTimeFault.h"
35 #include "wsnt_UnableToDestroySubscriptionFault.h"
36
37 #include "version.h"
38
39
40 /**
41 * @page wsnt_SubscriptionManager_provider SubscriptionManager Provider
42 *
43 * <h2>Provider Usage Overview</h2>
44 * This operation provider implements the SubscriptionManager portType
45 * defined in http://docs.oasis-open.org/wsn/bw-2
46 .
47 * This portType consists of the @a Renew and @a Unsubscribe operations.
48 * and related faults.
49 *
50 * <h2>Limitations</h2>
51 * - This provider does not implement any policies regarding what is an
52 * acceptable change of the Subscription lifetime.
53 */
54
55 static
56 globus_result_t
57 wsnt_Renew_provider(
58 globus_service_engine_t engine,
59 globus_soap_message_handle_t handle,
60 globus_service_descriptor_t * service,
61 wsnt_RenewType * Renew,
62 wsnt_RenewResponseType * RenewResponse,
63 xsd_any * fault);
64
65 static
66 globus_result_t
67 wsnt_Unsubscribe_provider(
68 globus_service_engine_t engine,
69 globus_soap_message_handle_t handle,
70 globus_service_descriptor_t * service,
71 wsnt_UnsubscribeType * Unsubscribe,
72 wsnt_UnsubscribeResponseType * UnsubscribeResponse,
73 xsd_any * fault);
74
75 static
76 int
77 wsnt_SubscriptionManager_activate(void);
78
79 static
80 int
81 wsnt_SubscriptionManager_deactivate(void);
82
83 static
84 time_t
85 wsnt_l_timegm(
86 const struct tm * tm);
87
88 /* Local Variables */
89 static xsd_QName wsnt_Renew_provider_qname =
90 {
91 "http://docs.oasis-open.org/wsn/bw-2/providers",
92 "Renew"
93 };
94
95 static xsd_QName wsnt_Unsubscribe_provider_qname =
96 {
97 "http://docs.oasis-open.org/wsn/bw-2/providers",
98 "Unsubscribe"
99 };
100
101 static
102 globus_operation_provider_descriptor_t
103 wsnt_Renew_descriptor =
104 {
105 &wsnt_Renew_provider_qname,
106 "Renew",
107 (void *)wsnt_Renew_provider,
108 NULL
109 };
110
111 static
112 globus_operation_provider_descriptor_t
113 wsnt_Unsubscribe_descriptor =
114 {
115 &wsnt_Unsubscribe_provider_qname,
116 "Unsubscribe",
117 (void *)wsnt_Unsubscribe_provider,
118 NULL
119 };
120
121 GlobusExtensionDefineModule(globus_wsnt_SubscriptionManager_provider) =
122 {
123 "globus_wsnt_SubscriptionManager_provider",
124 wsnt_SubscriptionManager_activate,
125 wsnt_SubscriptionManager_deactivate,
126 NULL,
127 NULL,
128 &local_version
129 };
130
131 /* Implementation */
132
133 static
134 globus_result_t
135 wsnt_Renew_provider(
136 globus_service_engine_t engine,
137 globus_soap_message_handle_t handle,
138 globus_service_descriptor_t * service,
139 wsnt_RenewType * Renew,
140 wsnt_RenewResponseType * RenewResponse,
141 xsd_any * fault)
142 0 {
143 0 globus_result_t result = GLOBUS_SUCCESS;
144 globus_resource_t resource;
145 xsd_dateTime computed_termination_time;
146 globus_abstime_t termination_time;
147 time_t now;
148
149 0 result = globus_wsrf_core_get_resource(handle, service, &resource);
150
151 0 if (result != GLOBUS_SUCCESS || resource == NULL)
152 {
153 0 result = globus_wsrf_core_create_fault(
154 fault,
155 &wsr_ResourceUnknownFault_qname);
156 0 goto out;
157 }
158
159 0 if (Renew->TerminationTime == NULL)
160 {
161 0 goto finish_out;
162 }
163
164 0 switch (Renew->TerminationTime->type)
165 {
166 case wsnt_AbsoluteOrRelativeTimeType_dateTime:
167 0 termination_time.tv_sec = wsnt_l_timegm(
168 &Renew->TerminationTime->value.dateTime);
169 0 termination_time.tv_nsec = 0;
170 0 break;
171 case wsnt_AbsoluteOrRelativeTimeType_duration:
172 0 now = time(NULL);
173
174 0 globus_libc_gmtime_r(&now, &computed_termination_time);
175 0 result = globus_wsrf_core_add_duration(
176 &computed_termination_time,
177 &Renew->TerminationTime->value.duration);
178 0 if (result != GLOBUS_SUCCESS)
179 {
180 0 goto out;
181 }
182 0 termination_time.tv_sec = wsnt_l_timegm(&computed_termination_time);
183 0 termination_time.tv_nsec = 0;
184 0 break;
185 default:
186 0 result = globus_wsrf_core_create_fault(
187 fault,
188 &wsnt_UnacceptableTerminationTimeFault_qname);
189 break;
190 }
191
192 0 result = globus_resource_set_destroy_time(resource, &termination_time);
193 0 if (result != GLOBUS_SUCCESS)
194 {
195 0 result = globus_wsrf_core_create_fault(
196 fault,
197 &wsnt_UnacceptableTerminationTimeFault_qname);
198
199 0 goto finish_out;
200 }
201
202 0 globus_libc_gmtime_r(
203 &termination_time.tv_sec,
204 &computed_termination_time);
205
206 0 result = xsd_dateTime_copy_contents(
207 &RenewResponse->TerminationTime,
208 &computed_termination_time);
209 0 if (result != GLOBUS_SUCCESS)
210 {
211 0 result = globus_wsrf_core_create_fault(
212 fault,
213 &wsnt_UnacceptableTerminationTimeFault_qname);
214
215 0 goto finish_out;
216 }
217
218 0 now = time(NULL);
219 0 globus_libc_gmtime_r(&now, &computed_termination_time);
220
221 0 result = xsd_dateTime_copy(&RenewResponse->CurrentTime,
222 &computed_termination_time);
223 0 if (result != GLOBUS_SUCCESS)
224 {
225 0 result = globus_wsrf_core_create_fault(
226 fault,
227 &wsnt_UnacceptableTerminationTimeFault_qname);
228
229 0 goto finish_out;
230 }
231
232 0 result = globus_resource_finish(resource);
233
234 0 if (result != GLOBUS_SUCCESS)
235 {
236 0 goto out;
237 }
238 0 return GLOBUS_SUCCESS;
239
240 0 finish_out:
241 0 globus_resource_finish(resource);
242 0 out:
243 0 return result;
244 }
245 /* wsnt_Renew_provider() */
246
247 static
248 globus_result_t
249 wsnt_Unsubscribe_provider(
250 globus_service_engine_t engine,
251 globus_soap_message_handle_t handle,
252 globus_service_descriptor_t * service,
253 wsnt_UnsubscribeType * Unsubscribe,
254 wsnt_UnsubscribeResponseType * UnsubscribeResponse,
255 xsd_any * fault)
256 3 {
257 globus_result_t result;
258 globus_resource_t resource;
259 globus_object_t * error;
260
261 3 result = globus_wsrf_core_get_resource(handle, service, &resource);
262
263 3 if (result != GLOBUS_SUCCESS || resource == NULL)
264 {
265 0 result = globus_wsrf_core_create_fault(
266 fault,
267 &wsr_ResourceUnknownFault_qname);
268 0 if (result != GLOBUS_SUCCESS)
269 {
270 0 goto out;
271 }
272 }
273
274 3 result = globus_resource_destroy(resource);
275
276 3 if (result != GLOBUS_SUCCESS)
277 {
278 0 error = globus_error_get(result);
279
280 0 if (globus_error_match(error,
281 GLOBUS_WSRF_RESOURCE_MODULE,
282 GLOBUS_WSRF_RESOURCE_ERROR_TYPE_ALREADY_DESTROYED))
283 {
284 0 result = globus_wsrf_core_create_fault(
285 fault,
286 &wsnt_UnableToDestroySubscriptionFault_qname);
287 }
288 else
289 {
290 0 result = globus_wsrf_core_create_fault(
291 fault,
292 &wsr_ResourceUnknownFault_qname);
293 }
294 0 globus_object_free(error);
295
296 0 goto out;
297 }
298
299 3 return GLOBUS_SUCCESS;
300
301 0 out:
302 0 return result;
303 }
304 /* wsnt_Unsubscribe_provider() */
305
306 static
307 int
308 wsnt_SubscriptionManager_activate(void)
309 21 {
310 21 int res = 0;
311 GlobusFuncName(wsnt_SubscriptionManager_activate);
312
313 21 res = globus_extension_registry_add(
314 GLOBUS_OPERATION_PROVIDER_REGISTRY,
315 &wsnt_Renew_provider_qname,
316 GlobusExtensionMyModule(globus_wsnt_SubscriptionManager_provider),
317 &wsnt_Renew_descriptor);
318
319 21 if (res != GLOBUS_SUCCESS)
320 {
321 0 goto out;
322 }
323
324 21 res = globus_extension_registry_add(
325 GLOBUS_OPERATION_PROVIDER_REGISTRY,
326 &wsnt_Unsubscribe_provider_qname,
327 GlobusExtensionMyModule(globus_wsnt_SubscriptionManager_provider),
328 &wsnt_Unsubscribe_descriptor);
329
330 21 if (res != GLOBUS_SUCCESS)
331 {
332 0 res = globus_extension_registry_remove(
333 GLOBUS_OPERATION_PROVIDER_REGISTRY,
334 &wsnt_Renew_provider_qname);
335 }
336
337 21 out:
338 21 return res;
339 }
340 /* wsnt_SubscriptionManager_activate() */
341
342 static
343 int
344 wsnt_SubscriptionManager_deactivate(void)
345 0 {
346 GlobusFuncName(wsnt_SubscriptionManager_deactivate);
347
348 0 globus_extension_registry_remove(
349 GLOBUS_OPERATION_PROVIDER_REGISTRY,
350 &wsnt_Unsubscribe_provider_qname);
351
352 0 globus_extension_registry_remove(
353 GLOBUS_OPERATION_PROVIDER_REGISTRY,
354 &wsnt_Renew_provider_qname);
355
356 0 return 0;
357 }
358 /* wsnt_SubscriptionManager_deactivate() */
359
360 /**
361 * Convert a struct tm to a time_t without accounting for the local timezone
362 * or modifying the struct tm contents.
363 *
364 * This may get a little kooky when the TZ shift occurs near the DST change.
365 */
366 static
367 time_t
368 wsnt_l_timegm(
369 const struct tm * tm)
370 0 {
371 struct tm tmp;
372 struct tm local_tm;
373 time_t local_time;
374 time_t shifted_time;
375
376 0 memcpy(&tmp, tm, sizeof(struct tm));
377
378 /* convert the tm to time_t in the local timezone */
379 0 local_time = mktime(&tmp);
380
381 /* create a new tm with this time (but without the TZ-related parts of the
382 * tm set) */
383 0 globus_libc_gmtime_r(&local_time, &local_tm);
384
385 /* convert the time to local time again, causing it to be shifted by
386 * time zone twice
387 */
388 0 shifted_time = mktime(&local_tm);
389
390 /*
391 * The difference between shifted_time and local_time is the TZ correction.
392 */
393 0 return local_time + (local_time - shifted_time);
394 }