You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2017/11/21 20:08:03 UTC
[06/19] celix git commit: CELIX-417: Refactor for CMake usage in RSA,
PSA and Docker. mostly trying to identify the api and common libraries
http://git-wip-us.apache.org/repos/asf/celix/blob/2a670f26/remote_services/remote_service_admin_dfi/rsa/private/src/remote_service_admin_dfi.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/private/src/remote_service_admin_dfi.c b/remote_services/remote_service_admin_dfi/rsa/private/src/remote_service_admin_dfi.c
deleted file mode 100644
index 9feab9f..0000000
--- a/remote_services/remote_service_admin_dfi/rsa/private/src/remote_service_admin_dfi.c
+++ /dev/null
@@ -1,775 +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.
- */
-/*
- * remote_service_admin_impl.c
- *
- * \date May 21, 2015
- * \author <a href="mailto:dev@celix.apache.org">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/dfi_utils.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/src/dfi_utils.c b/remote_services/remote_service_admin_dfi/rsa/src/dfi_utils.c
new file mode 100644
index 0000000..1b1eb36
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/rsa/src/dfi_utils.c
@@ -0,0 +1,98 @@
+/**
+ *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.
+ */
+
+#include "dfi_utils.h"
+#include <stdlib.h>
+#include <unistd.h>
+
+static celix_status_t dfi_findFileForFramework(bundle_context_pt context, const char *fileName, FILE **out) {
+ celix_status_t status;
+
+ char pwd[1024];
+ char path[1024];
+ const char *extPath = NULL;
+
+ status = bundleContext_getProperty(context, "CELIX_FRAMEWORK_EXTENDER_PATH", &extPath);
+ if (status != CELIX_SUCCESS || extPath == NULL) {
+ getcwd(pwd, sizeof(pwd));
+ extPath = pwd;
+ }
+
+ snprintf(path, sizeof(path), "%s/%s", extPath, fileName);
+
+ if (status == CELIX_SUCCESS) {
+ FILE *df = fopen(path, "r");
+ if (df == NULL) {
+ status = CELIX_FILE_IO_EXCEPTION;
+ } else {
+ *out = df;
+ }
+ }
+
+ return status;
+}
+
+static celix_status_t dfi_findFileForBundle(bundle_pt bundle, const char *fileName, FILE **out) {
+ celix_status_t status;
+
+ char *path = NULL;
+ char metaInfFileName[512];
+ snprintf(metaInfFileName, sizeof(metaInfFileName), "META-INF/descriptors/%s", fileName);
+
+ status = bundle_getEntry(bundle, fileName, &path);
+
+ if (status != CELIX_SUCCESS || path == NULL) {
+ status = bundle_getEntry(bundle, metaInfFileName, &path);
+ }
+
+ if (status == CELIX_SUCCESS && path != NULL) {
+ FILE *df = fopen(path, "r");
+ if (df == NULL) {
+ status = CELIX_FILE_IO_EXCEPTION;
+ } else {
+ *out = df;
+ }
+
+ }
+
+ free(path);
+ return status;
+}
+
+celix_status_t dfi_findDescriptor(bundle_context_pt context, bundle_pt bundle, const char *name, FILE **out) {
+ celix_status_t status;
+ char fileName[128];
+
+ snprintf(fileName, 128, "%s.descriptor", name);
+
+ long id;
+ status = bundle_getBundleId(bundle, &id);
+
+ if (status == CELIX_SUCCESS) {
+ if (id == 0) {
+ //framework bundle
+ status = dfi_findFileForFramework(context, fileName, out);
+ } else {
+ //normal bundle
+ status = dfi_findFileForBundle(bundle, fileName, out);
+ }
+ }
+
+ return status;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/2a670f26/remote_services/remote_service_admin_dfi/rsa/src/dfi_utils.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/src/dfi_utils.h b/remote_services/remote_service_admin_dfi/rsa/src/dfi_utils.h
new file mode 100644
index 0000000..cec8aa1
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/rsa/src/dfi_utils.h
@@ -0,0 +1,30 @@
+/**
+ *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.
+ */
+#ifndef DFI_UTILS_H_
+#define DFI_UTILS_H_
+
+#include "bundle.h"
+#include "bundle_context.h"
+#include <stdio.h>
+#include "celix_errno.h"
+
+
+celix_status_t dfi_findDescriptor(bundle_context_pt context, bundle_pt bundle, const char *name, FILE **out);
+
+#endif
http://git-wip-us.apache.org/repos/asf/celix/blob/2a670f26/remote_services/remote_service_admin_dfi/rsa/src/export_registration_dfi.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/src/export_registration_dfi.c b/remote_services/remote_service_admin_dfi/rsa/src/export_registration_dfi.c
new file mode 100644
index 0000000..b83b5a8
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/rsa/src/export_registration_dfi.c
@@ -0,0 +1,251 @@
+/**
+ *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.
+ */
+
+#include <jansson.h>
+#include <dyn_interface.h>
+#include <json_serializer.h>
+#include <remote_constants.h>
+#include <remote_service_admin.h>
+#include <service_tracker_customizer.h>
+#include <service_tracker.h>
+#include <json_rpc.h>
+#include "constants.h"
+#include "export_registration_dfi.h"
+#include "dfi_utils.h"
+
+struct export_reference {
+ endpoint_description_pt endpoint; //owner
+ service_reference_pt reference;
+};
+
+struct export_registration {
+ bundle_context_pt context;
+ struct export_reference exportReference;
+ char *servId;
+ dyn_interface_type *intf; //owner
+ service_tracker_pt tracker;
+
+ celix_thread_mutex_t mutex;
+ void *service; //protected by mutex
+
+ //TODO add tracker and lock
+ bool closed;
+};
+
+static void exportRegistration_addServ(export_registration_pt reg, service_reference_pt ref, void *service);
+static void exportRegistration_removeServ(export_registration_pt reg, service_reference_pt ref, void *service);
+
+celix_status_t exportRegistration_create(log_helper_pt helper, service_reference_pt reference, endpoint_description_pt endpoint, bundle_context_pt context, export_registration_pt *out) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ const char *servId = NULL;
+ status = serviceReference_getProperty(reference, "service.id", &servId);
+ if (status != CELIX_SUCCESS) {
+ logHelper_log(helper, OSGI_LOGSERVICE_WARNING, "Cannot find service.id for ref");
+ }
+
+ export_registration_pt reg = NULL;
+ if (status == CELIX_SUCCESS) {
+ reg = calloc(1, sizeof(*reg));
+ if (reg == NULL) {
+ status = CELIX_ENOMEM;
+ }
+ }
+
+
+ if (status == CELIX_SUCCESS) {
+ reg->context = context;
+ reg->exportReference.endpoint = endpoint;
+ reg->exportReference.reference = reference;
+ reg->closed = false;
+
+ celixThreadMutex_create(®->mutex, NULL);
+ }
+
+ const char *exports = NULL;
+ CELIX_DO_IF(status, serviceReference_getProperty(reference, (char *) OSGI_RSA_SERVICE_EXPORTED_INTERFACES, &exports));
+
+ bundle_pt bundle = NULL;
+ CELIX_DO_IF(status, serviceReference_getBundle(reference, &bundle));
+
+ FILE *descriptor = NULL;
+ if (status == CELIX_SUCCESS) {
+ status = dfi_findDescriptor(context, bundle, exports, &descriptor);
+ }
+
+ if (status != CELIX_SUCCESS || descriptor == NULL) {
+ status = CELIX_BUNDLE_EXCEPTION;
+ logHelper_log(helper, OSGI_LOGSERVICE_ERROR, "Cannot find/open descriptor for '%s'", exports);
+ }
+
+ if (status == CELIX_SUCCESS) {
+ int rc = dynInterface_parse(descriptor, ®->intf);
+ fclose(descriptor);
+ if (rc != 0) {
+ status = CELIX_BUNDLE_EXCEPTION;
+ logHelper_log(helper, OSGI_LOGSERVICE_WARNING, "RSA: Error parsing service descriptor.");
+ }
+ else{
+ /* Add the interface version as a property in the properties_map */
+ char* intfVersion = NULL;
+ dynInterface_getVersionString(reg->intf, &intfVersion);
+ const char *serviceVersion = properties_get(endpoint->properties,(char*) CELIX_FRAMEWORK_SERVICE_VERSION);
+ if(serviceVersion!=NULL){
+ if(strcmp(serviceVersion,intfVersion)!=0){
+ logHelper_log(helper, OSGI_LOGSERVICE_WARNING, "Service version (%s) and interface version from the descriptor (%s) are not the same!",serviceVersion,intfVersion);
+ }
+ }
+ else{
+ properties_set(endpoint->properties, (char*) CELIX_FRAMEWORK_SERVICE_VERSION, intfVersion);
+ }
+ }
+ }
+
+ if (status == CELIX_SUCCESS) {
+ service_tracker_customizer_pt cust = NULL;
+ status = serviceTrackerCustomizer_create(reg, NULL, (void *) exportRegistration_addServ, NULL,
+ (void *) exportRegistration_removeServ, &cust);
+ if (status == CELIX_SUCCESS) {
+ char filter[32];
+ snprintf(filter, 32, "(service.id=%s)", servId);
+ status = serviceTracker_createWithFilter(reg->context, filter, cust, ®->tracker);
+ }
+ }
+
+ if (status == CELIX_SUCCESS) {
+ *out = reg;
+ } else {
+ logHelper_log(helper, OSGI_LOGSERVICE_ERROR, "Error creating export registration");
+ exportRegistration_destroy(reg);
+ }
+
+ return status;
+}
+
+celix_status_t exportRegistration_call(export_registration_pt export, char *data, int datalength, char **responseOut, int *responseLength) {
+ int status = CELIX_SUCCESS;
+
+ //printf("calling for '%s'\n");
+
+ *responseLength = -1;
+ celixThreadMutex_lock(&export->mutex);
+ status = jsonRpc_call(export->intf, export->service, data, responseOut);
+ celixThreadMutex_unlock(&export->mutex);
+
+ return status;
+}
+
+void exportRegistration_destroy(export_registration_pt reg) {
+ if (reg != NULL) {
+ if (reg->intf != NULL) {
+ dyn_interface_type *intf = reg->intf;
+ reg->intf = NULL;
+ dynInterface_destroy(intf);
+ }
+
+ if (reg->exportReference.endpoint != NULL) {
+ endpoint_description_pt ep = reg->exportReference.endpoint;
+ reg->exportReference.endpoint = NULL;
+ endpointDescription_destroy(ep);
+ }
+ if (reg->tracker != NULL) {
+ serviceTracker_destroy(reg->tracker);
+ }
+ celixThreadMutex_destroy(®->mutex);
+
+ free(reg);
+ }
+}
+
+celix_status_t exportRegistration_start(export_registration_pt reg) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ serviceTracker_open(reg->tracker);
+ return status;
+}
+
+
+celix_status_t exportRegistration_stop(export_registration_pt reg) {
+ celix_status_t status = CELIX_SUCCESS;
+ if (status == CELIX_SUCCESS) {
+ status = bundleContext_ungetServiceReference(reg->context, reg->exportReference.reference);
+ serviceTracker_close(reg->tracker);
+ }
+ return status;
+}
+
+static void exportRegistration_addServ(export_registration_pt reg, service_reference_pt ref, void *service) {
+ celixThreadMutex_lock(®->mutex);
+ reg->service = service;
+ celixThreadMutex_unlock(®->mutex);
+}
+
+static void exportRegistration_removeServ(export_registration_pt reg, service_reference_pt ref, void *service) {
+ celixThreadMutex_lock(®->mutex);
+ if (reg->service == service) {
+ reg->service = NULL;
+ }
+ celixThreadMutex_unlock(®->mutex);
+}
+
+
+celix_status_t exportRegistration_close(export_registration_pt reg) {
+ celix_status_t status = CELIX_SUCCESS;
+ exportRegistration_stop(reg);
+ return status;
+}
+
+
+celix_status_t exportRegistration_getException(export_registration_pt registration) {
+ celix_status_t status = CELIX_SUCCESS;
+ //TODO
+ return status;
+}
+
+celix_status_t exportRegistration_getExportReference(export_registration_pt registration, export_reference_pt *out) {
+ celix_status_t status = CELIX_SUCCESS;
+ export_reference_pt ref = calloc(1, sizeof(*ref));
+ if (ref != NULL) {
+ ref->endpoint = registration->exportReference.endpoint;
+ ref->reference = registration->exportReference.reference;
+ } else {
+ status = CELIX_ENOMEM;
+ }
+
+ if (status == CELIX_SUCCESS) {
+ *out = ref;
+ }
+
+ return status;
+}
+
+celix_status_t exportReference_getExportedEndpoint(export_reference_pt reference, endpoint_description_pt *endpoint) {
+ celix_status_t status = CELIX_SUCCESS;
+ *endpoint = reference->endpoint;
+ return status;
+}
+
+celix_status_t exportReference_getExportedService(export_reference_pt reference, service_reference_pt *ref) {
+ celix_status_t status = CELIX_SUCCESS;
+ *ref = reference->reference;
+ return status;
+}
+
+
+
http://git-wip-us.apache.org/repos/asf/celix/blob/2a670f26/remote_services/remote_service_admin_dfi/rsa/src/export_registration_dfi.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/src/export_registration_dfi.h b/remote_services/remote_service_admin_dfi/rsa/src/export_registration_dfi.h
new file mode 100644
index 0000000..93f37ba
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/rsa/src/export_registration_dfi.h
@@ -0,0 +1,38 @@
+/**
+ *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.
+ */
+
+#ifndef CELIX_EXPORT_REGISTRATION_DFI_H
+#define CELIX_EXPORT_REGISTRATION_DFI_H
+
+
+#include "export_registration.h"
+#include "log_helper.h"
+#include "endpoint_description.h"
+
+celix_status_t exportRegistration_create(log_helper_pt helper, service_reference_pt reference, endpoint_description_pt endpoint, bundle_context_pt context, export_registration_pt *registration);
+celix_status_t exportRegistration_close(export_registration_pt registration);
+void exportRegistration_destroy(export_registration_pt registration);
+
+celix_status_t exportRegistration_start(export_registration_pt registration);
+celix_status_t exportRegistration_stop(export_registration_pt registration);
+
+celix_status_t exportRegistration_call(export_registration_pt export, char *data, int datalength, char **response, int *responseLength);
+
+
+#endif //CELIX_EXPORT_REGISTRATION_DFI_H
http://git-wip-us.apache.org/repos/asf/celix/blob/2a670f26/remote_services/remote_service_admin_dfi/rsa/src/import_registration_dfi.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/src/import_registration_dfi.c b/remote_services/remote_service_admin_dfi/rsa/src/import_registration_dfi.c
new file mode 100644
index 0000000..0b8dcf7
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/rsa/src/import_registration_dfi.c
@@ -0,0 +1,402 @@
+/**
+ *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.
+ */
+
+#include <stdlib.h>
+#include <jansson.h>
+#include <json_rpc.h>
+#include <assert.h>
+#include "version.h"
+#include "json_serializer.h"
+#include "dyn_interface.h"
+#include "import_registration.h"
+#include "import_registration_dfi.h"
+
+struct import_registration {
+ bundle_context_pt context;
+ endpoint_description_pt endpoint; //TODO owner? -> free when destroyed
+ const char *classObject; //NOTE owned by endpoint
+ version_pt version;
+
+ celix_thread_mutex_t mutex; //protects send & sendhandle
+ send_func_type send;
+ void *sendHandle;
+
+ service_factory_pt factory;
+ service_registration_pt factoryReg;
+
+ hash_map_pt proxies; //key -> bundle, value -> service_proxy
+ celix_thread_mutex_t proxiesMutex; //protects proxies
+};
+
+struct service_proxy {
+ dyn_interface_type *intf;
+ void *service;
+ size_t count;
+};
+
+static celix_status_t importRegistration_createProxy(import_registration_pt import, bundle_pt bundle,
+ struct service_proxy **proxy);
+static void importRegistration_proxyFunc(void *userData, void *args[], void *returnVal);
+static void importRegistration_destroyProxy(struct service_proxy *proxy);
+static void importRegistration_clearProxies(import_registration_pt import);
+
+celix_status_t importRegistration_create(bundle_context_pt context, endpoint_description_pt endpoint, const char *classObject, const char* serviceVersion,
+ import_registration_pt *out) {
+ celix_status_t status = CELIX_SUCCESS;
+ import_registration_pt reg = calloc(1, sizeof(*reg));
+
+ if (reg != NULL) {
+ reg->factory = calloc(1, sizeof(*reg->factory));
+ }
+
+ if (reg != NULL && reg->factory != NULL) {
+ reg->context = context;
+ reg->endpoint = endpoint;
+ reg->classObject = classObject;
+ reg->proxies = hashMap_create(NULL, NULL, NULL, NULL);
+
+ celixThreadMutex_create(®->mutex, NULL);
+ celixThreadMutex_create(®->proxiesMutex, NULL);
+ status = version_createVersionFromString((char*)serviceVersion,&(reg->version));
+
+ reg->factory->handle = reg;
+ reg->factory->getService = (void *)importRegistration_getService;
+ reg->factory->ungetService = (void *)importRegistration_ungetService;
+ } else {
+ status = CELIX_ENOMEM;
+ }
+
+ if (status == CELIX_SUCCESS) {
+ //printf("IMPORT REGISTRATION IS %p\n", reg);
+ *out = reg;
+ }
+ else{
+ importRegistration_destroy(reg);
+ }
+
+ return status;
+}
+
+
+celix_status_t importRegistration_setSendFn(import_registration_pt reg,
+ send_func_type send,
+ void *handle) {
+ celixThreadMutex_lock(®->mutex);
+ reg->send = send;
+ reg->sendHandle = handle;
+ celixThreadMutex_unlock(®->mutex);
+
+ return CELIX_SUCCESS;
+}
+
+static void importRegistration_clearProxies(import_registration_pt import) {
+ if (import != NULL) {
+ pthread_mutex_lock(&import->proxiesMutex);
+ if (import->proxies != NULL) {
+ hash_map_iterator_pt iter = hashMapIterator_create(import->proxies);
+ while (hashMapIterator_hasNext(iter)) {
+ hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+ struct service_proxy *proxy = hashMapEntry_getValue(entry);
+ importRegistration_destroyProxy(proxy);
+ }
+ hashMapIterator_destroy(iter);
+ }
+ pthread_mutex_unlock(&import->proxiesMutex);
+ }
+}
+
+void importRegistration_destroy(import_registration_pt import) {
+ if (import != NULL) {
+ if (import->proxies != NULL) {
+ hashMap_destroy(import->proxies, false, false);
+ import->proxies = NULL;
+ }
+
+ pthread_mutex_destroy(&import->mutex);
+ pthread_mutex_destroy(&import->proxiesMutex);
+
+ if (import->factory != NULL) {
+ free(import->factory);
+ }
+
+ if(import->version!=NULL){
+ version_destroy(import->version);
+ }
+ free(import);
+ }
+}
+
+celix_status_t importRegistration_start(import_registration_pt import) {
+ celix_status_t status = CELIX_SUCCESS;
+ if (import->factoryReg == NULL && import->factory != NULL) {
+ properties_pt props = NULL;
+ properties_copy(import->endpoint->properties, &props);
+ status = bundleContext_registerServiceFactory(import->context, (char *)import->classObject, import->factory, props, &import->factoryReg);
+ } else {
+ status = CELIX_ILLEGAL_STATE;
+ }
+ return status;
+}
+
+celix_status_t importRegistration_stop(import_registration_pt import) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ if (import->factoryReg != NULL) {
+ serviceRegistration_unregister(import->factoryReg);
+ import->factoryReg = NULL;
+ }
+
+ importRegistration_clearProxies(import);
+
+ return status;
+}
+
+
+celix_status_t importRegistration_getService(import_registration_pt import, bundle_pt bundle, service_registration_pt registration, void **out) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ /*
+ module_pt module = NULL;
+ char *name = NULL;
+ bundle_getCurrentModule(bundle, &module);
+ module_getSymbolicName(module, &name);
+ printf("getting service for bundle '%s'\n", name);
+ */
+
+
+ pthread_mutex_lock(&import->proxiesMutex);
+ struct service_proxy *proxy = hashMap_get(import->proxies, bundle);
+ if (proxy == NULL) {
+ status = importRegistration_createProxy(import, bundle, &proxy);
+ if (status == CELIX_SUCCESS) {
+ hashMap_put(import->proxies, bundle, proxy);
+ }
+ }
+
+ if (status == CELIX_SUCCESS) {
+ proxy->count += 1;
+ *out = proxy->service;
+ }
+ pthread_mutex_unlock(&import->proxiesMutex);
+
+ return status;
+}
+
+static celix_status_t importRegistration_createProxy(import_registration_pt import, bundle_pt bundle, struct service_proxy **out) {
+ celix_status_t status;
+ dyn_interface_type* intf = NULL;
+ FILE *descriptor = NULL;
+
+ status = dfi_findDescriptor(import->context, bundle, import->classObject, &descriptor);
+
+ if (status != CELIX_SUCCESS || descriptor == NULL) {
+ //TODO use log helper logHelper_log(helper, OSGI_LOGSERVICE_ERROR, "Cannot find/open descriptor for '%s'", import->classObject);
+ fprintf(stderr, "RSA_DFI: Cannot find/open descriptor for '%s'", import->classObject);
+ return CELIX_BUNDLE_EXCEPTION;
+ }
+
+ if (status == CELIX_SUCCESS) {
+ int rc = dynInterface_parse(descriptor, &intf);
+ fclose(descriptor);
+ if (rc != 0 || intf==NULL) {
+ return CELIX_BUNDLE_EXCEPTION;
+ }
+ }
+
+ /* Check if the imported service version is compatible with the one in the consumer descriptor */
+ version_pt consumerVersion = NULL;
+ bool isCompatible = false;
+ dynInterface_getVersion(intf,&consumerVersion);
+ version_isCompatible(consumerVersion,import->version,&isCompatible);
+
+ if(!isCompatible){
+ char* cVerString = NULL;
+ char* pVerString = NULL;
+ version_toString(consumerVersion,&cVerString);
+ version_toString(import->version,&pVerString);
+ printf("Service version mismatch: consumer has %s, provider has %s. NOT creating proxy.\n",cVerString,pVerString);
+ dynInterface_destroy(intf);
+ free(cVerString);
+ free(pVerString);
+ status = CELIX_SERVICE_EXCEPTION;
+ }
+
+ struct service_proxy *proxy = NULL;
+ if (status == CELIX_SUCCESS) {
+ proxy = calloc(1, sizeof(*proxy));
+ if (proxy == NULL) {
+ status = CELIX_ENOMEM;
+ }
+ }
+
+ if (status == CELIX_SUCCESS) {
+ proxy->intf = intf;
+ size_t count = dynInterface_nrOfMethods(proxy->intf);
+ proxy->service = calloc(1 + count, sizeof(void *));
+ if (proxy->service == NULL) {
+ status = CELIX_ENOMEM;
+ }
+ }
+
+ if (status == CELIX_SUCCESS) {
+ void **serv = proxy->service;
+ serv[0] = import;
+
+ struct methods_head *list = NULL;
+ dynInterface_methods(proxy->intf, &list);
+ struct method_entry *entry = NULL;
+ void (*fn)(void) = NULL;
+ int index = 0;
+ TAILQ_FOREACH(entry, list, entries) {
+ int rc = dynFunction_createClosure(entry->dynFunc, importRegistration_proxyFunc, entry, &fn);
+ serv[index + 1] = fn;
+ index += 1;
+
+ if (rc != 0) {
+ status = CELIX_BUNDLE_EXCEPTION;
+ break;
+ }
+ }
+ }
+
+ if (status == CELIX_SUCCESS) {
+ *out = proxy;
+ } else if (proxy != NULL) {
+ if (proxy->intf != NULL) {
+ dynInterface_destroy(proxy->intf);
+ proxy->intf = NULL;
+ }
+ free(proxy->service);
+ free(proxy);
+ }
+
+ return status;
+}
+
+static void importRegistration_proxyFunc(void *userData, void *args[], void *returnVal) {
+ int status = CELIX_SUCCESS;
+ struct method_entry *entry = userData;
+ import_registration_pt import = *((void **)args[0]);
+
+ if (import == NULL || import->send == NULL) {
+ status = CELIX_ILLEGAL_ARGUMENT;
+ }
+
+
+ char *invokeRequest = NULL;
+ if (status == CELIX_SUCCESS) {
+ status = jsonRpc_prepareInvokeRequest(entry->dynFunc, entry->id, args, &invokeRequest);
+ //printf("Need to send following json '%s'\n", invokeRequest);
+ }
+
+
+ if (status == CELIX_SUCCESS) {
+ char *reply = NULL;
+ int rc = 0;
+ //printf("sending request\n");
+ celixThreadMutex_lock(&import->mutex);
+ if (import->send != NULL) {
+ import->send(import->sendHandle, import->endpoint, invokeRequest, &reply, &rc);
+ }
+ celixThreadMutex_unlock(&import->mutex);
+ //printf("request sended. got reply '%s' with status %i\n", reply, rc);
+
+ if (rc == 0) {
+ //fjprintf("Handling reply '%s'\n", reply);
+ status = jsonRpc_handleReply(entry->dynFunc, reply, args);
+ }
+
+ *(int *) returnVal = rc;
+
+ free(invokeRequest); //Allocated by json_dumps in jsonRpc_prepareInvokeRequest
+ free(reply); //Allocated by json_dumps in remoteServiceAdmin_send through curl call
+ }
+
+ if (status != CELIX_SUCCESS) {
+ //TODO log error
+ }
+}
+
+celix_status_t importRegistration_ungetService(import_registration_pt import, bundle_pt bundle, service_registration_pt registration, void **out) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ assert(import != NULL);
+ assert(import->proxies != NULL);
+
+ pthread_mutex_lock(&import->proxiesMutex);
+
+ struct service_proxy *proxy = hashMap_get(import->proxies, bundle);
+ if (proxy != NULL) {
+ if (*out == proxy->service) {
+ proxy->count -= 1;
+ } else {
+ status = CELIX_ILLEGAL_ARGUMENT;
+ }
+
+ if (proxy->count == 0) {
+ hashMap_remove(import->proxies, bundle);
+ importRegistration_destroyProxy(proxy);
+ }
+ }
+
+ pthread_mutex_unlock(&import->proxiesMutex);
+
+ return status;
+}
+
+static void importRegistration_destroyProxy(struct service_proxy *proxy) {
+ if (proxy != NULL) {
+ if (proxy->intf != NULL) {
+ dynInterface_destroy(proxy->intf);
+ }
+ if (proxy->service != NULL) {
+ free(proxy->service);
+ }
+ free(proxy);
+ }
+}
+
+
+celix_status_t importRegistration_close(import_registration_pt registration) {
+ celix_status_t status = CELIX_SUCCESS;
+ importRegistration_stop(registration);
+ return status;
+}
+
+celix_status_t importRegistration_getException(import_registration_pt registration) {
+ celix_status_t status = CELIX_SUCCESS;
+ //TODO
+ return status;
+}
+
+celix_status_t importRegistration_getImportReference(import_registration_pt registration, import_reference_pt *reference) {
+ celix_status_t status = CELIX_SUCCESS;
+ //TODO
+ return status;
+}
+
+celix_status_t importReference_getImportedEndpoint(import_reference_pt reference) {
+ celix_status_t status = CELIX_SUCCESS;
+ return status;
+}
+
+celix_status_t importReference_getImportedService(import_reference_pt reference) {
+ celix_status_t status = CELIX_SUCCESS;
+ return status;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/2a670f26/remote_services/remote_service_admin_dfi/rsa/src/import_registration_dfi.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/src/import_registration_dfi.h b/remote_services/remote_service_admin_dfi/rsa/src/import_registration_dfi.h
new file mode 100644
index 0000000..aac4bc7
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/rsa/src/import_registration_dfi.h
@@ -0,0 +1,44 @@
+/**
+ *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.
+ */
+
+#ifndef CELIX_IMPORT_REGISTRATION_DFI_H
+#define CELIX_IMPORT_REGISTRATION_DFI_H
+
+#include "import_registration.h"
+#include "dfi_utils.h"
+
+#include <celix_errno.h>
+
+typedef void (*send_func_type)(void *handle, endpoint_description_pt endpointDescription, char *request, char **reply, int* replyStatus);
+
+celix_status_t importRegistration_create(bundle_context_pt context, endpoint_description_pt description, const char *classObject, const char* serviceVersion,
+ import_registration_pt *import);
+celix_status_t importRegistration_close(import_registration_pt import);
+void importRegistration_destroy(import_registration_pt import);
+
+celix_status_t importRegistration_setSendFn(import_registration_pt reg,
+ send_func_type,
+ void *handle);
+celix_status_t importRegistration_start(import_registration_pt import);
+celix_status_t importRegistration_stop(import_registration_pt import);
+
+celix_status_t importRegistration_getService(import_registration_pt import, bundle_pt bundle, service_registration_pt registration, void **service);
+celix_status_t importRegistration_ungetService(import_registration_pt import, bundle_pt bundle, service_registration_pt registration, void **service);
+
+#endif //CELIX_IMPORT_REGISTRATION_DFI_H
http://git-wip-us.apache.org/repos/asf/celix/blob/2a670f26/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_activator.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_activator.c b/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_activator.c
new file mode 100644
index 0000000..d4cc765
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_activator.c
@@ -0,0 +1,124 @@
+/**
+ *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_activator.c
+ *
+ * \date Sep 30, 2011
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+#include <stdlib.h>
+#include <remote_service_admin.h>
+
+#include "remote_service_admin_dfi.h"
+
+#include "bundle_activator.h"
+#include "service_registration.h"
+
+#include "export_registration_dfi.h"
+#include "import_registration_dfi.h"
+
+struct activator {
+ remote_service_admin_pt admin;
+ remote_service_admin_service_pt adminService;
+ service_registration_pt registration;
+};
+
+celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) {
+ celix_status_t status = CELIX_SUCCESS;
+ struct activator *activator;
+
+ activator = calloc(1, sizeof(*activator));
+ if (!activator) {
+ status = CELIX_ENOMEM;
+ } else {
+ activator->admin = NULL;
+ activator->registration = NULL;
+
+ *userData = activator;
+ }
+
+ return status;
+}
+
+celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
+ celix_status_t status = CELIX_SUCCESS;
+ struct activator *activator = userData;
+ remote_service_admin_service_pt remoteServiceAdmin = NULL;
+
+ status = remoteServiceAdmin_create(context, &activator->admin);
+ if (status == CELIX_SUCCESS) {
+ remoteServiceAdmin = calloc(1, sizeof(*remoteServiceAdmin));
+ if (!remoteServiceAdmin) {
+ status = CELIX_ENOMEM;
+ } else {
+ remoteServiceAdmin->admin = activator->admin;
+ remoteServiceAdmin->exportService = remoteServiceAdmin_exportService;
+
+ remoteServiceAdmin->getExportedServices = remoteServiceAdmin_getExportedServices;
+ remoteServiceAdmin->getImportedEndpoints = remoteServiceAdmin_getImportedEndpoints;
+ remoteServiceAdmin->importService = remoteServiceAdmin_importService;
+
+ remoteServiceAdmin->exportReference_getExportedEndpoint = exportReference_getExportedEndpoint;
+ remoteServiceAdmin->exportReference_getExportedService = exportReference_getExportedService;
+
+ remoteServiceAdmin->exportRegistration_close = remoteServiceAdmin_removeExportedService;
+ remoteServiceAdmin->exportRegistration_getException = exportRegistration_getException;
+ remoteServiceAdmin->exportRegistration_getExportReference = exportRegistration_getExportReference;
+
+ remoteServiceAdmin->importReference_getImportedEndpoint = importReference_getImportedEndpoint;
+ remoteServiceAdmin->importReference_getImportedService = importReference_getImportedService;
+
+ remoteServiceAdmin->importRegistration_close = remoteServiceAdmin_removeImportedService;
+ remoteServiceAdmin->importRegistration_getException = importRegistration_getException;
+ remoteServiceAdmin->importRegistration_getImportReference = importRegistration_getImportReference;
+
+ status = bundleContext_registerService(context, OSGI_RSA_REMOTE_SERVICE_ADMIN, remoteServiceAdmin, NULL, &activator->registration);
+ activator->adminService = remoteServiceAdmin;
+ }
+ }
+
+ return status;
+}
+
+celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) {
+ celix_status_t status = CELIX_SUCCESS;
+ struct activator *activator = userData;
+
+ serviceRegistration_unregister(activator->registration);
+ activator->registration = NULL;
+
+ remoteServiceAdmin_stop(activator->admin);
+ remoteServiceAdmin_destroy(&activator->admin);
+
+ free(activator->adminService);
+
+ return status;
+}
+
+celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) {
+ celix_status_t status = CELIX_SUCCESS;
+ struct activator *activator = userData;
+
+ free(activator);
+
+ return status;
+}
+
+