| /******************************************************************************* |
| * Copyright (C) 2004-2006 Intel Corp. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * - Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * - Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * - Neither the name of Intel Corp. nor the names of its |
| * contributors may be used to endorse or promote products derived from this |
| * software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| *******************************************************************************/ |
| |
| /** |
| * @author Anas Nashif |
| * @author Eugene Yarmosh |
| * @author Liang Hou |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include <wsman_config.h> |
| #endif |
| |
| #define _GNU_SOURCE |
| |
| #include "u/libu.h" |
| #include "wsman-xml-api.h" |
| #include "wsman-soap.h" |
| #include "wsman-xml.h" |
| #include "wsman-dispatcher.h" |
| #include "wsman-xml-serializer.h" |
| #include "wsman-xml-serialize.h" |
| #include "wsman-soap-envelope.h" |
| #include "wsman-faults.h" |
| #include "wsman-soap-message.h" |
| |
| #include "wsman-client-api.h" |
| #include "wsman-client-transport.h" |
| |
| /* ENUMERATION */ |
| #define ENUM_EXPIRED(enuminfo, mytime) \ |
| ((enumInfo->expires > 0) && \ |
| (enumInfo->expires > mytime)) |
| |
| |
| |
| /** |
| * Calculate needed space for interface array with Endpoints |
| * @param interfaces List of interfaces |
| * @return Needed size of WsManDispatcherInfo |
| */ |
| static int |
| calculate_map_count(list_t * interfaces) |
| { |
| int count = 0; |
| int j; |
| |
| lnode_t *node = list_first(interfaces); |
| while (node) { |
| WsDispatchInterfaceInfo *ifc = |
| (WsDispatchInterfaceInfo *) node->list_data; |
| for (j = 0; ifc->endPoints[j].serviceEndPoint != NULL; j++) |
| count++; |
| node = list_next(interfaces, node); |
| } |
| |
| return (list_count(interfaces) * sizeof(WsManDispatcherInfo)) |
| + (count * sizeof(DispatchToEpMap)); |
| } |
| |
| /** |
| * Register Dispatcher |
| * @param cntx Context |
| * @param proc Dispatcher Callback |
| * @param data Callback data |
| */ |
| static void |
| ws_register_dispatcher(WsContextH cntx, DispatcherCallback proc, void *data) |
| { |
| SoapH soap = ws_context_get_runtime(cntx); |
| if (soap) { |
| soap->dispatcherProc = proc; |
| soap->dispatcherData = data; |
| } |
| return; |
| } |
| |
| static int |
| set_context_val(WsContextH cntx, |
| char *name, |
| void *val, |
| int size, |
| int no_dup, |
| unsigned long type) |
| { |
| int retVal = 1; |
| debug("Setting context value: %s", name); |
| if (cntx && name) { |
| void *ptr = val; |
| |
| if (!no_dup) { |
| if (val && (ptr = u_malloc(size))) { |
| memcpy(ptr, val, size); |
| } |
| } |
| if (ptr || val == NULL) { |
| u_lock(cntx->soap); |
| ws_remove_context_val(cntx, name); |
| if (create_context_entry(cntx->entries, name, ptr)) { |
| retVal = 0; |
| } |
| u_unlock(cntx->soap); |
| } |
| } else { |
| error("error setting context value."); |
| } |
| return retVal; |
| } |
| |
| |
| static void |
| free_hentry_func(hnode_t * n, void *arg) |
| { |
| u_free((void*)hnode_getkey(n)); |
| u_free(n); |
| } |
| |
| |
| static void |
| remove_locked_enuminfo(WsContextH cntx, |
| WsEnumerateInfo * enumInfo) |
| { |
| u_lock(cntx->soap); |
| if (!(enumInfo->flags & WSMAN_ENUMINFO_INWORK_FLAG)) { |
| error("locked enuminfo unlocked"); |
| u_unlock(cntx->soap); |
| return; |
| } |
| hash_delete_free(cntx->enuminfos, |
| hash_lookup(cntx->enuminfos, enumInfo->enumId)); |
| u_unlock(cntx->soap); |
| } |
| |
| #ifdef ENABLE_EVENTING_SUPPORT |
| static void wsman_expiretime2xmldatetime(unsigned long expire, char *str) |
| { |
| time_t t = expire; |
| struct tm tm; |
| localtime_r(&t, &tm); |
| snprintf(str, 30, "%u-%u%u-%u%uT%u%u:%u%u:%u%u+%u%u:%u%u", |
| tm.tm_year + 1900, (tm.tm_mon + 1)/10, (tm.tm_mon + 1)%10, |
| tm.tm_mday/10, tm.tm_mday%10, tm.tm_hour/10, tm.tm_hour%10, |
| tm.tm_min/10, tm.tm_min%10, tm.tm_sec/10, tm.tm_sec%10, |
| 0, 0, 0,0); |
| |
| } |
| |
| static void delete_notification_info(WsNotificationInfoH notificationInfo) { |
| if(notificationInfo) { |
| ws_xml_destroy_doc(notificationInfo->EventContent); |
| ws_xml_destroy_doc(notificationInfo->headerOpaqueData); |
| u_free(notificationInfo->EventAction); |
| u_free(notificationInfo); |
| } |
| } |
| #endif |
| |
| |
| static WsSubscribeInfo* |
| search_pull_subs_info(SoapH soap, WsXmlDocH indoc) |
| { |
| WsSubscribeInfo *subsInfo = NULL; |
| char *uuid = NULL; |
| lnode_t *lnode; |
| WsContextH soapCntx = ws_get_soap_context(soap); |
| WsXmlNodeH node = ws_xml_get_soap_body(indoc); |
| |
| node = ws_xml_get_child(node, 0, XML_NS_ENUMERATION, WSENUM_PULL); |
| if(node) { |
| node = ws_xml_get_child(node, 0, XML_NS_ENUMERATION, WSENUM_ENUMERATION_CONTEXT); |
| uuid = ws_xml_get_node_text(node); |
| } |
| if(uuid == NULL) return subsInfo; |
| pthread_mutex_lock(&soap->lockSubs); |
| lnode = list_first(soapCntx->subscriptionMemList); |
| while(lnode) { |
| subsInfo = (WsSubscribeInfo *)lnode->list_data; |
| if(!strcmp(subsInfo->subsId, uuid+5)) break; |
| lnode = list_next(soapCntx->subscriptionMemList, lnode); |
| } |
| pthread_mutex_unlock(&soap->lockSubs); |
| if(lnode == NULL) return NULL; |
| return subsInfo; |
| } |
| |
| |
| static WsXmlDocH |
| create_enum_info(SoapOpH op, |
| WsContextH epcntx, |
| WsXmlDocH indoc, |
| WsEnumerateInfo **eInfo) |
| { |
| WsXmlNodeH node = ws_xml_get_soap_body(indoc); |
| WsXmlNodeH header = ws_xml_get_soap_header(indoc); |
| WsXmlDocH outdoc = NULL; |
| WsXmlNodeH enumnode = NULL; |
| WsEnumerateInfo *enumInfo; |
| WsmanMessage *msg = wsman_get_msg_from_op(op); |
| WsmanFaultCodeType fault_code = WSMAN_RC_OK; |
| WsmanFaultDetailType fault_detail_code = WSMAN_DETAIL_OK; |
| char *uri, *to; |
| |
| enumInfo = (WsEnumerateInfo *)u_zalloc(sizeof (WsEnumerateInfo)); |
| if (enumInfo == NULL) { |
| error("No memory"); |
| fault_code = WSMAN_INTERNAL_ERROR; |
| goto DONE; |
| } |
| enumInfo->encoding = u_strdup(msg->charset); |
| enumInfo->maxsize = wsman_get_maxsize_from_op(op); |
| if(enumInfo->maxsize == 0) { |
| enumnode = ws_xml_get_child(node, 0, XML_NS_ENUMERATION, WSENUM_ENUMERATE); |
| enumInfo->maxsize = ws_deserialize_uint32(NULL, enumnode, |
| 0, XML_NS_ENUMERATION, |
| WSENUM_MAX_CHARACTERS); |
| } |
| enumInfo->releaseproc = wsman_get_release_endpoint(epcntx, indoc); |
| to = ws_xml_get_node_text( |
| ws_xml_get_child(header, 0, XML_NS_ADDRESSING, WSA_TO)); |
| uri = ws_xml_get_node_text( |
| ws_xml_get_child(header, 0, XML_NS_WS_MAN, WSM_RESOURCE_URI)); |
| |
| enumInfo->epr_to = u_strdup(to); |
| enumInfo->epr_uri = u_strdup(uri); |
| node = ws_xml_get_child(node, 0, XML_NS_ENUMERATION, WSENUM_ENUMERATE); |
| node = ws_xml_get_child(node, 0, XML_NS_ENUMERATION, WSENUM_EXPIRES); |
| if (node == NULL) { |
| debug("No wsen:Expires"); |
| enumInfo->expires = 0; |
| } else { |
| wsman_set_expiretime(node, &(enumInfo->expires), &fault_code); |
| if (fault_code != WSMAN_RC_OK) { |
| fault_detail_code = WSMAN_DETAIL_EXPIRATION_TIME; |
| goto DONE; |
| } |
| } |
| |
| if (msg->auth_data.username != NULL) { |
| enumInfo->auth_data.username = |
| u_strdup(msg->auth_data.username); |
| enumInfo->auth_data.password = |
| u_strdup(msg->auth_data.password); |
| } else { |
| enumInfo->auth_data.username = NULL; |
| enumInfo->auth_data.password = NULL; |
| } |
| generate_uuid(enumInfo->enumId, EUIDLEN, 1); |
| |
| DONE: |
| if (fault_code != WSMAN_RC_OK) { |
| outdoc = wsman_generate_fault(indoc, fault_code, fault_detail_code, NULL); |
| u_free(enumInfo); |
| } else { |
| *eInfo = enumInfo; |
| } |
| return outdoc; |
| } |
| |
| static void |
| destroy_enuminfo(WsEnumerateInfo * enumInfo) |
| { |
| debug("destroy enuminfo"); |
| u_free(enumInfo->auth_data.username); |
| u_free(enumInfo->auth_data.password); |
| u_free(enumInfo->epr_to); |
| u_free(enumInfo->epr_uri); |
| u_free(enumInfo->encoding); |
| if (enumInfo->filter) |
| filter_destroy(enumInfo->filter); |
| u_free(enumInfo); |
| } |
| |
| static int |
| wsman_verify_enum_info(SoapOpH op, |
| WsEnumerateInfo * enumInfo, |
| WsXmlDocH doc, |
| WsmanStatus * status) |
| { |
| |
| WsmanMessage *msg = wsman_get_msg_from_op(op); |
| WsXmlNodeH header = ws_xml_get_soap_header(doc); |
| |
| char *to = ws_xml_get_node_text(ws_xml_get_child(header, 0, |
| XML_NS_ADDRESSING, WSA_TO)); |
| char *uri= ws_xml_get_node_text(ws_xml_get_child(header, 0, |
| XML_NS_WS_MAN, WSM_RESOURCE_URI)); |
| |
| if (strcmp(enumInfo->epr_to, to) != 0 || |
| strcmp(enumInfo->epr_uri, uri) != 0 ) { |
| status->fault_code = WSA_MESSAGE_INFORMATION_HEADER_REQUIRED; |
| status->fault_detail_code = 0; |
| debug("verifying enumeration context: ACTUAL uri: %s, to: %s", uri, to); |
| debug("verifying enumeration context: SHOULD uri: %s, to: %s", |
| enumInfo->epr_uri, enumInfo->epr_to); |
| return 0; |
| } |
| |
| if (msg->auth_data.username && msg->auth_data.password) { |
| if (strcmp(msg->auth_data.username, |
| enumInfo->auth_data.username) != 0 && |
| strcmp(msg->auth_data.password, |
| enumInfo->auth_data.password) != 0) { |
| status->fault_code = WSMAN_ACCESS_DENIED; |
| status->fault_detail_code = 0; |
| return 0; |
| } |
| } |
| return 1; |
| } |
| |
| |
| |
| static int |
| insert_enum_info(WsContextH cntx, |
| WsEnumerateInfo *enumInfo) |
| { |
| struct timeval tv; |
| int retVal = 1; |
| |
| u_lock(cntx->soap); |
| gettimeofday(&tv, NULL); |
| enumInfo->timeStamp = tv.tv_sec; |
| if (create_context_entry(cntx->enuminfos, enumInfo->enumId, enumInfo)) { |
| retVal = 0; |
| } |
| u_unlock(cntx->soap); |
| return retVal; |
| } |
| |
| |
| |
| static WsEnumerateInfo * |
| get_locked_enuminfo(WsContextH cntx, |
| WsXmlDocH doc, |
| SoapOpH op, |
| char *action, |
| WsmanStatus *status) |
| { |
| hnode_t *hn; |
| WsEnumerateInfo *eInfo = NULL; |
| char *enumId = NULL; |
| WsXmlNodeH node = ws_xml_get_soap_body(doc); |
| |
| if (node && (node = ws_xml_get_child(node, |
| 0, XML_NS_ENUMERATION, action))) { |
| node = ws_xml_get_child(node, 0, |
| XML_NS_ENUMERATION, WSENUM_ENUMERATION_CONTEXT); |
| if (node) { |
| enumId = ws_xml_get_node_text(node); |
| } |
| } |
| debug("enum context: %s", enumId); |
| |
| if (enumId == NULL) { |
| status->fault_code = WSEN_INVALID_ENUMERATION_CONTEXT; |
| return NULL; |
| } |
| u_lock(cntx->soap); |
| hn = hash_lookup(cntx->enuminfos, enumId); |
| if (hn) { |
| eInfo = (WsEnumerateInfo *)hnode_get(hn); |
| if (strcmp(eInfo->enumId, enumId)) { |
| error("enum context mismatch: %s == %s", |
| eInfo->enumId, enumId); |
| status->fault_code = WSMAN_INTERNAL_ERROR; |
| } else if (wsman_verify_enum_info(op, eInfo, doc,status)) { |
| if (eInfo->flags & WSMAN_ENUMINFO_INWORK_FLAG) { |
| status->fault_code = WSMAN_CONCURRENCY; |
| } else { |
| eInfo->flags |= WSMAN_ENUMINFO_INWORK_FLAG; |
| } |
| } |
| } else { |
| status->fault_code = WSEN_INVALID_ENUMERATION_CONTEXT; |
| } |
| |
| if (status->fault_code != WSMAN_RC_OK) { |
| eInfo = NULL; |
| } |
| u_unlock(cntx->soap); |
| return eInfo; |
| } |
| |
| static void |
| unlock_enuminfo(WsContextH cntx, WsEnumerateInfo *enumInfo) |
| { |
| struct timeval tv; |
| gettimeofday(&tv, NULL); |
| u_lock(cntx->soap); |
| if (!(enumInfo->flags & WSMAN_ENUMINFO_INWORK_FLAG)) { |
| error("locked enuminfo unlocked"); |
| u_unlock(cntx->soap); |
| return; |
| } |
| enumInfo->flags &= ~WSMAN_ENUMINFO_INWORK_FLAG; |
| enumInfo->timeStamp = tv.tv_sec; |
| u_unlock(cntx->soap); |
| } |
| |
| static void |
| ws_clear_context_entries(WsContextH hCntx) |
| { |
| hash_t *h; |
| if (!hCntx) { |
| return; |
| } |
| h = hCntx->entries; |
| hash_free(h); |
| } |
| |
| static void |
| ws_clear_context_enuminfos(WsContextH hCntx) |
| { |
| hash_t *h; |
| if (!hCntx) { |
| return; |
| } |
| h = hCntx->enuminfos; |
| hash_free(h); |
| } |
| |
| callback_t * |
| make_callback_entry(SoapServiceCallback proc, |
| void *data, |
| list_t * list_to_add) |
| { |
| callback_t *entry = (callback_t *) u_malloc(sizeof(callback_t)); |
| debug("make new callback entry"); |
| if (entry) { |
| lnode_init(&entry->node, data); |
| entry->proc = proc; |
| if (list_to_add == NULL) { |
| list_to_add = list_create(LISTCOUNT_T_MAX); |
| } |
| list_append(list_to_add, &entry->node); |
| } else { |
| return NULL; |
| } |
| return entry; |
| } |
| |
| |
| |
| void |
| ws_initialize_context(WsContextH cntx, SoapH soap) |
| { |
| cntx->entries = hash_create(HASHCOUNT_T_MAX, NULL, NULL); |
| hash_set_allocator(cntx->entries, NULL, free_hentry_func, NULL); |
| |
| cntx->enuminfos = hash_create(HASHCOUNT_T_MAX, NULL, NULL); |
| cntx->subscriptionMemList = list_create(LISTCOUNT_T_MAX); |
| hash_set_allocator(cntx->enuminfos, NULL, free_hentry_func, NULL); |
| cntx->owner = 1; |
| cntx->soap = soap; |
| cntx->serializercntx = ws_serializer_init(); |
| } |
| |
| WsContextH |
| ws_create_context(SoapH soap) |
| { |
| WsContextH cntx = (WsContextH) u_zalloc(sizeof (*cntx)); |
| if (cntx) { |
| ws_initialize_context(cntx, soap); |
| } |
| return cntx; |
| } |
| |
| SoapH |
| ws_soap_initialize() |
| { |
| SoapH soap = (SoapH) u_zalloc(sizeof(*soap)); |
| |
| if (soap == NULL) { |
| error("Could not alloc memory"); |
| return NULL; |
| } |
| soap->cntx = ws_create_context(soap); |
| |
| soap->inboundFilterList = NULL; |
| soap->outboundFilterList = NULL; |
| soap->dispatchList = NULL; |
| soap->processedMsgIdList = NULL; |
| |
| u_init_lock(soap); |
| u_init_lock(&soap->lockSubs); |
| ws_xml_parser_initialize(); |
| |
| soap_add_filter(soap, outbound_addressing_filter, NULL, 0); |
| soap_add_filter(soap, outbound_control_header_filter, NULL, 0); |
| return soap; |
| } |
| |
| void |
| ws_set_context_enumIdleTimeout(WsContextH cntx, |
| unsigned long timeout) |
| { |
| cntx->enumIdleTimeout = timeout; |
| } |
| |
| |
| |
| WsContextH |
| ws_create_runtime(list_t * interfaces) |
| { |
| SoapH soap = ws_soap_initialize(); |
| WsManDispatcherInfo *dispInfo; |
| int size; |
| lnode_t *node; |
| if (soap == NULL) { |
| error("Could not initialize soap"); |
| return NULL; |
| } |
| |
| if (interfaces == NULL) { |
| return soap->cntx; |
| } |
| |
| size = calculate_map_count(interfaces); |
| dispInfo = (WsManDispatcherInfo *) u_zalloc(size); |
| if (dispInfo == NULL) { |
| error("Could not allocate memory"); |
| u_free(soap); |
| return NULL; |
| } |
| debug("Registering %d plugins", (int) list_count(interfaces)); |
| dispInfo->interfaceCount = list_count(interfaces); |
| dispInfo->interfaces = interfaces; |
| node = list_first(interfaces); |
| while (node != NULL) { |
| WsDispatchInterfaceInfo *wdii = (WsDispatchInterfaceInfo *) node->list_data; |
| if (wsman_register_interface(soap->cntx, wdii, dispInfo) != 0) { |
| error("Interface registration failed for %s", wdii->displayName); |
| u_free(dispInfo); |
| soap_destroy(soap); |
| return NULL; |
| } |
| node = list_next(interfaces, node); |
| } |
| ws_register_dispatcher(soap->cntx, wsman_dispatcher, dispInfo); |
| return soap->cntx; |
| } |
| |
| |
| |
| |
| /** |
| * Register Dispatcher Interfaces |
| * @param cntx WS-Man Context |
| * @param wsInterface Interface |
| * @param dispinfo Dispatcher |
| */ |
| int |
| wsman_register_interface(WsContextH cntx, |
| WsDispatchInterfaceInfo * wsInterface, |
| WsManDispatcherInfo * dispInfo) |
| { |
| int i, retVal = 0; |
| WsDispatchEndPointInfo *ep = wsInterface->endPoints; |
| |
| for (i = 0; ep[i].serviceEndPoint != NULL; i++) { |
| if ((retVal = wsman_register_endpoint(cntx, wsInterface, |
| &ep[i], dispInfo)) != 0) { |
| break; |
| } |
| } |
| return retVal; |
| } |
| |
| |
| /* |
| * Register Endpoint |
| * @param cntx Context |
| * @param wsInterface Interface |
| * @param ep Endpoint |
| * @param dispInfo Dispatcher information |
| */ |
| int |
| wsman_register_endpoint(WsContextH cntx, |
| WsDispatchInterfaceInfo *wsInterface, |
| WsDispatchEndPointInfo *ep, |
| WsManDispatcherInfo *dispInfo) |
| { |
| SoapDispatchH disp = NULL; |
| unsigned long flags = SOAP_CUSTOM_DISPATCHER; |
| SoapServiceCallback callbackProc = NULL; |
| SoapH soap = ws_context_get_runtime(cntx); |
| char *action = NULL; |
| |
| debug("Registering Endpoint: %s", ep->inAction ? ep->inAction : "<null>"); |
| switch (ep->flags & WS_DISP_TYPE_MASK) { |
| case WS_DISP_TYPE_IDENTIFY: |
| debug("Registering endpoint for Identify"); |
| action = ep->inAction; |
| callbackProc = wsman_identify_stub; |
| break; |
| case WS_DISP_TYPE_ENUMERATE: |
| debug("Registering endpoint for Enumerate"); |
| action = ep->inAction; |
| callbackProc = wsenum_enumerate_stub; |
| break; |
| case WS_DISP_TYPE_RELEASE: |
| debug("Registering endpoint for Release"); |
| action = ep->inAction; |
| callbackProc = wsenum_release_stub; |
| break; |
| case WS_DISP_TYPE_DELETE: |
| debug("Registering endpoint for Delete"); |
| action = ep->inAction; |
| callbackProc = ws_transfer_delete_stub; |
| break; |
| case WS_DISP_TYPE_PULL: |
| debug("Registering endpoint for Pull"); |
| action = ep->inAction; |
| callbackProc = wsenum_pull_stub; |
| break; |
| case WS_DISP_TYPE_DIRECT_PULL: |
| debug("Registering endpoint for direct Pull"); |
| action = ep->inAction; |
| callbackProc = wsenum_pull_direct_stub; |
| break; |
| case WS_DISP_TYPE_GET: |
| debug("Registering endpoint for Get"); |
| action = ep->inAction; |
| callbackProc = ws_transfer_get_stub; |
| break; |
| case WS_DISP_TYPE_DIRECT_GET: |
| debug("Registering endpoint for direct Get"); |
| action = ep->inAction; |
| callbackProc = (SoapServiceCallback) ep->serviceEndPoint; |
| break; |
| case WS_DISP_TYPE_DIRECT_DELETE: |
| debug("Registering endpoint for Delete"); |
| action = ep->inAction; |
| callbackProc = (SoapServiceCallback) ep->serviceEndPoint; |
| break; |
| case WS_DISP_TYPE_DIRECT_PUT: |
| debug("Registering endpoint for direct Put"); |
| action = ep->inAction; |
| callbackProc = (SoapServiceCallback) ep->serviceEndPoint; |
| break; |
| case WS_DISP_TYPE_DIRECT_CREATE: |
| debug("Registering endpoint for direct Create"); |
| action = ep->inAction; |
| callbackProc = (SoapServiceCallback) ep->serviceEndPoint; |
| break; |
| case WS_DISP_TYPE_PUT: |
| debug("Registering endpoint for Put"); |
| action = ep->inAction; |
| callbackProc = ws_transfer_put_stub; |
| break; |
| #ifdef ENABLE_EVENTING_SUPPORT |
| case WS_DISP_TYPE_SUBSCRIBE: |
| debug("Registering endpoint for Subscribe"); |
| action = ep->inAction; |
| callbackProc = wse_subscribe_stub; |
| break; |
| case WS_DISP_TYPE_UNSUBSCRIBE: |
| debug("Registering endpoint for Unsubscribe"); |
| action = ep->inAction; |
| callbackProc = wse_unsubscribe_stub; |
| break; |
| case WS_DISP_TYPE_RENEW: |
| action = ep->inAction; |
| callbackProc = wse_renew_stub; |
| break; |
| #endif |
| case WS_DISP_TYPE_RAW_DOC: |
| action = ep->inAction; |
| callbackProc = (SoapServiceCallback) ep->serviceEndPoint; |
| break; |
| case WS_DISP_TYPE_CUSTOM_METHOD: |
| debug("Registering endpoint for custom method"); |
| action = ep->inAction; |
| callbackProc = (SoapServiceCallback) ep->serviceEndPoint; |
| break; |
| |
| case WS_DISP_TYPE_PRIVATE: |
| debug("Registering endpoint for private EndPoint"); |
| action = ep->inAction; |
| callbackProc = (SoapServiceCallback) ep->serviceEndPoint; |
| break; |
| |
| default: |
| debug("unknown dispatch type %lu", |
| ep->flags & WS_DISP_TYPE_MASK); |
| break; |
| } |
| |
| if (callbackProc != NULL && |
| (disp = wsman_dispatch_create(soap, action, NULL, NULL, callbackProc, ep, flags))) { |
| dispInfo->map[dispInfo->mapCount].ep = ep; |
| dispInfo->map[dispInfo->mapCount].disp = disp; |
| dispInfo->mapCount++; |
| wsman_dispatch_start(disp); |
| } |
| if (action && action != ep->inAction) { |
| u_free(action); |
| } |
| return (disp == NULL); |
| } |
| |
| /* ENDPOINTS STUBS */ |
| |
| int |
| wsman_identify_stub(SoapOpH op, |
| void *appData, |
| void *opaqueData) |
| { |
| void *data; |
| WsXmlDocH doc = NULL; |
| WsContextH cntx; |
| WsDispatchEndPointInfo *info; |
| XmlSerializerInfo *typeInfo; |
| WsmanStatus *status; |
| SoapH soap; |
| WsEndPointGet endPoint; |
| |
| status = u_zalloc(sizeof(WsmanStatus *)); |
| soap = soap_get_op_soap(op); |
| cntx = ws_create_ep_context(soap, soap_get_op_doc(op, 1)); |
| info = (WsDispatchEndPointInfo *) appData; |
| typeInfo = info->serializationInfo; |
| endPoint = (WsEndPointGet) info->serviceEndPoint; |
| debug("Identify called"); |
| |
| if ((data = endPoint(cntx, status, opaqueData)) == NULL) { |
| error("Identify Fault"); |
| doc = wsman_generate_fault(soap_get_op_doc(op, 1), WSMAN_INTERNAL_ERROR, 0, NULL); |
| } else { |
| doc = wsman_create_response_envelope(soap_get_op_doc(op, 1), NULL); |
| ws_serialize(cntx->serializercntx, ws_xml_get_soap_body(doc), data, typeInfo, |
| WSMID_IDENTIFY_RESPONSE, (char *) info->data, NULL, 1); |
| ws_serializer_free_mem(cntx->serializercntx, data, typeInfo); |
| u_free(data); |
| } |
| |
| if (doc) { |
| soap_set_op_doc(op, doc, 0); |
| } else { |
| error("Response doc invalid"); |
| } |
| |
| ws_destroy_context(cntx); |
| u_free(status); |
| |
| return 0; |
| } |
| |
| |
| |
| |
| int |
| ws_transfer_put_stub(SoapOpH op, |
| void *appData, |
| void *opaqueData) |
| { |
| int retVal = 0; |
| WsXmlDocH doc = NULL; |
| void *outData = NULL; |
| WsmanStatus status; |
| SoapH soap = soap_get_op_soap(op); |
| WsContextH cntx = ws_create_ep_context(soap, soap_get_op_doc(op, 1)); |
| WsDispatchEndPointInfo *info = (WsDispatchEndPointInfo *) appData; |
| XmlSerializerInfo *typeInfo = info->serializationInfo; |
| WsEndPointPut endPoint = (WsEndPointPut) info->serviceEndPoint; |
| |
| WsXmlDocH _doc = soap_get_op_doc(op, 1); |
| WsXmlNodeH _body = ws_xml_get_soap_body(_doc); |
| WsXmlNodeH _r = ws_xml_get_child(_body, 0, NULL, NULL); |
| |
| void *data = ws_deserialize(cntx->serializercntx, _body, typeInfo, |
| ws_xml_get_node_local_name(_r), |
| (char *) info->data, NULL, 0, 0); |
| |
| if ((retVal = endPoint(cntx, data, &outData, &status, opaqueData))) { |
| doc = wsman_generate_fault( _doc, status.fault_code, |
| status.fault_detail_code, NULL); |
| } else { |
| doc = wsman_create_response_envelope(_doc, NULL); |
| if (outData) { |
| ws_serialize(cntx->serializercntx, ws_xml_get_soap_body(doc), outData, |
| typeInfo, TRANSFER_PUT_RESP, |
| (char *) info->data, NULL, 1); |
| ws_serializer_free_mem(cntx->serializercntx, outData, typeInfo); |
| } |
| } |
| |
| if (doc) { |
| soap_set_op_doc(op, doc, 0); |
| } |
| ws_serializer_free_all(cntx->serializercntx); |
| ws_serializer_cleanup(cntx->serializercntx); |
| return retVal; |
| } |
| |
| |
| |
| |
| int |
| ws_transfer_delete_stub(SoapOpH op, |
| void *appData, |
| void *opaqueData) |
| { |
| WsmanStatus status; |
| SoapH soap = soap_get_op_soap(op); |
| WsContextH cntx = ws_create_ep_context(soap, |
| soap_get_op_doc(op, 1)); |
| |
| WsDispatchEndPointInfo *info = (WsDispatchEndPointInfo *) appData; |
| WsEndPointGet endPoint = (WsEndPointGet) info->serviceEndPoint; |
| |
| void *data; |
| WsXmlDocH doc = NULL; |
| |
| wsman_status_init(&status); |
| if ((data = endPoint(cntx, &status, opaqueData)) == NULL) { |
| warning("Transfer Delete fault"); |
| doc = wsman_generate_fault(soap_get_op_doc(op, 1), |
| WSMAN_INVALID_SELECTORS, 0, NULL); |
| } else { |
| debug("Creating Response doc"); |
| doc = wsman_create_response_envelope(soap_get_op_doc(op, 1), NULL); |
| } |
| |
| if (doc) { |
| soap_set_op_doc(op, doc, 0); |
| } else { |
| error("Response doc invalid"); |
| } |
| ws_destroy_context(cntx); |
| return 0; |
| } |
| |
| |
| |
| |
| int |
| ws_transfer_get_stub(SoapOpH op, |
| void *appData, |
| void *opaqueData) |
| { |
| WsmanStatus status; |
| |
| |
| SoapH soap = soap_get_op_soap(op); |
| WsContextH cntx = ws_create_ep_context(soap, soap_get_op_doc(op, 1)); |
| |
| WsDispatchEndPointInfo *info = (WsDispatchEndPointInfo *) appData; |
| XmlSerializerInfo *typeInfo = info->serializationInfo; |
| WsEndPointGet endPoint = (WsEndPointGet) info->serviceEndPoint; |
| |
| void *data; |
| WsXmlDocH doc = NULL; |
| |
| wsman_status_init(&status); |
| if ((data = endPoint(cntx, &status, opaqueData)) == NULL) { |
| warning("Transfer Get fault"); |
| doc = wsman_generate_fault( soap_get_op_doc(op, 1), |
| WSMAN_INVALID_SELECTORS, 0, NULL); |
| } else { |
| debug("Creating Response doc"); |
| doc = wsman_create_response_envelope(soap_get_op_doc(op, 1), NULL); |
| |
| ws_serialize(cntx->serializercntx, ws_xml_get_soap_body(doc), data, typeInfo, |
| TRANSFER_GET_RESP, (char *) info->data, NULL, 1); |
| ws_serializer_free_mem(cntx->serializercntx, data, typeInfo); |
| } |
| |
| if (doc) { |
| debug("Setting operation document"); |
| soap_set_op_doc(op, doc, 0); |
| } else { |
| warning("Response doc invalid"); |
| } |
| |
| ws_destroy_context(cntx); |
| return 0; |
| } |
| |
| |
| |
| WsmanMessage *wsman_get_msg_from_op(SoapOpH op) |
| { |
| op_t *_op = (op_t *)op; |
| WsmanMessage *msg = (WsmanMessage *)_op->data; |
| return msg; |
| } |
| |
| unsigned long wsman_get_maxsize_from_op(SoapOpH op) |
| { |
| op_t *_op = (op_t *)op; |
| return _op->maxsize; |
| } |
| |
| static |
| unsigned long get_total_enum_context(WsContextH cntx){ |
| hscan_t hs; |
| u_lock(cntx->soap); |
| hash_scan_begin(&hs, cntx->enuminfos); |
| unsigned long total = hash_count(hs.hash_table); |
| u_unlock(cntx->soap); |
| return total; |
| } |
| |
| /** |
| * The following extern methods are defined in wsmand-daemon.c, |
| * which is compiled into openwsmand binary, which in turn links |
| * to libwsman.la. So when a call is made to the following methods |
| * from the openwsmand binary, they should be present. |
| * |
| * However, if they are dlopened from somewhere other than |
| * openwsmand library or linked to some other |
| * binary or shared object, then these methods may or may not be |
| * preset, hence marking them as weak symbols and testing to see |
| * if they are resolved before using them. |
| */ |
| #pragma weak wsmand_options_get_max_threads |
| extern int wsmand_options_get_max_threads(void); |
| #pragma weak wsmand_options_get_max_connections_per_thread |
| extern int wsmand_options_get_max_connections_per_thread(void); |
| |
| /** |
| * Enumeration Stub for processing enumeration requests |
| * @param op SOAP pperation handler |
| * @param appData Application data |
| * @return status |
| */ |
| int |
| wsenum_enumerate_stub(SoapOpH op, |
| void *appData, |
| void *opaqueData) |
| { |
| WsXmlDocH doc = NULL; |
| int retVal = 0; |
| WsEnumerateInfo *enumInfo = NULL; |
| WsmanStatus status; |
| WsXmlNodeH resp_node, body; |
| WsContextH soapCntx; |
| SoapH soap = soap_get_op_soap(op); |
| |
| WsDispatchEndPointInfo *ep = (WsDispatchEndPointInfo *) appData; |
| WsEndPointEnumerate endPoint = |
| (WsEndPointEnumerate)ep->serviceEndPoint; |
| |
| WsXmlDocH _doc = soap_get_op_doc(op, 1); |
| WsContextH epcntx; |
| |
| int max_threads = 0; |
| int max_connections_per_thread = 0; |
| int(* fptr)(void); |
| if((fptr = wsmand_options_get_max_threads) != 0){ |
| max_threads = (* fptr)(); |
| if((fptr = wsmand_options_get_max_connections_per_thread) != 0){ |
| max_connections_per_thread = (* fptr)(); |
| } |
| else{ |
| debug("Could not resolve wsmand_options_get_max_connections_per_thread"); |
| max_threads=0; |
| } |
| } |
| else{ |
| debug("Could not resolve wsman_options_get_max_threads"); |
| } |
| |
| if(max_threads){ |
| if(get_total_enum_context(ws_get_soap_context(soap)) >= (max_threads * max_connections_per_thread)){ |
| debug("enum context queue is full, we wait till some expire or are cleared"); |
| doc = wsman_generate_fault(_doc, WSMAN_QUOTA_LIMIT, OWSMAN_NO_DETAILS, |
| "The service is busy servicing other requests. Try later."); |
| if(doc){ |
| soap_set_op_doc(op, doc, 0); |
| } |
| return 1; |
| } |
| } |
| |
| epcntx = ws_create_ep_context(soap, _doc); |
| wsman_status_init(&status); |
| doc = create_enum_info(op, epcntx, _doc, &enumInfo); |
| if (doc != NULL) { |
| /* wrong enum elements met. Fault message generated */ |
| goto DONE; |
| } |
| |
| if (endPoint && (retVal = endPoint(epcntx, enumInfo, &status, opaqueData))) { |
| debug("enumeration fault"); |
| doc = wsman_generate_fault( _doc, status.fault_code, |
| status.fault_detail_code, status.fault_msg); |
| destroy_enuminfo(enumInfo); |
| goto DONE; |
| } |
| if (enumInfo->pullResultPtr) { |
| doc = enumInfo->pullResultPtr; |
| enumInfo->index++; |
| } else { |
| doc = wsman_create_response_envelope( _doc, NULL); |
| } |
| |
| if (!doc) |
| goto DONE; |
| |
| wsman_set_estimated_total(_doc, doc, enumInfo); |
| body = ws_xml_get_soap_body(doc); |
| |
| if (enumInfo->pullResultPtr == NULL) { |
| resp_node = ws_xml_add_child(body, XML_NS_ENUMERATION, |
| WSENUM_ENUMERATE_RESP, NULL); |
| } else { |
| resp_node = ws_xml_get_child(body, 0, |
| XML_NS_ENUMERATION, WSENUM_ENUMERATE_RESP); |
| } |
| |
| soapCntx = ws_get_soap_context(soap); |
| if (( enumInfo->flags & WSMAN_ENUMINFO_OPT ) == WSMAN_ENUMINFO_OPT && |
| (enumInfo->totalItems == 0 || enumInfo->index == enumInfo->totalItems)) { |
| ws_serialize_str(epcntx->serializercntx, resp_node, NULL, |
| XML_NS_ENUMERATION, WSENUM_ENUMERATION_CONTEXT, 0); |
| ws_serialize_str(epcntx->serializercntx, resp_node, |
| NULL, XML_NS_WS_MAN, WSENUM_END_OF_SEQUENCE, 0); |
| destroy_enuminfo(enumInfo); |
| } else { |
| ws_serialize_str(epcntx->serializercntx, resp_node, enumInfo->enumId, |
| XML_NS_ENUMERATION, WSENUM_ENUMERATION_CONTEXT, 0); |
| insert_enum_info(soapCntx, enumInfo); |
| } |
| |
| DONE: |
| if (doc) { |
| soap_set_op_doc(op, doc, 0); |
| } |
| ws_destroy_context(epcntx); |
| u_free(status.fault_msg); |
| return retVal; |
| } |
| |
| |
| |
| int |
| wsenum_release_stub(SoapOpH op, |
| void *appData, |
| void *opaqueData) |
| { |
| int retVal = 0; |
| WsXmlDocH doc = NULL; |
| WsmanStatus status; |
| SoapH soap = soap_get_op_soap(op); |
| WsContextH soapCntx = ws_get_soap_context(soap); |
| WsDispatchEndPointInfo *ep = (WsDispatchEndPointInfo *) appData; |
| WsEndPointRelease endPoint = (WsEndPointRelease) ep->serviceEndPoint; |
| WsXmlDocH _doc = soap_get_op_doc(op, 1); |
| WsEnumerateInfo *enumInfo; |
| |
| wsman_status_init(&status); |
| enumInfo = get_locked_enuminfo(soapCntx, _doc, |
| op, WSENUM_RELEASE, &status); |
| |
| ws_set_context_xml_doc_val(soapCntx, WSFW_INDOC, _doc); |
| |
| if (enumInfo == NULL) { |
| doc = wsman_generate_fault( _doc, |
| status.fault_code, status.fault_detail_code, NULL); |
| |
| } else { |
| if (endPoint && (retVal = endPoint(soapCntx, |
| enumInfo, &status, opaqueData))) { |
| error("endPoint error"); |
| doc = wsman_generate_fault( _doc, |
| WSMAN_INTERNAL_ERROR, |
| OWSMAN_DETAIL_ENDPOINT_ERROR, NULL); |
| unlock_enuminfo(soapCntx, enumInfo); |
| } else { |
| doc = wsman_create_response_envelope( _doc, NULL); |
| debug("Releasing context: %s", enumInfo->enumId); |
| remove_locked_enuminfo(soapCntx, enumInfo); |
| destroy_enuminfo(enumInfo); |
| } |
| } |
| if (doc) { |
| soap_set_op_doc(op, doc, 0); |
| } |
| return retVal; |
| } |
| |
| |
| |
| |
| |
| int |
| wsenum_pull_stub(SoapOpH op, void *appData, |
| void *opaqueData) |
| { |
| WsXmlNodeH node; |
| WsmanStatus status; |
| SoapH soap = soap_get_op_soap(op); |
| WsContextH soapCntx = ws_get_soap_context(soap); |
| |
| WsDispatchEndPointInfo *ep = (WsDispatchEndPointInfo *) appData; |
| XmlSerializerInfo *typeInfo = ep->serializationInfo; |
| WsEndPointPull endPoint = (WsEndPointPull) ep->serviceEndPoint; |
| |
| int retVal = 0, locked = 0; |
| WsXmlDocH doc = NULL; |
| char *enumId = NULL; |
| |
| WsXmlDocH _doc = soap_get_op_doc(op, 1); |
| WsEnumerateInfo *enumInfo; |
| |
| wsman_status_init(&status); |
| enumInfo = get_locked_enuminfo(soapCntx, _doc, |
| op, WSENUM_PULL, &status); |
| |
| if (enumInfo == NULL) { |
| doc = wsman_generate_fault( _doc, status.fault_code, status.fault_detail_code, NULL); |
| goto DONE; |
| } |
| locked = 1; |
| if ((retVal = endPoint(ws_create_ep_context(soap, _doc), |
| enumInfo, &status, opaqueData))) { |
| doc = wsman_generate_fault(_doc, status.fault_code, status.fault_detail_code, NULL); |
| goto DONE; |
| } |
| enumInfo->index++; |
| doc = wsman_create_response_envelope( _doc, NULL); |
| |
| if (!doc) { |
| goto DONE; |
| } |
| |
| wsman_set_estimated_total(_doc, doc, enumInfo); |
| node = ws_xml_add_child(ws_xml_get_soap_body(doc), |
| XML_NS_ENUMERATION, WSENUM_PULL_RESP, NULL); |
| |
| if (node == NULL) { |
| goto DONE; |
| } |
| if (enumInfo->pullResultPtr) { |
| if (enumId) { |
| ws_serialize_str(soapCntx->serializercntx, node, enumId, |
| XML_NS_ENUMERATION, WSENUM_ENUMERATION_CONTEXT, 0); |
| } |
| WsXmlNodeH itemsNode = ws_xml_add_child(node, |
| XML_NS_ENUMERATION, WSENUM_ITEMS, NULL); |
| ws_serialize(soapCntx->serializercntx, itemsNode, enumInfo->pullResultPtr, |
| typeInfo, ep->respName, (char *) ep->data, NULL, 1); |
| ws_serializer_free_mem(soapCntx->serializercntx, |
| enumInfo->pullResultPtr, typeInfo); |
| } else { |
| /* |
| ws_serialize_str(soapCntx, node, NULL, |
| XML_NS_ENUMERATION, WSENUM_ENUMERATION_CONTEXT, 0); |
| */ |
| ws_serialize_str(soapCntx->serializercntx, |
| node, NULL, XML_NS_ENUMERATION, WSENUM_END_OF_SEQUENCE, 0); |
| remove_locked_enuminfo(soapCntx, enumInfo); |
| locked = 0; |
| destroy_enuminfo(enumInfo); |
| } |
| |
| DONE: |
| if (locked) { |
| unlock_enuminfo(soapCntx, enumInfo); |
| } |
| if (doc) { |
| soap_set_op_doc(op, doc, 0); |
| } |
| return retVal; |
| } |
| |
| |
| int |
| wsenum_pull_direct_stub(SoapOpH op, |
| void *appData, |
| void *opaqueData) |
| { |
| WsmanStatus status; |
| WsXmlDocH doc = NULL; |
| SoapH soap = soap_get_op_soap(op); |
| WsContextH soapCntx = ws_get_soap_context(soap); |
| WsDispatchEndPointInfo *ep = (WsDispatchEndPointInfo *) appData; |
| #ifdef ENABLE_EVENTING_SUPPORT |
| WsNotificationInfoH notificationInfo = NULL; |
| #endif |
| |
| WsEndPointPull endPoint = (WsEndPointPull) ep->serviceEndPoint; |
| int retVal = 0; |
| WsXmlDocH _doc = soap_get_op_doc(op, 1); |
| int locked = 0; |
| WsEnumerateInfo *enumInfo; |
| WsSubscribeInfo *subsInfo = NULL; |
| wsman_status_init(&status); |
| enumInfo = get_locked_enuminfo(soapCntx, |
| _doc, op, WSENUM_PULL, &status); |
| |
| if (enumInfo == NULL) { |
| subsInfo = search_pull_subs_info(soap, _doc); |
| if(subsInfo == NULL) { |
| error("Invalid enumeration context..."); |
| doc = wsman_generate_fault( _doc, status.fault_code, status.fault_detail_code, NULL); |
| goto cleanup; |
| } |
| } |
| if (enumInfo) { //pull things from "enumerate" results |
| locked = 1; |
| |
| if ((retVal = endPoint(ws_create_ep_context(soap, _doc), |
| enumInfo, &status, opaqueData))) { |
| doc = wsman_generate_fault( _doc, status.fault_code, status.fault_detail_code, NULL); |
| // ws_remove_context_val(soapCntx, cntxName); |
| goto cleanup; |
| } |
| |
| enumInfo->index++; |
| if (enumInfo->pullResultPtr) { |
| WsXmlNodeH body; |
| WsXmlNodeH response, items; |
| doc = enumInfo->pullResultPtr; |
| wsman_set_estimated_total(_doc, doc, enumInfo); |
| |
| body = ws_xml_get_soap_body(doc); |
| response = ws_xml_get_child(body, 0, |
| XML_NS_ENUMERATION, WSENUM_PULL_RESP); |
| items = ws_xml_get_child(response, 0, |
| XML_NS_ENUMERATION, WSENUM_ITEMS); |
| |
| if (enumInfo->totalItems == 0 || enumInfo->index == enumInfo->totalItems) { |
| /* |
| ws_serialize_str(soapCntx, response, NULL, |
| XML_NS_ENUMERATION, WSENUM_ENUMERATION_CONTEXT, 0); |
| */ |
| ws_serialize_str(soapCntx->serializercntx, response, NULL, |
| XML_NS_ENUMERATION, WSENUM_END_OF_SEQUENCE, 0); |
| remove_locked_enuminfo(soapCntx, enumInfo); |
| locked = 0; |
| destroy_enuminfo(enumInfo); |
| } else { |
| /* add Context before Items to comply to WS-Enumeration xsd */ |
| ws_xml_add_prev_sibling(items, XML_NS_ENUMERATION, |
| WSENUM_ENUMERATION_CONTEXT, enumInfo->enumId); |
| } |
| } |
| } |
| #ifdef ENABLE_EVENTING_SUPPORT |
| else { //pull things from notifications |
| ws_xml_destroy_doc(doc); |
| pthread_mutex_lock(&subsInfo->notificationlock); |
| int count = soap->eventpoolOpSet->count(subsInfo->subsId); |
| int max_elements = 1; |
| if(count > 0) { |
| doc = ws_xml_create_envelope(); |
| WsXmlNodeH docnode = ws_xml_get_soap_body(doc); |
| WsXmlNodeH docheader = ws_xml_get_soap_header(doc); |
| docnode = ws_xml_add_child(docnode, XML_NS_ENUMERATION, WSENUM_PULL_RESP, NULL); |
| if(docnode) { |
| ws_xml_add_child_format(docnode, XML_NS_ENUMERATION, WSENUM_ENUMERATION_CONTEXT, |
| "uuid:%s", subsInfo->subsId); |
| } |
| WsXmlDocH notidoc = NULL; |
| WsXmlNodeH header = ws_xml_get_soap_header(_doc); |
| if (ws_xml_get_child(header, 0,XML_NS_WS_MAN, WSM_REQUEST_TOTAL) != NULL) { |
| WsXmlNodeH response_header =ws_xml_get_soap_header(doc); |
| response_header = ws_xml_add_child(response_header, XML_NS_WS_MAN, |
| WSM_TOTAL_ESTIMATE, NULL); |
| if(response_header) |
| ws_xml_add_node_attr(response_header, XML_NS_SCHEMA_INSTANCE, XML_SCHEMA_NIL, "true"); |
| } |
| header = ws_xml_get_child(header, 0, XML_NS_ENUMERATION, WSENUM_MAX_ELEMENTS); |
| if(header) |
| max_elements = atoi(ws_xml_get_node_text(header)); |
| if(max_elements > 1 && count > 1) { |
| docnode = ws_xml_add_child(docnode, XML_NS_ENUMERATION, WSENUM_ITEMS, NULL); |
| } |
| while(max_elements > 0) { |
| if(soap->eventpoolOpSet->remove(subsInfo->subsId, ¬ificationInfo)) |
| break; |
| ws_xml_add_child(docheader, XML_NS_ADDRESSING, WSA_ACTION, notificationInfo->EventAction); |
| notidoc = notificationInfo->EventContent; |
| WsXmlNodeH tempnode = ws_xml_get_doc_root(notidoc); |
| ws_xml_duplicate_tree(docnode, tempnode); |
| delete_notification_info(notificationInfo); |
| max_elements--; |
| } |
| } |
| else { |
| status.fault_code = WSMAN_TIMED_OUT; |
| doc = wsman_generate_fault( _doc, status.fault_code, status.fault_detail_code, NULL); |
| } |
| pthread_mutex_unlock(&subsInfo->notificationlock); |
| } |
| #endif |
| cleanup: |
| if (locked) { |
| unlock_enuminfo(soapCntx, enumInfo); |
| } |
| if (doc) { |
| soap_set_op_doc(op, doc, 0); |
| } else { |
| error("doc is null"); |
| } |
| |
| return retVal; |
| } |
| |
| static list_t * |
| wsman_get_expired_enuminfos(WsContextH cntx) |
| { |
| list_t *list = NULL; |
| hnode_t *hn; |
| hscan_t hs; |
| WsEnumerateInfo *enumInfo; |
| struct timeval tv; |
| unsigned long mytime; |
| unsigned long aeit = cntx->enumIdleTimeout; |
| |
| if (aeit == 0) { |
| return NULL; |
| } |
| gettimeofday(&tv, NULL); |
| mytime = tv.tv_sec; |
| u_lock(cntx->soap); |
| if (hash_isempty(cntx->enuminfos)) { |
| u_unlock(cntx->soap); |
| return NULL; |
| } |
| hash_scan_begin(&hs, cntx->enuminfos); |
| while ((hn = hash_scan_next(&hs))) { |
| enumInfo = (WsEnumerateInfo *)hnode_get(hn); |
| if (enumInfo->flags & WSMAN_ENUMINFO_INWORK_FLAG) { |
| debug("Enum in work: %s", enumInfo->enumId); |
| continue; |
| } |
| if ((enumInfo->timeStamp + aeit > mytime) && |
| ((enumInfo->expires == 0) || |
| (enumInfo->expires > mytime))) { |
| continue; |
| } |
| if (list == NULL) { |
| list = list_create(LISTCOUNT_T_MAX); |
| } |
| if (list == NULL) { |
| u_unlock(cntx->soap); |
| error("could not create list"); |
| return NULL; |
| } |
| hash_scan_delfree(cntx->enuminfos, hn); |
| list_append(list, lnode_create(enumInfo)); |
| debug("Enum expired list appended: %s", enumInfo->enumId); |
| } |
| u_unlock(cntx->soap); |
| return list; |
| } |
| |
| void |
| wsman_timeouts_manager(WsContextH cntx, void *opaqueData) |
| { |
| list_t *list = wsman_get_expired_enuminfos(cntx); |
| lnode_t *node; |
| WsEnumerateInfo *enumInfo; |
| WsmanStatus status; |
| |
| if (list == NULL) { |
| return; |
| } |
| while ((node = list_del_first(list))) { |
| enumInfo = (WsEnumerateInfo *)lnode_get(node); |
| debug("EnumContext expired : %s", enumInfo->enumId); |
| lnode_destroy(node); |
| if (enumInfo->releaseproc) { |
| if (enumInfo->releaseproc(cntx, enumInfo, &status, opaqueData)) { |
| debug("released with failure: %s", |
| enumInfo->enumId); |
| } else { |
| debug("released: %s", enumInfo->enumId); |
| } |
| } else { |
| debug("no release endpoint: %s", enumInfo->enumId); |
| } |
| destroy_enuminfo(enumInfo); |
| if (list_isempty(list)) { |
| list_destroy(list); |
| break; |
| } |
| } |
| return; |
| } |
| |
| |
| #ifdef ENABLE_EVENTING_SUPPORT |
| static int destination_reachable(char *url) |
| { |
| int valid = 0; |
| u_uri_t *uri = NULL; |
| if(strstr(url, "http") == NULL) |
| return valid; |
| if (u_uri_parse((const char *)url, &uri) == 0) { |
| valid = 1; |
| } |
| u_uri_free(uri); |
| return valid; |
| } |
| |
| WsEventThreadContextH |
| ws_create_event_context(SoapH soap, WsSubscribeInfo *subsInfo, WsXmlDocH doc) |
| { |
| WsEventThreadContextH eventcntx = u_malloc(sizeof(*eventcntx)); |
| eventcntx->soap = soap; |
| eventcntx->subsInfo = subsInfo; |
| eventcntx->outdoc = doc; |
| return eventcntx; |
| } |
| |
| static void |
| destroy_subsinfo(WsSubscribeInfo * subsInfo) |
| { |
| if(subsInfo == NULL) return; |
| u_free(subsInfo->uri); |
| u_free(subsInfo->auth_data.username); |
| u_free(subsInfo->auth_data.password); |
| u_free(subsInfo->epr_notifyto); |
| u_free(subsInfo->locale); |
| u_free(subsInfo->soapNs); |
| u_free(subsInfo->contentEncoding); |
| u_free(subsInfo->cim_namespace); |
| u_free(subsInfo->username); |
| u_free(subsInfo->password); |
| u_free(subsInfo->certificate_thumbprint); |
| if (subsInfo->filter) { |
| filter_destroy(subsInfo->filter); |
| } |
| ws_xml_destroy_doc(subsInfo->bookmarkDoc); |
| ws_xml_destroy_doc(subsInfo->templateDoc); |
| ws_xml_destroy_doc(subsInfo->heartbeatDoc); |
| u_free(subsInfo); |
| } |
| |
| |
| static void |
| create_notification_template(WsXmlDocH indoc, WsSubscribeInfo *subsInfo) |
| { |
| WsXmlDocH notificationDoc = ws_xml_create_envelope(); |
| WsXmlNodeH temp = NULL; |
| WsXmlNodeH node = NULL; |
| WsXmlNodeH header = NULL; |
| header = ws_xml_get_soap_header(notificationDoc); |
| ws_xml_add_child(header, XML_NS_ADDRESSING, WSA_TO, subsInfo->epr_notifyto); |
| if(subsInfo->deliveryMode == WS_EVENT_DELIVERY_MODE_EVENTS || |
| subsInfo->deliveryMode == WS_EVENT_DELIVERY_MODE_PUSHWITHACK) { |
| ws_xml_add_child(header, XML_NS_WS_MAN, WSM_ACKREQUESTED, NULL); |
| } |
| node = ws_xml_get_soap_body(indoc); |
| node = ws_xml_get_child(node, 0, XML_NS_EVENTING, WSEVENT_SUBSCRIBE); |
| node = ws_xml_get_child(node, 0, XML_NS_EVENTING, WSEVENT_DELIVERY); |
| node = ws_xml_get_child(node, 0, XML_NS_EVENTING, WSEVENT_NOTIFY_TO); |
| temp = ws_xml_get_child(node, 0, XML_NS_ADDRESSING, WSA_REFERENCE_PROPERTIES); |
| if(temp == NULL) |
| node = ws_xml_get_child(node, 0, XML_NS_ADDRESSING, WSA_REFERENCE_PARAMETERS); |
| if(node ) { |
| ws_xml_duplicate_children(header, node); |
| } |
| subsInfo->templateDoc = ws_xml_duplicate_doc(notificationDoc); |
| subsInfo->heartbeatDoc = ws_xml_duplicate_doc( notificationDoc); |
| temp = ws_xml_get_soap_header(subsInfo->heartbeatDoc); |
| temp = ws_xml_add_child(temp, XML_NS_ADDRESSING, WSA_ACTION, WSMAN_ACTION_HEARTBEAT); |
| ws_xml_add_node_attr(temp, XML_NS_XML_SCHEMA, SOAP_MUST_UNDERSTAND, "true"); |
| ws_xml_destroy_doc(notificationDoc); |
| } |
| |
| |
| static WsXmlDocH |
| create_subs_info(SoapOpH op, |
| WsContextH epcntx, |
| WsXmlDocH indoc, |
| WsSubscribeInfo**sInfo) |
| { |
| WsXmlNodeH node = ws_xml_get_soap_body(indoc); |
| WsXmlNodeH subNode = ws_xml_get_child(node, 0, XML_NS_EVENTING, WSEVENT_SUBSCRIBE); |
| WsXmlNodeH temp; |
| WsXmlDocH outdoc = NULL; |
| WsSubscribeInfo *subsInfo; |
| WsXmlAttrH attr = NULL; |
| op_t *_op = (op_t *) op; |
| WsmanMessage *msg = (WsmanMessage *) _op->data; |
| WsmanFaultCodeType fault_code = WSMAN_RC_OK; |
| WsmanFaultDetailType fault_detail_code = WSMAN_DETAIL_OK; |
| char *str = NULL; |
| time_t timeout; |
| int r; |
| char *soapNs = NULL, *ntext = NULL; |
| |
| |
| *sInfo = NULL; |
| subsInfo = (WsSubscribeInfo *)u_zalloc(sizeof (WsSubscribeInfo)); |
| if (subsInfo == NULL) { |
| error("No memory"); |
| fault_code = WSMAN_INTERNAL_ERROR; |
| goto DONE; |
| } |
| if((r = pthread_mutex_init(&subsInfo->notificationlock, NULL)) != 0) { |
| fault_code = WSMAN_INTERNAL_ERROR; |
| goto DONE; |
| } |
| subsInfo->uri = u_strdup(wsman_get_resource_uri(epcntx, indoc)); |
| if(!subNode) { |
| message("No subsribe body"); |
| fault_code = WSE_INVALID_MESSAGE; |
| goto DONE; |
| } |
| soapNs = ws_xml_get_node_name_ns(ws_xml_get_doc_root(indoc)); |
| subsInfo->soapNs = u_strdup(soapNs); |
| node = ws_xml_get_child(subNode, 0, XML_NS_WS_MAN, WSM_SENDBOOKMARKS); |
| if(node) { |
| subsInfo->bookmarksFlag = 1; |
| } |
| node = ws_xml_get_child(subNode, 0, XML_NS_WS_MAN, WSM_BOOKMARK); |
| if(node) { |
| if(ws_xml_get_node_text(node) && |
| !strcmp(ws_xml_get_node_text(node), WSM_DEFAULTBOOKMARK)){ |
| subsInfo->flags |= WSMAN_SUBSCRIBEINFO_BOOKMARK_DEFAULT; |
| } |
| else { |
| subsInfo->bookmarkDoc = ws_xml_create_doc(XML_NS_WS_MAN, WSM_BOOKMARK); |
| temp = ws_xml_get_doc_root(subsInfo->bookmarkDoc); |
| ws_xml_duplicate_children(temp, node); |
| } |
| } |
| node = ws_xml_get_child(subNode, 0, XML_NS_EVENTING, WSEVENT_EXPIRES); |
| if (node == NULL) { |
| debug("No wsen:Expires"); |
| subsInfo->expires = 0; |
| } |
| else { |
| wsman_set_expiretime(node, &subsInfo->expires, &fault_code); |
| if (fault_code != WSMAN_RC_OK) { |
| debug("Invalid expiration time!"); |
| goto DONE; |
| } |
| if(time_expired(subsInfo->expires)) { |
| fault_code = WSE_INVALID_EXPIRATION_TIME; |
| debug("Invalid expiration time!"); |
| goto DONE; |
| } |
| } |
| node = ws_xml_get_child(subNode, 0, XML_NS_EVENTING, WSEVENT_DELIVERY); |
| attr = ws_xml_find_node_attr(node, NULL,WSEVENT_DELIVERY_MODE); |
| if(attr) { |
| str = ws_xml_get_attr_value(attr); |
| if (!strcasecmp(str, WSEVENT_DELIVERY_MODE_PUSH)) { |
| subsInfo->deliveryMode = WS_EVENT_DELIVERY_MODE_PUSH; |
| } |
| else if (!strcasecmp(str, WSEVENT_DELIVERY_MODE_PUSHWITHACK)) { |
| subsInfo->deliveryMode = WS_EVENT_DELIVERY_MODE_PUSHWITHACK; |
| } |
| else if (!strcasecmp(str, WSEVENT_DELIVERY_MODE_EVENTS)) { |
| subsInfo->deliveryMode = WS_EVENT_DELIVERY_MODE_EVENTS; |
| } |
| else { |
| subsInfo->deliveryMode = WS_EVENT_DELIVERY_MODE_PULL; |
| } |
| } |
| else { |
| //"push" is the default delivery mode |
| subsInfo->deliveryMode = WS_EVENT_DELIVERY_MODE_PUSH; |
| } |
| temp = ws_xml_get_child(node, 0, XML_NS_WS_MAN, WSM_CONTENTCODING); |
| if(temp){ |
| str = ws_xml_get_node_text(temp); |
| subsInfo->contentEncoding = u_strdup(str); |
| } |
| temp = ws_xml_get_child(node, 0, XML_NS_WS_MAN, WSM_LOCALE); |
| if(temp) { |
| attr = ws_xml_find_node_attr(temp, XML_NS_WS_MAN, WSM_LOCALE); |
| if(attr) |
| subsInfo->locale = u_strdup(ws_xml_get_attr_value(attr)); |
| } |
| temp = ws_xml_get_child(node, 0, XML_NS_WS_MAN, WSM_HEARTBEATS); |
| if(temp) { |
| str = ws_xml_get_node_text(temp); |
| debug("[heartbeat interval = %s]",str); |
| if(str[0]=='P') { |
| // xml duration |
| if (ws_deserialize_duration(str, &timeout)) { |
| fault_code = WSEN_INVALID_EXPIRATION_TIME; |
| goto DONE; |
| } |
| debug("timeout = %d", timeout); |
| subsInfo->heartbeatInterval = timeout * 1000; |
| subsInfo->heartbeatCountdown = subsInfo->heartbeatInterval; |
| } |
| } |
| if(subsInfo->deliveryMode != WS_EVENT_DELIVERY_MODE_PULL) { |
| temp = ws_xml_get_child(node, 0, XML_NS_EVENTING, WSEVENT_NOTIFY_TO); |
| if(temp == NULL) { |
| message("No notification destination"); |
| fault_code = WSE_INVALID_MESSAGE; |
| goto DONE; |
| } |
| str = ws_xml_get_node_text(ws_xml_get_child(temp, 0, XML_NS_ADDRESSING, WSA_ADDRESS)); |
| debug("event sink: %s", str); |
| if(str && strcmp(str, "")) { |
| subsInfo->epr_notifyto = u_strdup(str); |
| if(destination_reachable(str) == 0) { |
| fault_code = WSMAN_EVENT_DELIVER_TO_UNUSABLE; |
| goto DONE; |
| } |
| } |
| else { |
| fault_code = WSE_INVALID_MESSAGE; |
| goto DONE; |
| } |
| temp = ws_xml_get_child(node, 0, XML_NS_WS_MAN, WSM_AUTH); |
| if(temp) { |
| attr = ws_xml_find_node_attr(temp, NULL, WSM_PROFILE); |
| if(attr) { |
| str = ws_xml_get_attr_value(attr); |
| if(!strcasecmp(str, WSMAN_SECURITY_PROFILE_HTTP_BASIC)) |
| subsInfo->deliveryAuthType = WSMAN_SECURITY_PROFILE_HTTP_BASIC_TYPE; |
| else if(!strcasecmp(str, WSMAN_SECURITY_PROFILE_HTTP_DIGEST)) |
| subsInfo->deliveryAuthType = WSMAN_SECURITY_PROFILE_HTTP_DIGEST_TYPE; |
| else if(!strcasecmp(str, WSMAN_SECURITY_PROFILE_HTTPS_BASIC)) |
| subsInfo->deliveryAuthType = WSMAN_SECURITY_PROFILE_HTTPS_BASIC_TYPE; |
| else if(!strcasecmp(str, WSMAN_SECURITY_PROFILE_HTTPS_DIGEST)) |
| subsInfo->deliveryAuthType = WSMAN_SECURITY_PROFILE_HTTPS_DIGEST_TYPE; |
| else if(!strcasecmp(str, WSMAN_SECURITY_PROFILE_HTTPS_MUTUAL)) |
| subsInfo->deliveryAuthType = WSMAN_SECURITY_PROFILE_HTTPS_MUTUAL_TYPE; |
| else if(!strcasecmp(str, WSMAN_SECURITY_PROFILE_HTTPS_MUTUAL_BASIC)) |
| subsInfo->deliveryAuthType = WSMAN_SECURITY_PROFILE_HTTPS_MUTUAL_BASIC_TYPE; |
| else if(!strcasecmp(str, WSMAN_SECURITY_PROFILE_HTTPS_MUTUAL_DIGEST)) |
| subsInfo->deliveryAuthType = WSMAN_SECURITY_PROFILE_HTTPS_MUTUAL_DIGEST_TYPE; |
| else if(!strcasecmp(str, WSMAN_SECURITY_PROFILE_HTTPS_SPNEGO_KERBEROS)) |
| subsInfo->deliveryAuthType = WSMAN_SECURITY_PROFILE_HTTPS_SPNEGO_KERBEROS_TYPE; |
| else if(!strcasecmp(str, WSMAN_SECURITY_PROFILE_HTTPS_MUTUAL_SPNEGO_KERBEROS)) |
| subsInfo->deliveryAuthType = WSMAN_SECURITY_PROFILE_HTTPS_MUTUAL_SPNEGO_KERBEROS_TYPE; |
| else if(!strcasecmp(str, WSMAN_SECURITY_PROFILE_HTTP_SPNEGO_KERBEROS)) |
| subsInfo->deliveryAuthType = WSMAN_SECURITY_PROFILE_HTTP_SPNEGO_KERBEROS_TYPE; |
| else { |
| fault_code = WSMAN_INVALID_OPTIONS; |
| fault_detail_code = WSMAN_DETAIL_AUTHERIZATION_MODE; |
| goto DONE; |
| } |
| debug("auth profile type = %d", subsInfo->deliveryAuthType); |
| |
| } |
| } |
| } |
| if(wsman_parse_credentials(indoc, subsInfo, &fault_code, &fault_detail_code)) { |
| goto DONE; |
| } |
| if(wsman_parse_event_request(indoc, subsInfo, &fault_code, &fault_detail_code)) { |
| goto DONE; |
| } |
| if (msg->auth_data.username != NULL) { |
| subsInfo->auth_data.username = |
| u_strdup(msg->auth_data.username); |
| subsInfo->auth_data.password = |
| u_strdup(msg->auth_data.password); |
| } else { |
| subsInfo->auth_data.username = NULL; |
| subsInfo->auth_data.password = NULL; |
| } |
| temp = ws_xml_get_soap_header(indoc); |
| temp = ws_xml_get_child(temp, 0, XML_NS_OPENWSMAN, "FormerUID"); |
| ntext = ws_xml_get_node_text(temp); |
| if(temp && ntext) { //it is a request from the saved reqeust. So we recover the former UUID |
| strncpy(subsInfo->subsId, ntext, EUIDLEN); |
| debug("Recover to uuid:%s",subsInfo->subsId); |
| } |
| else |
| generate_uuid(subsInfo->subsId, EUIDLEN, 1); |
| if(subsInfo->deliveryMode != WS_EVENT_DELIVERY_MODE_PULL) |
| create_notification_template(indoc, subsInfo); |
| DONE: |
| if (fault_code != WSMAN_RC_OK) { |
| outdoc = wsman_generate_fault(indoc, fault_code, fault_detail_code, NULL); |
| destroy_subsinfo(subsInfo); |
| } else { |
| *sInfo = subsInfo; |
| } |
| return outdoc; |
| } |
| |
| |
| /** |
| * Subscribe Stub for processing subscription requests |
| * @param op SOAP pperation handler |
| * @param appData Application data |
| * @return status |
| */ |
| int |
| wse_subscribe_stub(SoapOpH op, void *appData, void *opaqueData) |
| { |
| WsXmlDocH doc = NULL; |
| int retVal = 0; |
| WsSubscribeInfo *subsInfo = NULL; |
| WsmanStatus status; |
| WsXmlNodeH inNode, body, header, temp; |
| SoapH soap = soap_get_op_soap(op); |
| WsContextH soapCntx = ws_get_soap_context(soap); |
| int i; |
| WsDispatchEndPointInfo *ep = (WsDispatchEndPointInfo *) appData; |
| WsEndPointSubscribe endPoint = |
| (WsEndPointSubscribe)ep->serviceEndPoint; |
| |
| WsXmlDocH _doc = soap_get_op_doc(op, 1); |
| WsContextH epcntx; |
| char *buf = NULL; |
| char *expiresstr = NULL; |
| int len; |
| epcntx = ws_create_ep_context(soap, _doc); |
| wsman_status_init(&status); |
| doc = create_subs_info(op, epcntx, _doc, &subsInfo); |
| if (doc != NULL) { |
| goto DONE; |
| } |
| if (endPoint && (retVal = endPoint(epcntx, subsInfo, &status, opaqueData))) { |
| debug("Subscribe fault"); |
| doc = wsman_generate_fault( _doc, status.fault_code, status.fault_detail_code, status.fault_msg); |
| destroy_subsinfo(subsInfo); |
| goto DONE; |
| } |
| doc = wsman_create_response_envelope(_doc, NULL); |
| if (!doc) |
| goto DONE; |
| |
| char str[30]; |
| wsman_expiretime2xmldatetime(subsInfo->expires, str); |
| if(soap->subscriptionOpSet) { |
| temp = ws_xml_get_child(ws_xml_get_soap_body(_doc), 0, XML_NS_EVENTING, WSEVENT_SUBSCRIBE); |
| temp = ws_xml_get_child(temp, 0, XML_NS_EVENTING, WSEVENT_EXPIRES); |
| if(temp) { |
| expiresstr = strdup(ws_xml_get_node_text(temp)); |
| ws_xml_set_node_text(temp, str); |
| } |
| temp = ws_xml_get_soap_header(_doc); |
| inNode = ws_xml_get_child(temp, 0, XML_NS_OPENWSMAN, "FormerUID"); |
| if(inNode == NULL) |
| ws_xml_add_child(temp, XML_NS_OPENWSMAN, "FormerUID", subsInfo->subsId); |
| ws_xml_dump_memory_enc(_doc, &buf, &len, "UTF-8"); |
| if(buf) { |
| soap->subscriptionOpSet->save_subscritption(soap->uri_subsRepository, subsInfo->subsId, (unsigned char*)buf); |
| u_free(buf); |
| } |
| } |
| lnode_t * sinfo = lnode_create(subsInfo); |
| pthread_mutex_lock(&soap->lockSubs); |
| list_append(soapCntx->subscriptionMemList, sinfo); |
| pthread_mutex_unlock(&soap->lockSubs); |
| debug("subscription uuid:%s kept in the memory", subsInfo->subsId); |
| header = ws_xml_get_soap_header(doc); |
| inNode = ws_xml_get_soap_header(_doc); |
| inNode = ws_xml_get_child(inNode, 0, XML_NS_ADDRESSING, WSA_REPLY_TO); |
| inNode = ws_xml_get_child(inNode, 0, XML_NS_ADDRESSING, WSA_REFERENCE_PROPERTIES); |
| if(inNode == NULL) |
| inNode = ws_xml_get_child(inNode, 0, XML_NS_ADDRESSING, WSA_REFERENCE_PARAMETERS); |
| if(inNode) { |
| for (i = 0; |
| (temp = |
| ws_xml_get_child(inNode, i, NULL, NULL)) != NULL; |
| i++) { |
| ws_xml_duplicate_tree(header, temp); |
| } |
| } |
| body = ws_xml_get_soap_body(doc); |
| inNode = ws_xml_add_child(body, XML_NS_EVENTING, WSEVENT_SUBSCRIBE_RESP, NULL); |
| temp = ws_xml_add_child(inNode, XML_NS_EVENTING, WSEVENT_SUBSCRIPTION_MANAGER, NULL); |
| if(subsInfo->expires) |
| ws_xml_add_child(inNode, XML_NS_EVENTING, WSEVENT_EXPIRES, expiresstr); |
| if(subsInfo->deliveryMode == WS_EVENT_DELIVERY_MODE_PULL) |
| ws_xml_add_child_format(inNode, XML_NS_ENUMERATION, |
| WSENUM_ENUMERATION_CONTEXT, "uuid:%s", subsInfo->subsId); |
| inNode = temp; |
| if(inNode){ |
| temp = ws_xml_get_soap_header(_doc); |
| temp = ws_xml_get_child(temp, 0, XML_NS_ADDRESSING, WSA_TO); |
| ws_xml_add_child(inNode,XML_NS_ADDRESSING,WSA_ADDRESS,ws_xml_get_node_text(temp)); |
| } |
| temp = ws_xml_add_child(inNode, XML_NS_ADDRESSING, WSA_REFERENCE_PARAMETERS, NULL); |
| if(temp) |
| ws_xml_add_child_format(temp, XML_NS_EVENTING, WSEVENT_IDENTIFIER, "uuid:%s", subsInfo->subsId); |
| DONE: |
| if (doc) { |
| soap_set_op_doc(op, doc, 0); |
| } |
| u_free(expiresstr); |
| ws_serializer_free_all(epcntx->serializercntx); |
| ws_destroy_context(epcntx); |
| u_free(status.fault_msg); |
| return retVal; |
| } |
| |
| |
| |
| |
| /** |
| * Unsubscribe Stub for processing unsubscription requests |
| * @param op SOAP pperation handler |
| * @param appData Application data |
| * @return status |
| */ |
| int |
| wse_unsubscribe_stub(SoapOpH op, void *appData, void *opaqueData) |
| { |
| WsXmlDocH doc = NULL; |
| int retVal = 0; |
| WsSubscribeInfo *subsInfo = NULL; |
| WsmanStatus status; |
| WsXmlNodeH inNode; |
| WsXmlNodeH header; |
| SoapH soap = soap_get_op_soap(op); |
| WsContextH soapCntx = ws_get_soap_context(soap); |
| WsDispatchEndPointInfo *ep = (WsDispatchEndPointInfo *) appData; |
| WsEndPointSubscribe endPoint = |
| (WsEndPointSubscribe)ep->serviceEndPoint; |
| |
| WsXmlDocH _doc = soap_get_op_doc(op, 1); |
| WsContextH epcntx; |
| |
| epcntx = ws_create_ep_context(soap, _doc); |
| wsman_status_init(&status); |
| header = ws_xml_get_soap_header(_doc); |
| inNode = ws_xml_get_child(header, 0, XML_NS_EVENTING, WSEVENT_IDENTIFIER); |
| if(inNode == NULL) { |
| status.fault_code = WSE_INVALID_MESSAGE; |
| status.fault_detail_code = WSMAN_DETAIL_INVALID_VALUE; |
| goto DONE; |
| } |
| char *uuid = ws_xml_get_node_text(inNode); |
| lnode_t *t = NULL; |
| pthread_mutex_lock(&soap->lockSubs); |
| if(!list_isempty(soapCntx->subscriptionMemList)) { |
| t = list_first(soapCntx->subscriptionMemList); |
| subsInfo = (WsSubscribeInfo *)t->list_data; |
| while(t && strcasecmp(subsInfo->subsId, uuid+5)) { |
| t = list_next(soapCntx->subscriptionMemList, t); |
| if(t) |
| subsInfo = (WsSubscribeInfo *)t->list_data; |
| } |
| } |
| if(t == NULL) { |
| status.fault_code = WSMAN_INVALID_PARAMETER; |
| status.fault_detail_code = WSMAN_DETAIL_INVALID_VALUE; |
| doc = wsman_generate_fault( _doc, |
| status.fault_code, status.fault_detail_code, NULL); |
| pthread_mutex_unlock(&soap->lockSubs); |
| goto DONE; |
| } |
| pthread_mutex_unlock(&soap->lockSubs); |
| if (endPoint && (retVal = endPoint(epcntx, subsInfo, &status, opaqueData))) { |
| debug("UnSubscribe fault"); |
| doc = wsman_generate_fault( _doc, status.fault_code, status.fault_detail_code, status.fault_msg); |
| goto DONE; |
| } |
| pthread_mutex_lock(&subsInfo->notificationlock); |
| subsInfo->flags |= WSMAN_SUBSCRIBEINFO_UNSUBSCRIBE; |
| pthread_mutex_unlock(&subsInfo->notificationlock); |
| debug("subscription %s unsubscribed", uuid); |
| doc = wsman_create_response_envelope( _doc, NULL); |
| if (!doc) |
| goto DONE; |
| DONE: |
| if (doc) { |
| soap_set_op_doc(op, doc, 0); |
| } |
| ws_serializer_free_all(epcntx->serializercntx); |
| ws_destroy_context(epcntx); |
| u_free(status.fault_msg); |
| return retVal; |
| } |
| |
| |
| /** |
| * Renew Stub for processing renew requests |
| * @param op SOAP pperation handler |
| * @param appData Application data |
| * @return status |
| */ |
| int |
| wse_renew_stub(SoapOpH op, void *appData, void *opaqueData) |
| { |
| WsXmlDocH doc = NULL; |
| int retVal = 0; |
| WsSubscribeInfo *subsInfo; |
| WsmanStatus status; |
| WsXmlNodeH inNode; |
| WsXmlNodeH body; |
| WsXmlNodeH header; |
| SoapH soap = soap_get_op_soap(op); |
| WsContextH soapCntx = ws_get_soap_context(soap); |
| char * expirestr = NULL; |
| |
| WsDispatchEndPointInfo *ep = (WsDispatchEndPointInfo *) appData; |
| WsEndPointSubscribe endPoint = |
| (WsEndPointSubscribe)ep->serviceEndPoint; |
| |
| WsXmlDocH _doc = soap_get_op_doc(op, 1); |
| WsContextH epcntx; |
| epcntx = ws_create_ep_context(soap, _doc); |
| wsman_status_init(&status); |
| body = ws_xml_get_soap_body(_doc); |
| header = ws_xml_get_soap_header(_doc); |
| inNode = ws_xml_get_child(header, 0, XML_NS_EVENTING, WSEVENT_IDENTIFIER); |
| char *uuid = ws_xml_get_node_text(inNode); |
| if(uuid == NULL) { |
| status.fault_code = WSE_INVALID_MESSAGE; |
| status.fault_detail_code = WSMAN_DETAIL_MISSING_VALUES; |
| doc = wsman_generate_fault( _doc, status.fault_code, status.fault_detail_code, NULL); |
| goto DONE; |
| } |
| pthread_mutex_lock(&soap->lockSubs); |
| lnode_t *t = NULL; |
| if(!list_isempty(soapCntx->subscriptionMemList)) { |
| t = list_first(soapCntx->subscriptionMemList); |
| subsInfo = (WsSubscribeInfo *)t->list_data; |
| while(t && strcasecmp(subsInfo->subsId, uuid+5)) { |
| t = list_next(soapCntx->subscriptionMemList, t); |
| if(t) |
| subsInfo = (WsSubscribeInfo *)t->list_data; |
| } |
| } |
| if(t == NULL) { |
| status.fault_code = WSE_UNABLE_TO_RENEW; |
| doc = wsman_generate_fault( _doc, status.fault_code, status.fault_detail_code, NULL); |
| pthread_mutex_unlock(&soap->lockSubs); |
| goto DONE; |
| } |
| pthread_mutex_unlock(&soap->lockSubs); |
| inNode = ws_xml_get_child(body, 0, XML_NS_EVENTING, WSEVENT_RENEW); |
| inNode = ws_xml_get_child(inNode, 0, XML_NS_EVENTING ,WSEVENT_EXPIRES); |
| pthread_mutex_lock(&subsInfo->notificationlock); |
| wsman_set_expiretime(inNode, &subsInfo->expires, &status.fault_code); |
| expirestr = ws_xml_get_node_text(inNode); |
| pthread_mutex_unlock(&subsInfo->notificationlock); |
| if (status.fault_code != WSMAN_RC_OK) { |
| status.fault_detail_code = WSMAN_DETAIL_EXPIRATION_TIME; |
| pthread_mutex_unlock(&subsInfo->notificationlock); |
| goto DONE; |
| } |
| char str[30]; |
| wsman_expiretime2xmldatetime(subsInfo->expires, str); |
| if(soap->subscriptionOpSet) { |
| soap->subscriptionOpSet->update_subscription(soap->uri_subsRepository, uuid+5, |
| str); |
| debug("subscription %s updated!", uuid); |
| } |
| |
| if (endPoint && (retVal = endPoint(epcntx, subsInfo, &status, opaqueData))) { |
| debug("renew fault in plug-in"); |
| doc = wsman_generate_fault( _doc, status.fault_code, status.fault_detail_code, status.fault_msg); |
| pthread_mutex_unlock(&subsInfo->notificationlock); |
| goto DONE; |
| } |
| doc = wsman_create_response_envelope( _doc, NULL); |
| if (!doc) |
| goto DONE; |
| body = ws_xml_get_soap_body(doc); |
| body = ws_xml_add_child(body, XML_NS_EVENTING, WSEVENT_RENEW_RESP, NULL); |
| ws_xml_add_child(body, XML_NS_EVENTING, WSEVENT_EXPIRES, expirestr); |
| DONE: |
| if (doc) { |
| soap_set_op_doc(op, doc, 0); |
| } |
| ws_serializer_free_all(epcntx->serializercntx); |
| ws_destroy_context(epcntx); |
| u_free(status.fault_msg); |
| return retVal; |
| } |
| |
| |
| void |
| wsman_heartbeat_generator(WsContextH cntx, void *opaqueData) |
| { |
| SoapH soap = cntx->soap; |
| WsSubscribeInfo *subsInfo = NULL; |
| WsEventThreadContextH threadcntx = NULL; |
| WsContextH soapCntx = ws_get_soap_context(soap); |
| pthread_t eventsender; |
| pthread_attr_t pattrs; |
| int r; |
| if ((r = pthread_attr_init(&pattrs)) != 0) { |
| debug("pthread_attr_init failed = %d", r); |
| return; |
| } |
| if ((r = pthread_attr_setdetachstate(&pattrs, |
| PTHREAD_CREATE_DETACHED)) !=0) { |
| debug("pthread_attr_setdetachstate = %d", r); |
| return; |
| } |
| pthread_mutex_lock(&soap->lockSubs); |
| lnode_t *node = list_first(soapCntx->subscriptionMemList); |
| while(node) { |
| subsInfo = (WsSubscribeInfo *)node->list_data; |
| pthread_mutex_lock(&subsInfo->notificationlock); |
| #if 0 |
| debug("subscription %s : event sent last time = %d, heartbeat= %ld, heartbeatcountdown = %ld, pending events = %d", |
| subsInfo->subsId, subsInfo->eventSentLastTime, subsInfo->heartbeatInterval, subsInfo->heartbeatCountdown, subsInfo->flags & WSMAN_SUBSCRIPTION_NOTIFICAITON_PENDING); |
| #endif |
| if(subsInfo->flags & WSMAN_SUBSCRIBEINFO_UNSUBSCRIBE) { |
| goto LOOP; |
| } |
| if(time_expired(subsInfo->expires)) { |
| |
| goto LOOP; |
| |
| } |
| if(subsInfo->heartbeatInterval == 0 || subsInfo->deliveryMode == WS_EVENT_DELIVERY_MODE_PULL) { |
| goto LOOP; |
| } |
| subsInfo->heartbeatCountdown -= 1000; |
| if(subsInfo->heartbeatCountdown > 0) { |
| goto LOOP; |
| } |
| if(subsInfo->eventSentLastTime) { |
| subsInfo->eventSentLastTime = 0; |
| } |
| else { |
| debug("one heartbeat document created for %s", subsInfo->subsId); |
| if((subsInfo->flags & WSMAN_SUBSCRIPTION_NOTIFICAITON_PENDING) == 0) { |
| threadcntx = ws_create_event_context(soap, subsInfo, NULL); |
| if(pthread_create(&eventsender, &pattrs, wse_heartbeat_sender, threadcntx) == 0) |
| subsInfo->flags |= WSMAN_SUBSCRIPTION_NOTIFICAITON_PENDING; |
| } |
| } |
| subsInfo->heartbeatCountdown = subsInfo->heartbeatInterval; |
| LOOP: |
| pthread_mutex_unlock(&subsInfo->notificationlock); |
| node = list_next(soapCntx->subscriptionMemList, node); |
| } |
| pthread_mutex_unlock(&soap->lockSubs); |
| } |
| |
| static int wse_send_notification(WsEventThreadContextH cntx, WsXmlDocH outdoc, WsSubscribeInfo *subsInfo, unsigned char acked) |
| { |
| int retVal = 0; |
| WsManClient *notificationSender = wsmc_create_from_uri(subsInfo->epr_notifyto); |
| if(subsInfo->contentEncoding) |
| wsmc_set_encoding(notificationSender, subsInfo->contentEncoding); |
| if(subsInfo->username) |
| wsman_transport_set_userName(notificationSender, subsInfo->username); |
| if(subsInfo->password) |
| wsman_transport_set_password(notificationSender, subsInfo->password); |
| if(subsInfo->deliveryAuthType == |
| WSMAN_SECURITY_PROFILE_HTTP_BASIC_TYPE) { |
| } |
| else if(subsInfo->deliveryAuthType == |
| WSMAN_SECURITY_PROFILE_HTTP_DIGEST_TYPE) { |
| } |
| else if(subsInfo->deliveryAuthType == |
| WSMAN_SECURITY_PROFILE_HTTPS_BASIC_TYPE) { |
| wsman_transport_set_verify_peer(notificationSender, 0); |
| } |
| else if(subsInfo->deliveryAuthType == |
| WSMAN_SECURITY_PROFILE_HTTPS_DIGEST_TYPE) { |
| wsman_transport_set_verify_peer(notificationSender, 0); |
| } |
| else if(subsInfo->deliveryAuthType == |
| WSMAN_SECURITY_PROFILE_HTTPS_MUTUAL_TYPE) { |
| wsman_transport_set_verify_peer(notificationSender, 1); |
| wsman_transport_set_certhumbprint(notificationSender, subsInfo->certificate_thumbprint); |
| } |
| else if(subsInfo->deliveryAuthType == |
| WSMAN_SECURITY_PROFILE_HTTPS_MUTUAL_BASIC_TYPE) { |
| wsman_transport_set_verify_peer(notificationSender, 1); |
| wsman_transport_set_certhumbprint(notificationSender, subsInfo->certificate_thumbprint); |
| } |
| else if(subsInfo->deliveryAuthType == |
| WSMAN_SECURITY_PROFILE_HTTPS_MUTUAL_DIGEST_TYPE) { |
| wsman_transport_set_verify_peer(notificationSender, 1); |
| wsman_transport_set_certhumbprint(notificationSender, subsInfo->certificate_thumbprint); |
| } |
| else if(subsInfo->deliveryAuthType == |
| WSMAN_SECURITY_PROFILE_HTTPS_SPNEGO_KERBEROS_TYPE) { |
| } |
| else if(subsInfo->deliveryAuthType == |
| WSMAN_SECURITY_PROFILE_HTTPS_MUTUAL_SPNEGO_KERBEROS_TYPE) { |
| } |
| else { //WSMAN_SECURITY_PROFILE_HTTP_SPNEGO_KERBEROS_TYPE |
| } |
| wsmc_transport_init(notificationSender, NULL); |
| if (wsman_send_request(notificationSender, outdoc)) { |
| warning("wse_send_notification: wsman_send_request fails for endpoint %s", subsInfo->epr_notifyto); |
| /* FIXME: retVal */ |
| } |
| if(acked) { |
| retVal = WSE_NOTIFICATION_NOACK; |
| WsXmlDocH ackdoc = wsmc_build_envelope_from_response(notificationSender); |
| if(ackdoc) { |
| WsXmlNodeH node = ws_xml_get_soap_header(ackdoc); |
| WsXmlNodeH srcnode = ws_xml_get_soap_header(outdoc); |
| WsXmlNodeH temp = NULL; |
| srcnode = ws_xml_get_child(srcnode, 0, XML_NS_ADDRESSING, WSA_MESSAGE_ID); |
| if(node) { |
| temp = ws_xml_get_child(node, 0, XML_NS_ADDRESSING, WSA_RELATES_TO); |
| if(temp) { |
| if(!strcasecmp(ws_xml_get_node_text(srcnode), |
| ws_xml_get_node_text(temp))) { |
| node = ws_xml_get_child(node, 0, XML_NS_ADDRESSING, WSA_ACTION); |
| if(!strcasecmp(ws_xml_get_node_text(node), WSMAN_ACTION_ACK)) |
| retVal = 0; |
| } |
| |
| } |
| } |
| ws_xml_destroy_doc(ackdoc); |
| } |
| } |
| wsmc_release(notificationSender); |
| return retVal; |
| } |
| |
| |
| static void * wse_event_sender(void * thrdcntx, unsigned char flag) |
| { |
| char uuidBuf[50]; |
| WsXmlNodeH header; |
| if(thrdcntx == NULL) return NULL; |
| WsEventThreadContextH threadcntx = (WsEventThreadContextH)thrdcntx; |
| WsSubscribeInfo * subsInfo = threadcntx->subsInfo; |
| if(flag == 1) |
| debug("wse_notification_sender for %s started", subsInfo->subsId); |
| else |
| debug("wse_heartbeat_sender for %s started", subsInfo->subsId); |
| WsXmlDocH notificationDoc = NULL; |
| pthread_mutex_lock(&subsInfo->notificationlock); |
| if(flag == 1) |
| subsInfo->eventSentLastTime = 1; |
| if(!(subsInfo->flags & WSMAN_SUBSCRIBEINFO_UNSUBSCRIBE) && |
| !time_expired(subsInfo->expires)) { |
| if(flag) { |
| notificationDoc = threadcntx->outdoc; |
| } |
| else { |
| notificationDoc = ws_xml_duplicate_doc(subsInfo->heartbeatDoc); |
| header = ws_xml_get_soap_header(notificationDoc); |
| generate_uuid(uuidBuf, sizeof(uuidBuf), 0); |
| ws_xml_add_child(header, XML_NS_ADDRESSING, WSA_MESSAGE_ID,uuidBuf); |
| } |
| if (subsInfo->deliveryMode == WS_EVENT_DELIVERY_MODE_EVENTS || |
| subsInfo->deliveryMode == WS_EVENT_DELIVERY_MODE_PUSHWITHACK){ |
| if(wse_send_notification(threadcntx, notificationDoc, subsInfo, 1) == WSE_NOTIFICATION_NOACK) |
| subsInfo->flags |= WSMAN_SUBSCRIPTION_CANCELLED; |
| } |
| else |
| wse_send_notification(threadcntx, notificationDoc, subsInfo, 0); |
| } |
| ws_xml_destroy_doc(notificationDoc); |
| subsInfo->flags &= ~WSMAN_SUBSCRIPTION_NOTIFICAITON_PENDING; |
| debug("[ wse_notification_sender thread for %s quit! ]",subsInfo->subsId); |
| pthread_mutex_unlock(&subsInfo->notificationlock); |
| u_free(thrdcntx); |
| return NULL; |
| } |
| |
| void * wse_heartbeat_sender(void *thrdcntx) |
| { |
| return wse_event_sender(thrdcntx, 0); |
| } |
| |
| void *wse_notification_sender(void *thrdcntx) |
| { |
| return wse_event_sender(thrdcntx, 1); |
| } |
| |
| void wse_notification_manager(void * cntx) |
| { |
| int retVal; |
| WsSubscribeInfo * subsInfo = NULL; |
| WsXmlDocH notificationDoc =NULL; |
| WsXmlNodeH header = NULL; |
| WsXmlNodeH body = NULL; |
| WsXmlNodeH node = NULL; |
| WsXmlNodeH eventnode = NULL; |
| WsXmlNodeH temp = NULL; |
| lnode_t *subsnode = NULL; |
| WsEventThreadContextH threadcntx = NULL; |
| WsContextH contex = (WsContextH)cntx; |
| SoapH soap = contex->soap; |
| WsContextH soapCntx = ws_get_soap_context(soap); |
| pthread_t eventsender; |
| pthread_attr_t pattrs; |
| char uuidBuf[50]; |
| int r; |
| if ((r = pthread_attr_init(&pattrs)) != 0) { |
| debug("pthread_attr_init failed = %d", r); |
| return; |
| } |
| if ((r = pthread_attr_setdetachstate(&pattrs, |
| PTHREAD_CREATE_DETACHED)) !=0) { |
| debug("pthread_attr_setdetachstate = %d", r); |
| return; |
| } |
| pthread_mutex_lock(&soap->lockSubs); |
| subsnode = list_first(soapCntx->subscriptionMemList); |
| while(subsnode) { |
| subsInfo = (WsSubscribeInfo *)subsnode->list_data; |
| pthread_mutex_lock(&subsInfo->notificationlock); |
| threadcntx = ws_create_event_context(soap, subsInfo, NULL); |
| if(((subsInfo->flags & WSMAN_SUBSCRIBEINFO_UNSUBSCRIBE) || |
| subsInfo->flags & WSMAN_SUBSCRIPTION_CANCELLED || |
| time_expired(subsInfo->expires)) && |
| ((subsInfo->flags & WSMAN_SUBSCRIPTION_NOTIFICAITON_PENDING ) == 0)) { |
| lnode_t *nodetemp = list_delete2(soapCntx->subscriptionMemList, subsnode); |
| soap->subscriptionOpSet->delete_subscription(soap->uri_subsRepository, subsInfo->subsId); |
| soap->eventpoolOpSet->clear(subsInfo->subsId, delete_notification_info); |
| if(!(subsInfo->flags & WSMAN_SUBSCRIBEINFO_UNSUBSCRIBE) && subsInfo->cancel) |
| subsInfo->cancel(threadcntx); |
| if(subsInfo->flags & WSMAN_SUBSCRIBEINFO_UNSUBSCRIBE) |
| debug("Unsubscribed!uuid:%s deleted", subsInfo->subsId); |
| else if(subsInfo->flags & WSMAN_SUBSCRIPTION_CANCELLED) |
| debug("Cancelled! uuid:%s deleted", subsInfo->subsId); |
| else |
| debug("Expired! uuid:%s deleted", subsInfo->subsId); |
| destroy_subsinfo(subsInfo); |
| lnode_destroy(subsnode); |
| u_free(threadcntx); |
| subsnode = nodetemp; |
| continue; |
| } |
| if(subsInfo->eventpoll) { //poll the events |
| retVal = subsInfo->eventpoll(threadcntx); |
| if(retVal == WSE_NOTIFICATION_EVENTS_PENDING) { |
| goto LOOP; |
| } |
| } |
| if(subsInfo->deliveryMode == WS_EVENT_DELIVERY_MODE_PULL) |
| goto LOOP; |
| WsNotificationInfoH notificationInfo = NULL; |
| if(soap->eventpoolOpSet->remove(subsInfo->subsId, ¬ificationInfo) ) // to get the event and delete it from the event source |
| goto LOOP; |
| if(subsInfo->deliveryMode == WS_EVENT_DELIVERY_MODE_PULL) goto LOOP; |
| notificationDoc = ws_xml_duplicate_doc(subsInfo->templateDoc); |
| header = ws_xml_get_soap_header(notificationDoc); |
| body = ws_xml_get_soap_body(notificationDoc); |
| if(notificationInfo->headerOpaqueData) { |
| temp = ws_xml_get_doc_root(notificationInfo->headerOpaqueData); |
| ws_xml_duplicate_tree(header, temp); |
| } |
| if(subsInfo->deliveryMode == WS_EVENT_DELIVERY_MODE_EVENTS) { |
| ws_xml_add_child(header, XML_NS_ADDRESSING, WSA_ACTION, WSEVENT_DELIVERY_MODE_EVENTS); |
| generate_uuid(uuidBuf, sizeof(uuidBuf), 0); |
| ws_xml_add_child(header, XML_NS_ADDRESSING, WSA_MESSAGE_ID,uuidBuf); |
| eventnode = ws_xml_add_child(body, XML_NS_WS_MAN, WSM_EVENTS, NULL); |
| while(notificationInfo) { |
| temp = ws_xml_add_child(eventnode, XML_NS_WS_MAN, WSM_EVENT, NULL); |
| if(notificationInfo->EventAction) { |
| ws_xml_add_node_attr(temp, XML_NS_WS_MAN, WSM_ACTION, notificationInfo->EventAction); |
| } |
| else { |
| ws_xml_add_node_attr(temp, XML_NS_WS_MAN, WSM_ACTION, WSMAN_ACTION_EVENT); |
| } |
| if(temp) { |
| node = ws_xml_get_doc_root(notificationInfo->EventContent); |
| ws_xml_duplicate_children(temp, node); |
| } |
| delete_notification_info(notificationInfo); |
| soap->eventpoolOpSet->remove(subsInfo->subsId, ¬ificationInfo); |
| } |
| } |
| else{ |
| generate_uuid(uuidBuf, sizeof(uuidBuf), 0); |
| ws_xml_add_child(header, XML_NS_ADDRESSING, WSA_MESSAGE_ID,uuidBuf); |
| if(notificationInfo->EventAction) |
| ws_xml_add_child(header, XML_NS_WS_MAN, WSM_ACTION, notificationInfo->EventAction); |
| else |
| ws_xml_add_child(header, XML_NS_WS_MAN, WSM_ACTION, WSMAN_ACTION_EVENT); |
| node = ws_xml_get_doc_root(notificationInfo->EventContent); |
| ws_xml_duplicate_children(body, node); |
| delete_notification_info(notificationInfo); |
| } |
| if(subsInfo->deliveryMode != WS_EVENT_DELIVERY_MODE_PULL) { |
| if((subsInfo->flags & WSMAN_SUBSCRIPTION_NOTIFICAITON_PENDING) == 0) { |
| WsEventThreadContextH threadcntx2 = ws_create_event_context(soap, subsInfo, notificationDoc); |
| if(pthread_create(&eventsender, &pattrs, wse_notification_sender, threadcntx2) == 0) { |
| subsInfo->flags |= WSMAN_SUBSCRIPTION_NOTIFICAITON_PENDING; |
| } |
| else { |
| debug("thread created for %s failed![ %s ]", subsInfo->subsId, strerror(errno)); |
| } |
| } |
| } |
| |
| LOOP: |
| if(threadcntx) |
| u_free(threadcntx); |
| pthread_mutex_unlock(&subsInfo->notificationlock); |
| subsnode = list_next(soapCntx->subscriptionMemList, subsnode); |
| } |
| pthread_mutex_unlock(&soap->lockSubs); |
| } |
| |
| |
| |
| #endif |
| |
| |
| WsContextH |
| ws_get_soap_context(SoapH soap) |
| { |
| return soap->cntx; |
| } |
| |
| |
| int |
| ws_remove_context_val(WsContextH cntx, char *name) |
| { |
| int retVal = 1; |
| if (cntx && name) { |
| hnode_t *hn; |
| u_lock(cntx->soap); |
| hn = hash_lookup(cntx->entries, name); |
| if (hn) { |
| debug("Found context entry: %s", name); |
| hash_delete_free(cntx->entries, hn); |
| retVal = 0; |
| } |
| u_unlock(cntx->soap); |
| } |
| return retVal; |
| } |
| |
| int |
| ws_set_context_ulong_val(WsContextH cntx, |
| char *name, |
| unsigned long val) |
| { |
| int retVal = set_context_val(cntx, name, &val, sizeof(unsigned long), |
| 0, WS_CONTEXT_TYPE_ULONG); |
| return retVal; |
| } |
| |
| |
| int |
| ws_set_context_xml_doc_val(WsContextH cntx, |
| char *name, |
| WsXmlDocH val) |
| { |
| cntx->indoc = val; |
| return 0; |
| } |
| |
| WsContextH |
| ws_create_ep_context(SoapH soap, |
| WsXmlDocH doc) |
| { |
| WsContextH cntx = ws_create_context(soap); |
| if (cntx) |
| ws_set_context_xml_doc_val(cntx, WSFW_INDOC, doc); |
| return cntx; |
| } |
| |
| |
| int |
| ws_destroy_context(WsContextH cntx) |
| { |
| int retVal = 1; |
| if (cntx && cntx->owner) { |
| ws_clear_context_entries(cntx); |
| ws_clear_context_enuminfos(cntx); |
| ws_serializer_cleanup(cntx->serializercntx); |
| if(cntx->subscriptionMemList) { |
| list_destroy_nodes(cntx->subscriptionMemList); |
| list_destroy(cntx->subscriptionMemList); |
| } |
| u_free(cntx); |
| retVal = 0; |
| } |
| return retVal; |
| } |
| |
| |
| hnode_t* |
| create_context_entry(hash_t * h, |
| char *name, |
| void *val) |
| { |
| char *key = u_strdup(name); |
| hnode_t *hn = hnode_create(val); |
| hash_insert(h, hn, (void *) key); |
| return hn; |
| } |
| |
| SoapH |
| ws_context_get_runtime(WsContextH cntx) |
| { |
| SoapH soap = NULL; |
| if (cntx) |
| soap = cntx->soap; |
| return soap; |
| } |
| |
| |
| const void * |
| get_context_val(WsContextH cntx, const char *name) |
| { |
| const char *val = NULL; |
| if (cntx && name) { |
| u_lock(cntx->soap); |
| if (cntx->entries) { |
| hnode_t *hn = hash_lookup(cntx->entries, name); |
| if (hn) |
| val = hnode_get(hn); |
| } |
| u_unlock(cntx->soap); |
| } |
| return val; |
| } |
| |
| |
| const void * |
| ws_get_context_val(WsContextH cntx, const char *name, int *size) |
| { |
| return get_context_val(cntx, name); |
| } |
| |
| |
| unsigned long |
| ws_get_context_ulong_val(WsContextH cntx, char *name) |
| { |
| const void *ptr = get_context_val(cntx, name); |
| if (ptr != NULL) |
| return *((unsigned long *) ptr); |
| return 0; |
| } |
| |
| |
| SoapOpH |
| soap_create_op(SoapH soap, |
| char *inboundAction, |
| char *outboundAction, //optional |
| char *role, |
| SoapServiceCallback callbackProc, |
| void *callbackData, |
| unsigned long flags) |
| { |
| SoapDispatchH disp = NULL; |
| op_t *entry = NULL; |
| |
| if ((disp = wsman_dispatch_create(soap, inboundAction, outboundAction, |
| NULL, //reserved, must be NULL |
| callbackProc, callbackData, flags)) != NULL) { |
| entry = create_op_entry(soap, disp, NULL); |
| } |
| return (SoapOpH) entry; |
| } |
| |
| |
| |
| /** |
| * Get Operation Document |
| * @param op Operation Handle |
| * @param inbound Direction flag |
| * @return XML Document |
| */ |
| WsXmlDocH |
| soap_get_op_doc(SoapOpH op, |
| int inbound) |
| { |
| WsXmlDocH doc = NULL; |
| if (op) { |
| op_t *e = (op_t *) op; |
| doc = (!inbound) ? e->out_doc : e->in_doc; |
| } |
| return doc; |
| } |
| |
| WsXmlDocH |
| soap_detach_op_doc(SoapOpH op, |
| int inbound) |
| { |
| WsXmlDocH doc = NULL; |
| if (op) { |
| op_t *e = (op_t *) op; |
| if (!inbound) { |
| doc = e->out_doc; |
| e->out_doc = NULL; |
| } else { |
| doc = e->in_doc; |
| e->in_doc = NULL; |
| } |
| } |
| return doc; |
| } |
| |
| int |
| soap_set_op_doc(SoapOpH op, |
| WsXmlDocH doc, |
| int inbound) |
| { |
| int retVal = 1; |
| if (op) { |
| op_t *e = (op_t *) op; |
| if (!inbound) |
| e->out_doc = doc; |
| else |
| e->in_doc = doc; |
| retVal = 0; |
| } |
| return retVal; |
| } |
| |
| |
| SoapH |
| soap_get_op_soap(SoapOpH op) |
| { |
| if (op) |
| return (SoapH) ((op_t *) op)->dispatch->soap; |
| |
| return NULL; |
| } |
| |
| void |
| soap_destroy_op(SoapOpH op) |
| { |
| destroy_op_entry((op_t *) op); |
| } |
| |
| |
| op_t * |
| create_op_entry(SoapH soap, |
| SoapDispatchH dispatch, |
| WsmanMessage * data) |
| { |
| op_t *entry = (op_t *) u_zalloc(sizeof(op_t)); |
| if (entry) { |
| entry->dispatch = dispatch; |
| entry->cntx = ws_create_context(soap); |
| entry->data = data; |
| // entry->processed_headers = list_create(LISTCOUNT_T_MAX); |
| } |
| return entry; |
| } |
| |
| |
| void |
| destroy_op_entry(op_t * entry) |
| { |
| SoapH soap; |
| debug("destroy op"); |
| if (!entry) { |
| debug("nothing to destroy..."); |
| return; |
| } |
| soap = entry->dispatch->soap; |
| if (soap == NULL) { |
| goto NULL_SOAP; |
| } |
| u_lock(soap); |
| if (soap->dispatchList && list_contains(soap->dispatchList, &entry->dispatch->node)) { |
| list_delete(soap->dispatchList, &entry->dispatch->node); |
| } |
| u_unlock(soap); |
| |
| NULL_SOAP: |
| destroy_dispatch_entry(entry->dispatch); |
| ws_destroy_context(entry->cntx); |
| #if 0 |
| list_destroy_nodes(entry->processed_headers); |
| list_destroy(entry->processed_headers); |
| #endif |
| u_free(entry); |
| } |
| |
| void |
| destroy_dispatch_entry(SoapDispatchH entry) |
| { |
| int usageCount; |
| list_t *dlist; |
| if (!entry) { |
| return; |
| } |
| |
| u_lock(entry->soap); |
| entry->usageCount--; |
| usageCount = entry->usageCount; |
| dlist = entry->soap->dispatchList; |
| if (!usageCount && dlist != NULL && |
| list_contains(dlist, &entry->node)) { |
| lnode_t *n = list_delete(dlist, &entry->node); |
| lnode_destroy(n); |
| } |
| u_unlock(entry->soap); |
| |
| if (!usageCount) { |
| if (entry->inboundFilterList) { |
| list_destroy_nodes(entry->inboundFilterList); |
| list_destroy(entry->inboundFilterList); |
| } |
| if (entry->outboundFilterList) { |
| list_destroy_nodes(entry->outboundFilterList); |
| list_destroy(entry->outboundFilterList); |
| } |
| |
| u_free(entry->inboundAction); |
| u_free(entry->outboundAction); |
| |
| u_free(entry); |
| } |
| } |
| |
| |
| void |
| soap_destroy(SoapH soap) |
| { |
| if (soap == NULL ) |
| return; |
| |
| if (soap->dispatcherProc) |
| soap->dispatcherProc(soap->cntx, soap->dispatcherData, NULL); |
| |
| if (soap->dispatchList) { |
| while (!list_isempty(soap->dispatchList)) { |
| destroy_dispatch_entry( |
| (SoapDispatchH)list_first(soap->dispatchList)); |
| } |
| list_destroy(soap->dispatchList); |
| } |
| |
| if (soap->processedMsgIdList) { |
| while (!list_isempty(soap->processedMsgIdList)) { |
| lnode_t *node = list_del_first(soap->processedMsgIdList); |
| u_free(node->list_data); |
| lnode_destroy(node); |
| } |
| list_destroy(soap->processedMsgIdList); |
| } |
| |
| |
| if (soap->inboundFilterList) { |
| list_destroy_nodes(soap->inboundFilterList); |
| list_destroy(soap->inboundFilterList); |
| } |
| |
| if (soap->outboundFilterList) { |
| list_destroy_nodes(soap->outboundFilterList); |
| list_destroy(soap->outboundFilterList); |
| } |
| ws_xml_parser_destroy(); |
| |
| ws_destroy_context(soap->cntx); |
| u_free(soap); |
| |
| return; |
| } |
| |
| |
| void |
| wsman_status_init(WsmanStatus * status) |
| { |
| status->fault_code = 0; |
| status->fault_detail_code = 0; |
| status->fault_msg = NULL; |
| } |
| |
| int |
| wsman_check_status(WsmanStatus * status) |
| { |
| return status->fault_code; |
| } |