http://git-wip-us.apache.org/repos/asf/celix/blob/2a670f26/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_dfi.c ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_dfi.c b/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_dfi.c new file mode 100644 index 0000000..9feab9f --- /dev/null +++ b/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_dfi.c @@ -0,0 +1,775 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * remote_service_admin_impl.c + * + * \date May 21, 2015 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ +#include <stdio.h> +#include <stdlib.h> + +#include <arpa/inet.h> +#include <netdb.h> +#include <ifaddrs.h> +#include <string.h> +#include <uuid/uuid.h> +#include <curl/curl.h> + +#include <jansson.h> +#include "json_serializer.h" +#include "remote_service_admin.h" +#include "celix_threads.h" +#include "hash_map.h" +#include "array_list.h" + +#include "import_registration_dfi.h" +#include "export_registration_dfi.h" +#include "remote_service_admin_dfi.h" +#include "dyn_interface.h" +#include "json_rpc.h" + +#include "remote_constants.h" +#include "constants.h" +#include "civetweb.h" + +// defines how often the webserver is restarted (with an increased port number) +#define MAX_NUMBER_OF_RESTARTS 5 + + +#define RSA_LOG_ERROR(admin, msg, ...) \ + logHelper_log((admin)->loghelper, OSGI_LOGSERVICE_ERROR, (msg), ##__VA_ARGS__) + +#define RSA_LOG_WARNING(admin, msg, ...) \ + logHelper_log((admin)->loghelper, OSGI_LOGSERVICE_ERROR, (msg), ##__VA_ARGS__) + +#define RSA_LOG_DEBUG(admin, msg, ...) \ + logHelper_log((admin)->loghelper, OSGI_LOGSERVICE_ERROR, (msg), ##__VA_ARGS__) + +struct remote_service_admin { + bundle_context_pt context; + log_helper_pt loghelper; + + celix_thread_mutex_t exportedServicesLock; + hash_map_pt exportedServices; + + celix_thread_mutex_t importedServicesLock; + array_list_pt importedServices; + + char *port; + char *ip; + + struct mg_context *ctx; +}; + +struct post { + const char *readptr; + int size; +}; + +struct get { + char *writeptr; + int size; +}; + +#define OSGI_RSA_REMOTE_PROXY_FACTORY "remote_proxy_factory" +#define OSGI_RSA_REMOTE_PROXY_TIMEOUT "remote_proxy_timeout" + +static const char *data_response_headers = + "HTTP/1.1 200 OK\r\n" + "Cache: no-cache\r\n" + "Content-Type: application/json\r\n" + "\r\n"; + +static const char *no_content_response_headers = + "HTTP/1.1 204 OK\r\n"; + +// TODO do we need to specify a non-Amdatu specific configuration type?! +static const char * const CONFIGURATION_TYPE = "org.amdatu.remote.admin.http"; +static const char * const ENDPOINT_URL = "org.amdatu.remote.admin.http.url"; + +static const char *DEFAULT_PORT = "8888"; +static const char *DEFAULT_IP = "127.0.0.1"; + +static const unsigned int DEFAULT_TIMEOUT = 0; + +static int remoteServiceAdmin_callback(struct mg_connection *conn); +static celix_status_t remoteServiceAdmin_createEndpointDescription(remote_service_admin_pt admin, service_reference_pt reference, properties_pt props, char *interface, endpoint_description_pt *description); +static celix_status_t remoteServiceAdmin_send(void *handle, endpoint_description_pt endpointDescription, char *request, char **reply, int* replyStatus); +static celix_status_t remoteServiceAdmin_getIpAdress(char* interface, char** ip); +static size_t remoteServiceAdmin_readCallback(void *ptr, size_t size, size_t nmemb, void *userp); +static size_t remoteServiceAdmin_write(void *contents, size_t size, size_t nmemb, void *userp); +static void remoteServiceAdmin_log(remote_service_admin_pt admin, int level, const char *file, int line, const char *msg, ...); + +celix_status_t remoteServiceAdmin_create(bundle_context_pt context, remote_service_admin_pt *admin) { + celix_status_t status = CELIX_SUCCESS; + + *admin = calloc(1, sizeof(**admin)); + + if (!*admin) { + status = CELIX_ENOMEM; + } else { + unsigned int port_counter = 0; + const char *port = NULL; + const char *ip = NULL; + char *detectedIp = NULL; + (*admin)->context = context; + (*admin)->exportedServices = hashMap_create(NULL, NULL, NULL, NULL); + arrayList_create(&(*admin)->importedServices); + + celixThreadMutex_create(&(*admin)->exportedServicesLock, NULL); + celixThreadMutex_create(&(*admin)->importedServicesLock, NULL); + + if (logHelper_create(context, &(*admin)->loghelper) == CELIX_SUCCESS) { + logHelper_start((*admin)->loghelper); + dynCommon_logSetup((void *)remoteServiceAdmin_log, *admin, 1); + dynType_logSetup((void *)remoteServiceAdmin_log, *admin, 1); + dynFunction_logSetup((void *)remoteServiceAdmin_log, *admin, 1); + dynInterface_logSetup((void *)remoteServiceAdmin_log, *admin, 1); + jsonSerializer_logSetup((void *)remoteServiceAdmin_log, *admin, 1); + jsonRpc_logSetup((void *)remoteServiceAdmin_log, *admin, 1); + } + + bundleContext_getProperty(context, "RSA_PORT", &port); + if (port == NULL) { + port = (char *)DEFAULT_PORT; + } + + bundleContext_getProperty(context, "RSA_IP", &ip); + if (ip == NULL) { + const char *interface = NULL; + + bundleContext_getProperty(context, "RSA_INTERFACE", &interface); + if ((interface != NULL) && (remoteServiceAdmin_getIpAdress((char*)interface, &detectedIp) != CELIX_SUCCESS)) { + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "RSA: Could not retrieve IP adress for interface %s", interface); + } + + if (ip == NULL) { + remoteServiceAdmin_getIpAdress(NULL, &detectedIp); + } + + ip = detectedIp; + } + + if (ip != NULL) { + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Using %s for service annunciation", ip); + (*admin)->ip = strdup(ip); + } + else { + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "RSA: No IP address for service annunciation set. Using %s", DEFAULT_IP); + (*admin)->ip = strdup((char*) DEFAULT_IP); + } + + if (detectedIp != NULL) { + free(detectedIp); + } + + // Prepare callbacks structure. We have only one callback, the rest are NULL. + struct mg_callbacks callbacks; + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.begin_request = remoteServiceAdmin_callback; + + char newPort[10]; + + do { + + const char *options[] = { "listening_ports", port, "num_threads", "5", NULL}; + + (*admin)->ctx = mg_start(&callbacks, (*admin), options); + + if ((*admin)->ctx != NULL) { + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Start webserver: %s", port); + (*admin)->port = strdup(port); + + } + else { + errno = 0; + char* endptr = (char*)port; + int currentPort = strtol(port, &endptr, 10); + + if (*endptr || errno != 0) { + currentPort = strtol(DEFAULT_PORT, NULL, 10); + } + + port_counter++; + snprintf(&newPort[0], 6, "%d", (currentPort+1)); + + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_ERROR, "Error while starting rsa server on port %s - retrying on port %s...", port, newPort); + port = newPort; + } + } while(((*admin)->ctx == NULL) && (port_counter < MAX_NUMBER_OF_RESTARTS)); + + } + + return status; +} + + +celix_status_t remoteServiceAdmin_destroy(remote_service_admin_pt *admin) +{ + celix_status_t status = CELIX_SUCCESS; + + free((*admin)->ip); + free((*admin)->port); + free(*admin); + + //TODO destroy exports/imports + + *admin = NULL; + + return status; +} + + +celix_status_t remoteServiceAdmin_stop(remote_service_admin_pt admin) { + celix_status_t status = CELIX_SUCCESS; + + celixThreadMutex_lock(&admin->exportedServicesLock); + + hash_map_iterator_pt iter = hashMapIterator_create(admin->exportedServices); + while (hashMapIterator_hasNext(iter)) { + array_list_pt exports = hashMapIterator_nextValue(iter); + int i; + for (i = 0; i < arrayList_size(exports); i++) { + export_registration_pt export = arrayList_get(exports, i); + if (export != NULL) { + exportRegistration_stop(export); + exportRegistration_destroy(export); + } + } + arrayList_destroy(exports); + } + hashMapIterator_destroy(iter); + celixThreadMutex_unlock(&admin->exportedServicesLock); + + celixThreadMutex_lock(&admin->importedServicesLock); + int i; + int size = arrayList_size(admin->importedServices); + for (i = 0; i < size ; i += 1) { + import_registration_pt import = arrayList_get(admin->importedServices, i); + if (import != NULL) { + importRegistration_stop(import); + importRegistration_destroy(import); + } + } + celixThreadMutex_unlock(&admin->importedServicesLock); + + if (admin->ctx != NULL) { + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Stopping webserver..."); + mg_stop(admin->ctx); + admin->ctx = NULL; + } + + hashMap_destroy(admin->exportedServices, false, false); + arrayList_destroy(admin->importedServices); + + logHelper_stop(admin->loghelper); + logHelper_destroy(&admin->loghelper); + + return status; +} + +/** + * Request: http://host:port/services/{service}/{request} + */ +//void *remoteServiceAdmin_callback(enum mg_event event, struct mg_connection *conn, const struct mg_request_info *request_info) { + +celix_status_t importRegistration_getFactory(import_registration_pt import, service_factory_pt *factory); + +static int remoteServiceAdmin_callback(struct mg_connection *conn) { + int result = 1; // zero means: let civetweb handle it further, any non-zero value means it is handled by us... + + const struct mg_request_info *request_info = mg_get_request_info(conn); + if (request_info->uri != NULL) { + remote_service_admin_pt rsa = request_info->user_data; + + + if (strncmp(request_info->uri, "/service/", 9) == 0 && strcmp("POST", request_info->request_method) == 0) { + + // uri = /services/myservice/call + const char *uri = request_info->uri; + // rest = myservice/call + + const char *rest = uri+9; + char *interfaceStart = strchr(rest, '/'); + int pos = interfaceStart - rest; + char service[pos+1]; + strncpy(service, rest, pos); + service[pos] = '\0'; + unsigned long serviceId = strtoul(service,NULL,10); + + celixThreadMutex_lock(&rsa->exportedServicesLock); + + //find endpoint + export_registration_pt export = NULL; + hash_map_iterator_pt iter = hashMapIterator_create(rsa->exportedServices); + while (hashMapIterator_hasNext(iter)) { + hash_map_entry_pt entry = hashMapIterator_nextEntry(iter); + array_list_pt exports = hashMapEntry_getValue(entry); + int expIt = 0; + for (expIt = 0; expIt < arrayList_size(exports); expIt++) { + export_registration_pt check = arrayList_get(exports, expIt); + export_reference_pt ref = NULL; + exportRegistration_getExportReference(check, &ref); + endpoint_description_pt checkEndpoint = NULL; + exportReference_getExportedEndpoint(ref, &checkEndpoint); + if (serviceId == checkEndpoint->serviceId) { + export = check; + free(ref); + break; + } + free(ref); + } + } + hashMapIterator_destroy(iter); + + if (export != NULL) { + + uint64_t datalength = request_info->content_length; + char* data = malloc(datalength + 1); + mg_read(conn, data, datalength); + data[datalength] = '\0'; + + char *response = NULL; + int responceLength = 0; + int rc = exportRegistration_call(export, data, -1, &response, &responceLength); + if (rc != CELIX_SUCCESS) { + RSA_LOG_ERROR(rsa, "Error trying to invoke remove service, got error %i\n", rc); + } + + if (rc == CELIX_SUCCESS && response != NULL) { + mg_write(conn, data_response_headers, strlen(data_response_headers)); + mg_write(conn, response, strlen(response)); + free(response); + } else { + mg_write(conn, no_content_response_headers, strlen(no_content_response_headers)); + } + result = 1; + + free(data); + } else { + result = 0; + RSA_LOG_WARNING(rsa, "NO export registration found for service id %lu", serviceId); + } + + celixThreadMutex_unlock(&rsa->exportedServicesLock); + + } + } + + return result; +} + +celix_status_t remoteServiceAdmin_exportService(remote_service_admin_pt admin, char *serviceId, properties_pt properties, array_list_pt *registrations) { + celix_status_t status; + + arrayList_create(registrations); + array_list_pt references = NULL; + service_reference_pt reference = NULL; + char filter [256]; + + snprintf(filter, 256, "(%s=%s)", (char *)OSGI_FRAMEWORK_SERVICE_ID, serviceId); + + status = bundleContext_getServiceReferences(admin->context, NULL, filter, &references); + + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "RSA: exportService called for serviceId %s", serviceId); + + int i; + int size = arrayList_size(references); + for (i = 0; i < size; i += 1) { + if (i == 0) { + reference = arrayList_get(references, i); + } else { + bundleContext_ungetServiceReference(admin->context, arrayList_get(references, i)); + } + } + arrayList_destroy(references); + + if (reference == NULL) { + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "ERROR: expected a reference for service id %s.", serviceId); + status = CELIX_ILLEGAL_STATE; + } + + const char *exports = NULL; + const char *provided = NULL; + if (status == CELIX_SUCCESS) { + serviceReference_getProperty(reference, (char *) OSGI_RSA_SERVICE_EXPORTED_INTERFACES, &exports); + serviceReference_getProperty(reference, (char *) OSGI_FRAMEWORK_OBJECTCLASS, &provided); + + if (exports == NULL || provided == NULL || strcmp(exports, provided) != 0) { + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_WARNING, "RSA: No Services to export."); + status = CELIX_ILLEGAL_STATE; + } else { + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Export service (%s)", provided); + } + } + + if (status == CELIX_SUCCESS) { + const char *interface = provided; + endpoint_description_pt endpoint = NULL; + export_registration_pt registration = NULL; + + remoteServiceAdmin_createEndpointDescription(admin, reference, properties, (char*)interface, &endpoint); + //TODO precheck if descriptor exists + status = exportRegistration_create(admin->loghelper, reference, endpoint, admin->context, ®istration); + if (status == CELIX_SUCCESS) { + status = exportRegistration_start(registration); + if (status == CELIX_SUCCESS) { + arrayList_add(*registrations, registration); + } + } + } + + + if (status == CELIX_SUCCESS) { + celixThreadMutex_lock(&admin->exportedServicesLock); + hashMap_put(admin->exportedServices, reference, *registrations); + celixThreadMutex_unlock(&admin->exportedServicesLock); + } + else{ + arrayList_destroy(*registrations); + *registrations = NULL; + } + + return status; +} + +celix_status_t remoteServiceAdmin_removeExportedService(remote_service_admin_pt admin, export_registration_pt registration) { + celix_status_t status; + + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA_DFI: Removing exported service"); + + export_reference_pt ref = NULL; + status = exportRegistration_getExportReference(registration, &ref); + + if (status == CELIX_SUCCESS && ref != NULL) { + service_reference_pt servRef; + celixThreadMutex_lock(&admin->exportedServicesLock); + exportReference_getExportedService(ref, &servRef); + + array_list_pt exports = (array_list_pt)hashMap_remove(admin->exportedServices, servRef); + if(exports!=NULL){ + arrayList_destroy(exports); + } + + exportRegistration_close(registration); + exportRegistration_destroy(registration); + + celixThreadMutex_unlock(&admin->exportedServicesLock); + + free(ref); + + } else { + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "Cannot find reference for registration"); + } + + return status; +} + +static celix_status_t remoteServiceAdmin_createEndpointDescription(remote_service_admin_pt admin, service_reference_pt reference, properties_pt props, char *interface, endpoint_description_pt *endpoint) { + + celix_status_t status = CELIX_SUCCESS; + properties_pt endpointProperties = properties_create(); + + + unsigned int size = 0; + char **keys; + + serviceReference_getPropertyKeys(reference, &keys, &size); + for (int i = 0; i < size; i++) { + char *key = keys[i]; + const char *value = NULL; + + if (serviceReference_getProperty(reference, key, &value) == CELIX_SUCCESS + && strcmp(key, (char*) OSGI_RSA_SERVICE_EXPORTED_INTERFACES) != 0 + && strcmp(key, (char*) OSGI_FRAMEWORK_OBJECTCLASS) != 0) { + properties_set(endpointProperties, key, value); + } + } + + hash_map_entry_pt entry = hashMap_getEntry(endpointProperties, (void *) OSGI_FRAMEWORK_SERVICE_ID); + + char* key = hashMapEntry_getKey(entry); + char *serviceId = (char *) hashMap_remove(endpointProperties, (void *) OSGI_FRAMEWORK_SERVICE_ID); + const char *uuid = NULL; + + char buf[512]; + snprintf(buf, 512, "/service/%s/%s", serviceId, interface); + + char url[1024]; + snprintf(url, 1024, "http://%s:%s%s", admin->ip, admin->port, buf); + + uuid_t endpoint_uid; + uuid_generate(endpoint_uid); + char endpoint_uuid[37]; + uuid_unparse_lower(endpoint_uid, endpoint_uuid); + + bundleContext_getProperty(admin->context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &uuid); + properties_set(endpointProperties, (char*) OSGI_RSA_ENDPOINT_FRAMEWORK_UUID, uuid); + properties_set(endpointProperties, (char*) OSGI_FRAMEWORK_OBJECTCLASS, interface); + properties_set(endpointProperties, (char*) OSGI_RSA_ENDPOINT_SERVICE_ID, serviceId); + properties_set(endpointProperties, (char*) OSGI_RSA_ENDPOINT_ID, endpoint_uuid); + properties_set(endpointProperties, (char*) OSGI_RSA_SERVICE_IMPORTED, "true"); + properties_set(endpointProperties, (char*) OSGI_RSA_SERVICE_IMPORTED_CONFIGS, (char*) CONFIGURATION_TYPE); + properties_set(endpointProperties, (char*) ENDPOINT_URL, url); + + if (props != NULL) { + hash_map_iterator_pt propIter = hashMapIterator_create(props); + while (hashMapIterator_hasNext(propIter)) { + hash_map_entry_pt entry = hashMapIterator_nextEntry(propIter); + properties_set(endpointProperties, (char*)hashMapEntry_getKey(entry), (char*)hashMapEntry_getValue(entry)); + } + hashMapIterator_destroy(propIter); + } + + *endpoint = calloc(1, sizeof(**endpoint)); + if (!*endpoint) { + status = CELIX_ENOMEM; + } else { + (*endpoint)->id = (char*)properties_get(endpointProperties, (char*) OSGI_RSA_ENDPOINT_ID); + const char *serviceId = NULL; + serviceReference_getProperty(reference, (char*) OSGI_FRAMEWORK_SERVICE_ID, &serviceId); + (*endpoint)->serviceId = strtoull(serviceId, NULL, 0); + (*endpoint)->frameworkUUID = (char*) properties_get(endpointProperties, (char*) OSGI_RSA_ENDPOINT_FRAMEWORK_UUID); + (*endpoint)->service = strndup(interface, 1024*10); + (*endpoint)->properties = endpointProperties; + } + + free(key); + free(serviceId); + free(keys); + + return status; +} + +static celix_status_t remoteServiceAdmin_getIpAdress(char* interface, char** ip) { + celix_status_t status = CELIX_BUNDLE_EXCEPTION; + + struct ifaddrs *ifaddr, *ifa; + char host[NI_MAXHOST]; + + if (getifaddrs(&ifaddr) != -1) + { + for (ifa = ifaddr; ifa != NULL && status != CELIX_SUCCESS; ifa = ifa->ifa_next) + { + if (ifa->ifa_addr == NULL) + continue; + + if ((getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0) && (ifa->ifa_addr->sa_family == AF_INET)) { + if (interface == NULL) { + *ip = strdup(host); + status = CELIX_SUCCESS; + } + else if (strcmp(ifa->ifa_name, interface) == 0) { + *ip = strdup(host); + status = CELIX_SUCCESS; + } + } + } + + freeifaddrs(ifaddr); + } + + return status; +} + + +celix_status_t remoteServiceAdmin_destroyEndpointDescription(endpoint_description_pt *description) +{ + celix_status_t status = CELIX_SUCCESS; + + properties_destroy((*description)->properties); + free((*description)->service); + free(*description); + + return status; +} + + +celix_status_t remoteServiceAdmin_getExportedServices(remote_service_admin_pt admin, array_list_pt *services) { + celix_status_t status = CELIX_SUCCESS; + return status; +} + +celix_status_t remoteServiceAdmin_getImportedEndpoints(remote_service_admin_pt admin, array_list_pt *services) { + celix_status_t status = CELIX_SUCCESS; + return status; +} + +celix_status_t remoteServiceAdmin_importService(remote_service_admin_pt admin, endpoint_description_pt endpointDescription, import_registration_pt *out) { + celix_status_t status = CELIX_SUCCESS; + import_registration_pt import = NULL; + + const char *objectClass = properties_get(endpointDescription->properties, "objectClass"); + const char *serviceVersion = properties_get(endpointDescription->properties, (char*) CELIX_FRAMEWORK_SERVICE_VERSION); + + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Import service %s", endpointDescription->service); + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "Registering service factory (proxy) for service '%s'\n", objectClass); + + if (objectClass != NULL) { + status = importRegistration_create(admin->context, endpointDescription, objectClass, serviceVersion, &import); + } + if (status == CELIX_SUCCESS && import != NULL) { + importRegistration_setSendFn(import, (send_func_type) remoteServiceAdmin_send, admin); + } + + if (status == CELIX_SUCCESS && import != NULL) { + status = importRegistration_start(import); + } + + celixThreadMutex_lock(&admin->importedServicesLock); + arrayList_add(admin->importedServices, import); + celixThreadMutex_unlock(&admin->importedServicesLock); + + if (status == CELIX_SUCCESS) { + *out = import; + } + + return status; +} + + +celix_status_t remoteServiceAdmin_removeImportedService(remote_service_admin_pt admin, import_registration_pt registration) { + celix_status_t status = CELIX_SUCCESS; + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA_DFI: Removing imported service"); + + celixThreadMutex_lock(&admin->importedServicesLock); + int i; + int size = arrayList_size(admin->importedServices); + import_registration_pt current = NULL; + for (i = 0; i < size; i += 1) { + current = arrayList_get(admin->importedServices, i); + if (current == registration) { + arrayList_remove(admin->importedServices, i); + importRegistration_close(current); + importRegistration_destroy(current); + break; + } + } + celixThreadMutex_unlock(&admin->importedServicesLock); + + return status; +} + + +static celix_status_t remoteServiceAdmin_send(void *handle, endpoint_description_pt endpointDescription, char *request, char **reply, int* replyStatus) { + remote_service_admin_pt rsa = handle; + struct post post; + post.readptr = request; + post.size = strlen(request); + + struct get get; + get.size = 0; + get.writeptr = malloc(1); + + char *serviceUrl = (char*)properties_get(endpointDescription->properties, (char*) ENDPOINT_URL); + char url[256]; + snprintf(url, 256, "%s", serviceUrl); + + // assume the default timeout + int timeout = DEFAULT_TIMEOUT; + + const char *timeoutStr = NULL; + // Check if the endpoint has a timeout, if so, use it. + timeoutStr = (char*) properties_get(endpointDescription->properties, (char*) OSGI_RSA_REMOTE_PROXY_TIMEOUT); + if (timeoutStr == NULL) { + // If not, get the global variable and use that one. + bundleContext_getProperty(rsa->context, (char*) OSGI_RSA_REMOTE_PROXY_TIMEOUT, &timeoutStr); + } + + // Update timeout if a property is used to set it. + if (timeoutStr != NULL) { + timeout = atoi(timeoutStr); + } + + celix_status_t status = CELIX_SUCCESS; + CURL *curl; + CURLcode res; + + curl = curl_easy_init(); + if(!curl) { + status = CELIX_ILLEGAL_STATE; + } else { + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_POST, 1L); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, remoteServiceAdmin_readCallback); + curl_easy_setopt(curl, CURLOPT_READDATA, &post); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, remoteServiceAdmin_write); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&get); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (curl_off_t)post.size); + logHelper_log(rsa->loghelper, OSGI_LOGSERVICE_DEBUG, "RSA: Performing curl post\n"); + res = curl_easy_perform(curl); + + *reply = get.writeptr; + *replyStatus = res; + + curl_easy_cleanup(curl); + } + + return status; +} + +static size_t remoteServiceAdmin_readCallback(void *ptr, size_t size, size_t nmemb, void *userp) { + struct post *post = userp; + + if (post->size) { + *(char *) ptr = post->readptr[0]; + post->readptr++; + post->size--; + return 1; + } + + return 0; +} + +static size_t remoteServiceAdmin_write(void *contents, size_t size, size_t nmemb, void *userp) { + size_t realsize = size * nmemb; + struct get *mem = (struct get *)userp; + + mem->writeptr = realloc(mem->writeptr, mem->size + realsize + 1); + if (mem->writeptr == NULL) { + /* out of memory! */ + printf("not enough memory (realloc returned NULL)"); + exit(EXIT_FAILURE); + } + + memcpy(&(mem->writeptr[mem->size]), contents, realsize); + mem->size += realsize; + mem->writeptr[mem->size] = 0; + + return realsize; +} + + +static void remoteServiceAdmin_log(remote_service_admin_pt admin, int level, const char *file, int line, const char *msg, ...) { + va_list ap; + va_start(ap, msg); + int levels[5] = {0, OSGI_LOGSERVICE_ERROR, OSGI_LOGSERVICE_WARNING, OSGI_LOGSERVICE_INFO, OSGI_LOGSERVICE_DEBUG}; + + char buf1[256]; + snprintf(buf1, 256, "FILE:%s, LINE:%i, MSG:", file, line); + + char buf2[256]; + vsnprintf(buf2, 256, msg, ap); + logHelper_log(admin->loghelper, levels[level], "%s%s", buf1, buf2); + va_end(ap); +}
http://git-wip-us.apache.org/repos/asf/celix/blob/2a670f26/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_dfi.h ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_dfi.h b/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_dfi.h new file mode 100644 index 0000000..8b282f1 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_dfi.h @@ -0,0 +1,57 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * remote_service_admin_http_impl.h + * + * \date Sep 30, 2011 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + +#ifndef REMOTE_SERVICE_ADMIN_HTTP_IMPL_H_ +#define REMOTE_SERVICE_ADMIN_HTTP_IMPL_H_ + + +#include "bundle_context.h" +#include "endpoint_description.h" + +//typedef struct remote_service_admin *remote_service_admin_pt; + +celix_status_t remoteServiceAdmin_create(bundle_context_pt context, remote_service_admin_pt *admin); +celix_status_t remoteServiceAdmin_destroy(remote_service_admin_pt *admin); + +celix_status_t remoteServiceAdmin_stop(remote_service_admin_pt admin); + +celix_status_t remoteServiceAdmin_exportService(remote_service_admin_pt admin, char *serviceId, properties_pt properties, array_list_pt *registrations); +celix_status_t remoteServiceAdmin_removeExportedService(remote_service_admin_pt admin, export_registration_pt registration); +celix_status_t remoteServiceAdmin_getExportedServices(remote_service_admin_pt admin, array_list_pt *services); +celix_status_t remoteServiceAdmin_getImportedEndpoints(remote_service_admin_pt admin, array_list_pt *services); +celix_status_t remoteServiceAdmin_importService(remote_service_admin_pt admin, endpoint_description_pt endpoint, import_registration_pt *registration); +celix_status_t remoteServiceAdmin_removeImportedService(remote_service_admin_pt admin, import_registration_pt registration); + + +celix_status_t exportReference_getExportedEndpoint(export_reference_pt reference, endpoint_description_pt *endpoint); +celix_status_t exportReference_getExportedService(export_reference_pt reference, service_reference_pt *service); + +celix_status_t importReference_getImportedEndpoint(import_reference_pt reference); +celix_status_t importReference_getImportedService(import_reference_pt reference); + +celix_status_t remoteServiceAdmin_destroyEndpointDescription(endpoint_description_pt *description); + +#endif /* REMOTE_SERVICE_ADMIN_HTTP_IMPL_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/2a670f26/remote_services/remote_service_admin_dfi/rsa_tst/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/rsa_tst/CMakeLists.txt b/remote_services/remote_service_admin_dfi/rsa_tst/CMakeLists.txt index 543d5a1..b3b272e 100644 --- a/remote_services/remote_service_admin_dfi/rsa_tst/CMakeLists.txt +++ b/remote_services/remote_service_admin_dfi/rsa_tst/CMakeLists.txt @@ -31,10 +31,8 @@ add_executable(test_rsa_dfi run_tests.cpp rsa_tests.cpp rsa_client_server_tests.cpp - - ${PROJECT_SOURCE_DIR}/remote_services/remote_service_admin/private/src/endpoint_description.c ) -target_link_libraries(test_rsa_dfi Celix::framework ${CURL_LIBRARIES} ${CPPUTEST_LIBRARY}) +target_link_libraries(test_rsa_dfi PRIVATE Celix::framework ${CURL_LIBRARIES} ${CPPUTEST_LIBRARY} remote_service_admin_common) get_property(rsa_bundle_file TARGET remote_service_admin_dfi PROPERTY BUNDLE_FILE) get_property(calc_bundle_file TARGET calculator PROPERTY BUNDLE_FILE) http://git-wip-us.apache.org/repos/asf/celix/blob/2a670f26/remote_services/remote_service_admin_dfi/rsa_tst/bundle/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/rsa_tst/bundle/CMakeLists.txt b/remote_services/remote_service_admin_dfi/rsa_tst/bundle/CMakeLists.txt index 27c3804..65b18e8 100644 --- a/remote_services/remote_service_admin_dfi/rsa_tst/bundle/CMakeLists.txt +++ b/remote_services/remote_service_admin_dfi/rsa_tst/bundle/CMakeLists.txt @@ -15,14 +15,6 @@ # specific language governing permissions and limitations # under the License. -include_directories( - ${CPPUTEST_INCLUDE_DIR} - ${PROJECT_SOURCE_DIR}/framework/public/include - ${PROJECT_SOURCE_DIR}/utils/public/include - ${PROJECT_SOURCE_DIR}/remote_services/examples/calculator_service/public/include -) - - add_bundle(rsa_dfi_tst_bundle VERSION 0.0.1 SOURCES @@ -30,8 +22,8 @@ add_bundle(rsa_dfi_tst_bundle ) bundle_files(rsa_dfi_tst_bundle - ${PROJECT_SOURCE_DIR}/remote_services/examples/calculator_service/public/include/org.apache.celix.calc.api.Calculator2.descriptor + ${PROJECT_SOURCE_DIR}/remote_services/examples/calculator_api/include/org.apache.celix.calc.api.Calculator2.descriptor DESTINATION . ) - -target_link_libraries(rsa_dfi_tst_bundle PRIVATE ${CPPUTEST_LIBRARY} ) +target_include_directories(rsa_dfi_tst_bundle PRIVATE calculator) +target_link_libraries(rsa_dfi_tst_bundle PRIVATE ${CPPUTEST_LIBRARY} calculator_api) http://git-wip-us.apache.org/repos/asf/celix/blob/2a670f26/remote_services/topology_manager/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/remote_services/topology_manager/CMakeLists.txt b/remote_services/topology_manager/CMakeLists.txt index 4bac4fd..defee5c 100644 --- a/remote_services/topology_manager/CMakeLists.txt +++ b/remote_services/topology_manager/CMakeLists.txt @@ -16,27 +16,19 @@ # under the License. celix_subproject(RSA_TOPOLOGY_MANAGER "Option to enable building the Remote Service Admin Service SHM bundle" ON DEPS REMOTE_SERVICE_ADMIN_DFI) if (RSA_TOPOLOGY_MANAGER) - include_directories("${PROJECT_SOURCE_DIR}/utils/public/include") - include_directories("${PROJECT_SOURCE_DIR}/remote_services/utils/public/include") - include_directories("${PROJECT_SOURCE_DIR}/remote_services/topology_manager/private/include") - include_directories("${PROJECT_SOURCE_DIR}/remote_services/endpoint_listener/public/include") - include_directories("${PROJECT_SOURCE_DIR}/remote_services/remote_service_admin/public/include") - include_directories("${PROJECT_SOURCE_DIR}/log_service/public/include") - include_directories("${PROJECT_SOURCE_DIR}/remote_services/topology_manager/public/include") - add_bundle(topology_manager SOURCES - private/src/topology_manager - private/src/scope - private/src/activator - - private/include/topology_manager.h - public/include/tm_scope.h + add_bundle(topology_manager + SOURCES + src/topology_manager + src/scope + src/activator VERSION 0.9.0 SYMBOLIC_NAME "apache_celix_rs_topology_manager" - NAME - "Apache Celix RS Topology Manager" + NAME "Apache Celix RS Topology Manager" ) - target_link_libraries(topology_manager PRIVATE Celix::log_helper) + target_include_directories(topology_manager PRIVATE src) + target_include_directories(topology_manager PUBLIC include) + target_link_libraries(topology_manager PRIVATE Celix::log_helper remote_service_admin_api) install_bundle(topology_manager) http://git-wip-us.apache.org/repos/asf/celix/blob/2a670f26/remote_services/topology_manager/include/tm_scope.h ---------------------------------------------------------------------- diff --git a/remote_services/topology_manager/include/tm_scope.h b/remote_services/topology_manager/include/tm_scope.h new file mode 100644 index 0000000..d4f60ca --- /dev/null +++ b/remote_services/topology_manager/include/tm_scope.h @@ -0,0 +1,46 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * tm_scope.h + * + * \date Oct 29, 2015 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + +#ifndef TM_SCOPE_H_ +#define TM_SCOPE_H_ + +#include "celix_errno.h" + +#define TOPOLOGYMANAGER_SCOPE_SERVICE "tm_scope" + + +struct tm_scope_service { + void *handle; // scope_pt + celix_status_t (*addExportScope)(void *handle, char *filter, properties_pt props); + celix_status_t (*removeExportScope)(void *handle, char *filter); + celix_status_t (*addImportScope)(void *handle, char *filter); + celix_status_t (*removeImportScope)(void *handle, char *filter); +}; + +typedef struct tm_scope_service tm_scope_service_t; +typedef tm_scope_service_t *tm_scope_service_pt; + +#endif /* TM_SCOPE_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/2a670f26/remote_services/topology_manager/private/include/scope.h ---------------------------------------------------------------------- diff --git a/remote_services/topology_manager/private/include/scope.h b/remote_services/topology_manager/private/include/scope.h deleted file mode 100644 index 4035e2c..0000000 --- a/remote_services/topology_manager/private/include/scope.h +++ /dev/null @@ -1,150 +0,0 @@ -/** - *Licensed to the Apache Software Foundation (ASF) under one - *or more contributor license agreements. See the NOTICE file - *distributed with this work for additional information - *regarding copyright ownership. The ASF licenses this file - *to you under the Apache License, Version 2.0 (the - *"License"); you may not use this file except in compliance - *with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - *Unless required by applicable law or agreed to in writing, - *software distributed under the License is distributed on an - *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - *specific language governing permissions and limitations - *under the License. - */ -/* - * scope.h - * - * \date Sep 29, 2015 - * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> - * \copyright Apache License, Version 2.0 - */ - -#ifndef TOPOLOGY_SCOPE_H_ -#define TOPOLOGY_SCOPE_H_ - -#include "celixbool.h" -#include "celix_errno.h" -#include "celix_threads.h" -#include "hash_map.h" -#include "endpoint_description.h" -#include "properties.h" -#include "service_reference.h" -#include "tm_scope.h" - -typedef struct scope *scope_pt; - - - -/* \brief create scope structure - * - * \param owning component pointer - * \param scope to be created - * - * \return CELIX_SUCCESS - * CELIX_ENOMEM - */ -celix_status_t scope_scopeCreate(void *handle, scope_pt *scope); - -/* \brief destroy scope structure - * - * \param scope to be destroyed - * - * \return CELIX_SUCCESS - */ -celix_status_t scope_scopeDestroy(scope_pt scope); - -/* \brief register export scope change callback of topology manager - * - * \param scope structure - * \param changed function pointer - * - * \return - - */ -void scope_setExportScopeChangedCallback(scope_pt scope, celix_status_t (*changed)(void *handle, char *servName)); - -/* \brief register import scope change callback of topology manager - * - * \param scope structure - * \param changed function pointer - * - * \return - - */ -void scope_setImportScopeChangedCallback(scope_pt scope, celix_status_t (*changed)(void *handle, char *servName)); - - -/* \brief Test if scope allows import of service - * - * \param scope containing import rules - * \param endpoint import service endpoint description - * - * \return true import allowed - * false import not allowed - */ -bool scope_allowImport(scope_pt scope, endpoint_description_pt endpoint); - -/* \brief Test if scope allows import of service - * - * \param scope containing export rules - * \param reference to service - * \param props, additional properties defining restrictions for the exported service - * NULL if no additional restrictions found - * - * \return CELIX_SUCCESS - * - */ -celix_status_t scope_getExportProperties(scope_pt scope, service_reference_pt reference, properties_pt *props); - -/* \brief add restricted scope for specified exported service - * - * \param handle pointer to scope - * \param filter, filter string - * \param props additional properties defining restrictions for the exported service - * - * \return CELIX_SUCCESS if added to scope - * CELIX_ILLEGAL_ARGUMENT if service scope is already restricted before - * - */ -celix_status_t tm_addExportScope(void *handle, char *filter, properties_pt props); - -/* \brief remove restricted scope for specified exported service - * - * \param handle pointer to scope - * \param filter, filter string - * - * \return CELIX_SUCCESS if removed - * CELIX_ILLEGAL_ARGUMENT if service not found in scope - * - */ -celix_status_t tm_removeExportScope(void *handle, char *filter); - -/* \brief add restricted scope for specified imported service - * - * \param handle pointer to scope - * \param filter, filter string - * \param props additional properties defining restrictions for the imported service - * - * \return CELIX_SUCCESS if added to scope - * CELIX_ILLEGAL_ARGUMENT if service scope is already restricted before - * - */ -celix_status_t tm_addImportScope(void *handle, char *filter); - - -/* \brief remove restricted scope for specified imported service - * - * \param handle pointer to scope - * \param filter, filter string - * - * \return CELIX_SUCCESS if removed - * CELIX_ILLEGAL_ARGUMENT if service not found in scope - * - */ -celix_status_t tm_removeImportScope(void *handle, char *filter); - - -#endif // TOPOLOGY_SCOPE_H_ http://git-wip-us.apache.org/repos/asf/celix/blob/2a670f26/remote_services/topology_manager/private/include/topology_manager.h ---------------------------------------------------------------------- diff --git a/remote_services/topology_manager/private/include/topology_manager.h b/remote_services/topology_manager/private/include/topology_manager.h deleted file mode 100644 index 7e5e917..0000000 --- a/remote_services/topology_manager/private/include/topology_manager.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - *Licensed to the Apache Software Foundation (ASF) under one - *or more contributor license agreements. See the NOTICE file - *distributed with this work for additional information - *regarding copyright ownership. The ASF licenses this file - *to you under the Apache License, Version 2.0 (the - *"License"); you may not use this file except in compliance - *with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - *Unless required by applicable law or agreed to in writing, - *software distributed under the License is distributed on an - *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - *specific language governing permissions and limitations - *under the License. - */ -/* - * topology_manager.h - * - * \date Sep 29, 2011 - * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> - * \copyright Apache License, Version 2.0 - */ - -#ifndef TOPOLOGY_MANAGER_H_ -#define TOPOLOGY_MANAGER_H_ - -#include "endpoint_listener.h" -#include "service_reference.h" -#include "bundle_context.h" -#include "log_helper.h" -#include "scope.h" - -#define OSGI_RSA_REMOTE_SERVICE_ADMIN "remote_service_admin" - -typedef struct topology_manager *topology_manager_pt; - -celix_status_t topologyManager_create(bundle_context_pt context, log_helper_pt logHelper, topology_manager_pt *manager, void **scope); -celix_status_t topologyManager_destroy(topology_manager_pt manager); -celix_status_t topologyManager_closeImports(topology_manager_pt manager); - -celix_status_t topologyManager_rsaAdding(void *handle, service_reference_pt reference, void **service); -celix_status_t topologyManager_rsaAdded(void *handle, service_reference_pt reference, void *service); -celix_status_t topologyManager_rsaModified(void *handle, service_reference_pt reference, void *service); -celix_status_t topologyManager_rsaRemoved(void *handle, service_reference_pt reference, void *service); - -celix_status_t topologyManager_endpointListenerAdding(void* handle, service_reference_pt reference, void** service); -celix_status_t topologyManager_endpointListenerAdded(void* handle, service_reference_pt reference, void* service); -celix_status_t topologyManager_endpointListenerModified(void * handle, service_reference_pt reference, void* service); -celix_status_t topologyManager_endpointListenerRemoved(void * handle, service_reference_pt reference, void* service); - -celix_status_t topologyManager_serviceChanged(void *listener, service_event_pt event); - -celix_status_t topologyManager_addImportedService(void *handle, endpoint_description_pt endpoint, char *matchedFilter); -celix_status_t topologyManager_removeImportedService(void *handle, endpoint_description_pt endpoint, char *matchedFilter); - -celix_status_t topologyManager_addExportedService(topology_manager_pt manager, service_reference_pt reference, char *serviceId); -celix_status_t topologyManager_removeExportedService(topology_manager_pt manager, service_reference_pt reference, char *serviceId); - -celix_status_t topologyManager_listenerAdded(void *handle, array_list_pt listeners); -celix_status_t topologyManager_listenerRemoved(void *handle, array_list_pt listeners); - -#endif /* TOPOLOGY_MANAGER_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/2a670f26/remote_services/topology_manager/private/src/activator.c ---------------------------------------------------------------------- diff --git a/remote_services/topology_manager/private/src/activator.c b/remote_services/topology_manager/private/src/activator.c deleted file mode 100644 index 7f39a25..0000000 --- a/remote_services/topology_manager/private/src/activator.c +++ /dev/null @@ -1,289 +0,0 @@ -/** - *Licensed to the Apache Software Foundation (ASF) under one - *or more contributor license agreements. See the NOTICE file - *distributed with this work for additional information - *regarding copyright ownership. The ASF licenses this file - *to you under the Apache License, Version 2.0 (the - *"License"); you may not use this file except in compliance - *with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - *Unless required by applicable law or agreed to in writing, - *software distributed under the License is distributed on an - *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - *specific language governing permissions and limitations - *under the License. - */ -/* - * activator.c - * - * \date Sep 29, 2011 - * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> - * \copyright Apache License, Version 2.0 - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "constants.h" -#include "bundle_activator.h" -#include "service_tracker.h" -#include "service_registration.h" - -#include "topology_manager.h" -#include "endpoint_listener.h" -#include "remote_constants.h" -#include "listener_hook_service.h" -#include "log_service.h" -#include "log_helper.h" -#include "scope.h" -#include "tm_scope.h" -#include "topology_manager.h" - -struct activator { - bundle_context_pt context; - - topology_manager_pt manager; - - service_tracker_pt endpointListenerTracker; - service_tracker_pt remoteServiceAdminTracker; - service_listener_pt serviceListener; - - endpoint_listener_pt endpointListener; - service_registration_pt endpointListenerService; - - listener_hook_service_pt hookService; - service_registration_pt hook; - - tm_scope_service_pt scopeService; - service_registration_pt scopeReg; - - log_helper_pt loghelper; -}; - - -static celix_status_t bundleActivator_createEPLTracker(struct activator *activator, service_tracker_pt *tracker); -static celix_status_t bundleActivator_createRSATracker(struct activator *activator, service_tracker_pt *tracker); -static celix_status_t bundleActivator_createServiceListener(struct activator *activator, service_listener_pt *listener); - -celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) { - celix_status_t status = CELIX_SUCCESS; - struct activator *activator = NULL; - void *scope; - - activator = calloc(1, sizeof(struct activator)); - - if (!activator) { - return CELIX_ENOMEM; - } - - activator->context = context; - activator->endpointListenerService = NULL; - activator->endpointListenerTracker = NULL; - activator->hook = NULL; - activator->manager = NULL; - activator->remoteServiceAdminTracker = NULL; - activator->serviceListener = NULL; - activator->scopeService = calloc(1, sizeof(*(activator->scopeService))); - if (activator->scopeService == NULL) - { - free(activator); - return CELIX_ENOMEM; - } - - activator->scopeService->addExportScope = tm_addExportScope; - activator->scopeService->removeExportScope = tm_removeExportScope; - activator->scopeService->addImportScope = tm_addImportScope; - activator->scopeService->removeImportScope = tm_removeImportScope; - activator->scopeReg = NULL; // explicitly needed, otherwise exception - - logHelper_create(context, &activator->loghelper); - logHelper_start(activator->loghelper); - - status = topologyManager_create(context, activator->loghelper, &activator->manager, &scope); - activator->scopeService->handle = scope; - - if (status == CELIX_SUCCESS) { - status = bundleActivator_createEPLTracker(activator, &activator->endpointListenerTracker); - if (status == CELIX_SUCCESS) { - status = bundleActivator_createRSATracker(activator, &activator->remoteServiceAdminTracker); - if (status == CELIX_SUCCESS) { - status = bundleActivator_createServiceListener(activator, &activator->serviceListener); - if (status == CELIX_SUCCESS) { - *userData = activator; - } - } - } - } - - if(status != CELIX_SUCCESS){ - bundleActivator_destroy(activator,context); - } - - return status; -} - -static celix_status_t bundleActivator_createEPLTracker(struct activator *activator, service_tracker_pt *tracker) { - celix_status_t status; - - service_tracker_customizer_pt customizer = NULL; - - status = serviceTrackerCustomizer_create(activator->manager, topologyManager_endpointListenerAdding, topologyManager_endpointListenerAdded, topologyManager_endpointListenerModified, - topologyManager_endpointListenerRemoved, &customizer); - - if (status == CELIX_SUCCESS) { - status = serviceTracker_create(activator->context, (char *) OSGI_ENDPOINT_LISTENER_SERVICE, customizer, tracker); - } - - return status; -} - -static celix_status_t bundleActivator_createRSATracker(struct activator *activator, service_tracker_pt *tracker) { - celix_status_t status; - - service_tracker_customizer_pt customizer = NULL; - - status = serviceTrackerCustomizer_create(activator->manager, topologyManager_rsaAdding, topologyManager_rsaAdded, topologyManager_rsaModified, topologyManager_rsaRemoved, &customizer); - - if (status == CELIX_SUCCESS) { - status = serviceTracker_create(activator->context, OSGI_RSA_REMOTE_SERVICE_ADMIN, customizer, tracker); - } - - return status; -} - -static celix_status_t bundleActivator_createServiceListener(struct activator *activator, service_listener_pt *listener) { - celix_status_t status = CELIX_SUCCESS; - - *listener = malloc(sizeof(**listener)); - if (!*listener) { - return CELIX_ENOMEM; - } - - (*listener)->handle = activator->manager; - (*listener)->serviceChanged = topologyManager_serviceChanged; - - return status; -} - -celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) { - celix_status_t status; - struct activator *activator = userData; - - endpoint_listener_pt endpointListener = malloc(sizeof(*endpointListener)); - endpointListener->handle = activator->manager; - endpointListener->endpointAdded = topologyManager_addImportedService; - endpointListener->endpointRemoved = topologyManager_removeImportedService; - activator->endpointListener = endpointListener; - - const char *uuid = NULL; - status = bundleContext_getProperty(activator->context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &uuid); - if (!uuid) { - logHelper_log(activator->loghelper, OSGI_LOGSERVICE_ERROR, "TOPOLOGY_MANAGER: no framework UUID defined?!"); - return CELIX_ILLEGAL_STATE; - } - - size_t len = 14 + strlen(OSGI_FRAMEWORK_OBJECTCLASS) + strlen(OSGI_RSA_ENDPOINT_FRAMEWORK_UUID) + strlen(uuid); - char *scope = malloc(len); - if (!scope) { - return CELIX_ENOMEM; - } - - snprintf(scope, len, "(&(%s=*)(!(%s=%s)))", OSGI_FRAMEWORK_OBJECTCLASS, OSGI_RSA_ENDPOINT_FRAMEWORK_UUID, uuid); - - logHelper_log(activator->loghelper, OSGI_LOGSERVICE_INFO, "TOPOLOGY_MANAGER: endpoint listener scope is %s", scope); - - properties_pt props = properties_create(); - properties_set(props, (char *) OSGI_ENDPOINT_LISTENER_SCOPE, scope); - - // We can release the scope, as properties_set makes a copy of the key & value... - free(scope); - - bundleContext_registerService(context, (char *) OSGI_ENDPOINT_LISTENER_SERVICE, endpointListener, props, &activator->endpointListenerService); - - listener_hook_service_pt hookService = malloc(sizeof(*hookService)); - hookService->handle = activator->manager; - hookService->added = topologyManager_listenerAdded; - hookService->removed = topologyManager_listenerRemoved; - activator->hookService = hookService; - - bundleContext_registerService(context, (char *) OSGI_FRAMEWORK_LISTENER_HOOK_SERVICE_NAME, hookService, NULL, &activator->hook); - bundleContext_addServiceListener(context, activator->serviceListener, "(service.exported.interfaces=*)"); - - if (status == CELIX_SUCCESS) { - serviceTracker_open(activator->remoteServiceAdminTracker); - } - - if (status == CELIX_SUCCESS) { - status = serviceTracker_open(activator->endpointListenerTracker); - } - - bundleContext_registerService(context, (char *) TOPOLOGYMANAGER_SCOPE_SERVICE, activator->scopeService, NULL, &activator->scopeReg); - - array_list_pt references = NULL; - bundleContext_getServiceReferences(context, NULL, "(service.exported.interfaces=*)", &references); - int i; - for (i = 0; i < arrayList_size(references); i++) { - service_reference_pt reference = arrayList_get(references, i); - const char* serviceId = NULL; - status = CELIX_DO_IF(status, serviceReference_getProperty(reference, OSGI_FRAMEWORK_SERVICE_ID, &serviceId)); - - CELIX_DO_IF(status, topologyManager_addExportedService(activator->manager, reference, (char*)serviceId)); - } - arrayList_destroy(references); - - return status; -} - -celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) { - celix_status_t status = CELIX_SUCCESS; - struct activator *activator = userData; - - if (serviceTracker_close(activator->remoteServiceAdminTracker) == CELIX_SUCCESS) { - serviceTracker_destroy(activator->remoteServiceAdminTracker); - } - - if (serviceTracker_close(activator->endpointListenerTracker) == CELIX_SUCCESS) { - serviceTracker_destroy(activator->endpointListenerTracker); - } - - bundleContext_removeServiceListener(context, activator->serviceListener); - free(activator->serviceListener); - - serviceRegistration_unregister(activator->hook); - free(activator->hookService); - - serviceRegistration_unregister(activator->endpointListenerService); - free(activator->endpointListener); - - serviceRegistration_unregister(activator->scopeReg); - - topologyManager_closeImports(activator->manager); - - return status; -} - -celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) { - celix_status_t status = CELIX_SUCCESS; - - struct activator *activator = userData; - if (!activator || !activator->manager) { - status = CELIX_BUNDLE_EXCEPTION; - } else { - logHelper_stop(activator->loghelper); - logHelper_destroy(&activator->loghelper); - - status = topologyManager_destroy(activator->manager); - - if (activator->scopeService) { - free(activator->scopeService); - } - - free(activator); - } - - return status; -} http://git-wip-us.apache.org/repos/asf/celix/blob/2a670f26/remote_services/topology_manager/private/src/scope.c ---------------------------------------------------------------------- diff --git a/remote_services/topology_manager/private/src/scope.c b/remote_services/topology_manager/private/src/scope.c deleted file mode 100644 index b81d050..0000000 --- a/remote_services/topology_manager/private/src/scope.c +++ /dev/null @@ -1,326 +0,0 @@ -/** - *Licensed to the Apache Software Foundation (ASF) under one - *or more contributor license agreements. See the NOTICE file - *distributed with this work for additional information - *regarding copyright ownership. The ASF licenses this file - *to you under the Apache License, Version 2.0 (the - *"License"); you may not use this file except in compliance - *with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - *Unless required by applicable law or agreed to in writing, - *software distributed under the License is distributed on an - *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - *specific language governing permissions and limitations - *under the License. - */ -/* - * scope.c - * - * \date Sep 29, 2015 - * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> - * \copyright Apache License, Version 2.0 - */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "scope.h" -#include "tm_scope.h" -#include "topology_manager.h" -#include "utils.h" - -struct scope_item { - properties_pt props; -}; - -struct scope { - void *manager; // owner of the scope datastructure - celix_thread_mutex_t exportScopeLock; - hash_map_pt exportScopes; // key is filter, value is scope_item (properties set) - - celix_thread_mutex_t importScopeLock; - array_list_pt importScopes; // list of filters - - celix_status_t (*exportScopeChangedHandler)(void* manager, char *filter); - celix_status_t (*importScopeChangedHandler)(void* manager, char *filter); -}; - -static celix_status_t import_equal(const void *, const void *, bool *equals); - -/* - * SERVICES - */ - -celix_status_t tm_addExportScope(void *handle, char *filter, properties_pt props) { - celix_status_t status = CELIX_SUCCESS; - scope_pt scope = (scope_pt) handle; - properties_pt present; - - if (handle == NULL) - return CELIX_ILLEGAL_ARGUMENT; - - if (celixThreadMutex_lock(&scope->exportScopeLock) == CELIX_SUCCESS) { - // For now we just don't allow two exactly the same filters - // TODO: What we actually need is the following - // If part of the new filter is already present in any of the filters in exportScopes - // we have to assure that the new filter defines other property keys than the property keys - // in the already defined filter! - present = (properties_pt) hashMap_get(scope->exportScopes, filter); - if (present == NULL) { - struct scope_item *item = calloc(1, sizeof(*item)); - if (item == NULL) { - status = CELIX_ENOMEM; - } else { - item->props = props; - hashMap_put(scope->exportScopes, (void*) strdup(filter), (void*) item); - } - } else { - // don't allow the same filter twice - properties_destroy(props); - status = CELIX_ILLEGAL_ARGUMENT; - } - celixThreadMutex_unlock(&scope->exportScopeLock); - } - - if (scope->exportScopeChangedHandler != NULL) { - status = CELIX_DO_IF(status, scope->exportScopeChangedHandler(scope->manager, filter)); - } - - return status; -} - -celix_status_t tm_removeExportScope(void *handle, char *filter) { - celix_status_t status = CELIX_SUCCESS; - scope_pt scope = (scope_pt) handle; - - if (handle == NULL) - return CELIX_ILLEGAL_ARGUMENT; - - if (celixThreadMutex_lock(&scope->exportScopeLock) == CELIX_SUCCESS) { - struct scope_item *present = (struct scope_item *) hashMap_get(scope->exportScopes, filter); - if (present == NULL) { - status = CELIX_ILLEGAL_ARGUMENT; - } else { - properties_destroy(present->props); - hashMap_remove(scope->exportScopes, filter); // frees also the item! - } - celixThreadMutex_unlock(&scope->exportScopeLock); - } - if (scope->exportScopeChangedHandler != NULL) { - status = CELIX_DO_IF(status, scope->exportScopeChangedHandler(scope->manager, filter)); - } - return status; -} - -celix_status_t tm_addImportScope(void *handle, char *filter) { - celix_status_t status = CELIX_SUCCESS; - scope_pt scope = (scope_pt) handle; - - filter_pt new; - - if (handle == NULL) - return CELIX_ILLEGAL_ARGUMENT; - new = filter_create(filter); - if (new == NULL) { - return CELIX_ILLEGAL_ARGUMENT; // filter not parseble - } - if (celixThreadMutex_lock(&scope->importScopeLock) == CELIX_SUCCESS) { - int index = arrayList_indexOf(scope->importScopes, new); - filter_pt present = (filter_pt) arrayList_get(scope->importScopes, index); - if (present == NULL) { - arrayList_add(scope->importScopes, new); - } else { - filter_destroy(new); - status = CELIX_ILLEGAL_ARGUMENT; - } - - celixThreadMutex_unlock(&scope->importScopeLock); - } - if (scope->importScopeChangedHandler != NULL) { - status = CELIX_DO_IF(status, scope->importScopeChangedHandler(scope->manager, filter)); - } - return status; -} - -celix_status_t tm_removeImportScope(void *handle, char *filter) { - celix_status_t status = CELIX_SUCCESS; - scope_pt scope = (scope_pt) handle; - filter_pt new; - - if (handle == NULL) - return CELIX_ILLEGAL_ARGUMENT; - - new = filter_create(filter); - if (new == NULL) { - return CELIX_ILLEGAL_ARGUMENT; // filter not parseble - } - - if (celixThreadMutex_lock(&scope->importScopeLock) == CELIX_SUCCESS) { - int index = arrayList_indexOf(scope->importScopes, new); - filter_pt present = (filter_pt) arrayList_get(scope->importScopes, index); - if (present == NULL) - status = CELIX_ILLEGAL_ARGUMENT; - else { - arrayList_removeElement(scope->importScopes, present); - filter_destroy(present); - } - celixThreadMutex_unlock(&scope->importScopeLock); - } - if (scope->importScopeChangedHandler != NULL) { - status = CELIX_DO_IF(status, scope->importScopeChangedHandler(scope->manager, filter)); - } - filter_destroy(new); - return status; -} - -/***************************************************************************** - * GLOBAL FUNCTIONS - *****************************************************************************/ - -void scope_setExportScopeChangedCallback(scope_pt scope, celix_status_t (*changed)(void *handle, char *servName)) { - scope->exportScopeChangedHandler = changed; -} - -void scope_setImportScopeChangedCallback(scope_pt scope, celix_status_t (*changed)(void *handle, char *servName)) { - scope->importScopeChangedHandler = changed; -} - -celix_status_t scope_scopeCreate(void *handle, scope_pt *scope) { - celix_status_t status = CELIX_SUCCESS; - - *scope = calloc(1, sizeof **scope); - - if (*scope == NULL) { - return CELIX_ENOMEM; - } - - (*scope)->manager = handle; - celixThreadMutex_create(&(*scope)->exportScopeLock, NULL); - celixThreadMutex_create(&(*scope)->importScopeLock, NULL); - - (*scope)->exportScopes = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL); - arrayList_createWithEquals(import_equal, &((*scope)->importScopes)); - (*scope)->exportScopeChangedHandler = NULL; - - return status; -} - -celix_status_t scope_scopeDestroy(scope_pt scope) { - celix_status_t status = CELIX_SUCCESS; - - if (celixThreadMutex_lock(&scope->exportScopeLock) == CELIX_SUCCESS) { - hash_map_iterator_pt iter = hashMapIterator_create(scope->exportScopes); - while (hashMapIterator_hasNext(iter)) { - hash_map_entry_pt scopedEntry = hashMapIterator_nextEntry(iter); - struct scope_item *item = (struct scope_item*) hashMapEntry_getValue(scopedEntry); - properties_destroy(item->props); - } - hashMapIterator_destroy(iter); - hashMap_destroy(scope->exportScopes, true, true); // free keys, free values - celixThreadMutex_unlock(&scope->exportScopeLock); - } - - if (celixThreadMutex_lock(&scope->importScopeLock) == CELIX_SUCCESS) { - array_list_iterator_pt imp_iter = arrayListIterator_create(scope->importScopes); - while (arrayListIterator_hasNext(imp_iter)) { - filter_pt element = (filter_pt) arrayListIterator_next(imp_iter); - filter_destroy(element); - // no need to call arrayList_removeElement(element) because complete list is destroyed - } - arrayListIterator_destroy(imp_iter); - arrayList_destroy(scope->importScopes); - celixThreadMutex_unlock(&scope->importScopeLock); - } - - celixThreadMutex_destroy(&scope->exportScopeLock); - celixThreadMutex_destroy(&scope->importScopeLock); - free(scope); - return status; -} - -/***************************************************************************** - * STATIC FUNCTIONS - *****************************************************************************/ -static celix_status_t import_equal(const void *src, const void *dest, bool *equals) { - celix_status_t status; - - filter_pt src_filter = (filter_pt) src; - filter_pt dest_filter = (filter_pt) dest; - status = filter_match_filter(src_filter, dest_filter, equals); - return status; -} - -bool scope_allowImport(scope_pt scope, endpoint_description_pt endpoint) { - bool allowImport = false; - array_list_iterator_pt iter; - - if (celixThreadMutex_lock(&(scope->importScopeLock)) == CELIX_SUCCESS) { - if (arrayList_size(scope->importScopes) == 0) { - allowImport = true; - } else { - iter = arrayListIterator_create(scope->importScopes); - while ((allowImport == false) && arrayListIterator_hasNext(iter)) { - filter_pt element = (filter_pt) arrayListIterator_next(iter); - filter_match(element, endpoint->properties, &allowImport); - } - arrayListIterator_destroy(iter); - } - celixThreadMutex_unlock(&scope->importScopeLock); - } - return allowImport; -} - -celix_status_t scope_getExportProperties(scope_pt scope, service_reference_pt reference, properties_pt *props) { - celix_status_t status = CELIX_SUCCESS; - unsigned int size = 0; - char **keys; - bool found = false; - - *props = NULL; - properties_pt serviceProperties = properties_create(); // GB: not sure if a copy is needed - // or serviceReference_getProperties() is - // is acceptable - - serviceReference_getPropertyKeys(reference, &keys, &size); - for (int i = 0; i < size; i++) { - char *key = keys[i]; - const char* value = NULL; - - if (serviceReference_getProperty(reference, key, &value) == CELIX_SUCCESS) { -// && strcmp(key, (char*) OSGI_RSA_SERVICE_EXPORTED_INTERFACES) != 0 -// && strcmp(key, (char*) OSGI_FRAMEWORK_OBJECTCLASS) != 0) { - properties_set(serviceProperties, key, value); - } - - } - - free(keys); - - if (celixThreadMutex_lock(&(scope->exportScopeLock)) == CELIX_SUCCESS) { - hash_map_iterator_pt scopedPropIter = hashMapIterator_create(scope->exportScopes); - // TODO: now stopping if first filter matches, alternatively we could build up - // the additional output properties for each filter that matches? - while ((!found) && hashMapIterator_hasNext(scopedPropIter)) { - hash_map_entry_pt scopedEntry = hashMapIterator_nextEntry(scopedPropIter); - char *filterStr = (char *) hashMapEntry_getKey(scopedEntry); - filter_pt filter = filter_create(filterStr); - if (filter != NULL) { - // test if the scope filter matches the exported service properties - status = filter_match(filter, serviceProperties, &found); - if (found) { - struct scope_item *item = (struct scope_item *) hashMapEntry_getValue(scopedEntry); - *props = item->props; - } - } - filter_destroy(filter); - } - hashMapIterator_destroy(scopedPropIter); - properties_destroy(serviceProperties); - - celixThreadMutex_unlock(&(scope->exportScopeLock)); - } - - return status; -}
