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 2015/05/31 20:34:24 UTC
[1/2] celix git commit: CELIX-237: initial drop. Contains a ffi based
rsa.
Repository: celix
Updated Branches:
refs/heads/feature/CELIX-237_rsa-ffi [created] 387f7792d
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/remote_service_admin_http_ffi/private/src/remote_service_admin_impl.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_http_ffi/private/src/remote_service_admin_impl.c b/remote_services/remote_service_admin_http_ffi/private/src/remote_service_admin_impl.c
new file mode 100644
index 0000000..ac54e8d
--- /dev/null
+++ b/remote_services/remote_service_admin_http_ffi/private/src/remote_service_admin_impl.c
@@ -0,0 +1,1085 @@
+/**
+ *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 <sys/socket.h>
+#include <netdb.h>
+#include <ifaddrs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <uuid/uuid.h>
+
+#include <curl/curl.h>
+
+#include <ffi.h>
+#include <jansson.h>
+
+#include "export_registration_impl.h"
+#include "import_registration_impl.h"
+#include "remote_service_admin_impl.h"
+#include "remote_constants.h"
+#include "constants.h"
+#include "utils.h"
+#include "bundle_context.h"
+#include "bundle.h"
+#include "service_reference.h"
+#include "service_registration.h"
+#include "log_helper.h"
+#include "log_service.h"
+#include "celix_threads.h"
+#include "civetweb.h"
+#include "log_helper.h"
+#include "endpoint_description.h"
+
+// defines how often the webserver is restarted (with an increased port number)
+#define MAX_NUMBER_OF_RESTARTS 5
+
+typedef void (*GEN_FUNC_TYPE)(void);
+
+struct generic_service_layout {
+ void *handle;
+ GEN_FUNC_TYPE functions[];
+};
+
+struct proxy {
+ remote_service_admin_pt admin;
+ char *sig;
+ int index;
+ ffi_cif cif;
+ ffi_closure *closure;
+ endpoint_description_pt endpointDescription
+};
+
+
+
+
+
+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;
+ hash_map_pt importedServices;
+
+ char *port;
+ char *ip;
+
+ struct mg_context *ctx;
+};
+
+struct post {
+ const char *readptr;
+ int size;
+};
+
+struct get {
+ char *writeptr;
+ int size;
+};
+
+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, char *interface, endpoint_description_pt *description);
+
+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);
+
+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;
+ char *port = NULL;
+ char *ip = NULL;
+ char *detectedIp = NULL;
+ (*admin)->context = context;
+ (*admin)->exportedServices = hashMap_create(NULL, NULL, NULL, NULL);
+ (*admin)->importedServices = hashMap_create(NULL, NULL, NULL, NULL);
+
+ celixThreadMutex_create(&(*admin)->exportedServicesLock, NULL);
+ celixThreadMutex_create(&(*admin)->importedServicesLock, NULL);
+
+ if (logHelper_create(context, &(*admin)->loghelper) == CELIX_SUCCESS) {
+ logHelper_start((*admin)->loghelper);
+ }
+
+ bundleContext_getProperty(context, "RSA_PORT", &port);
+ if (port == NULL) {
+ port = (char *)DEFAULT_PORT;
+ }
+
+ bundleContext_getProperty(context, "RSA_IP", &ip);
+ if (ip == NULL) {
+ char *interface = NULL;
+
+ bundleContext_getProperty(context, "RSA_INTERFACE", &interface);
+ if ((interface != NULL) && (remoteServiceAdmin_getIpAdress(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 = (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;
+
+ do {
+ char newPort[10];
+ const char *options[] = { "listening_ports", port, 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 {
+ char* endptr = port;
+ int currentPort = strtol(port, &endptr, 10);
+
+ errno = 0;
+
+ 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);
+
+ *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);
+ exportRegistration_stopTracking(export);
+ }
+ }
+ hashMapIterator_destroy(iter);
+ celixThreadMutex_unlock(&admin->exportedServicesLock);
+
+ celixThreadMutex_lock(&admin->importedServicesLock);
+
+ iter = hashMapIterator_create(admin->importedServices);
+ while (hashMapIterator_hasNext(iter))
+ {
+ hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+
+ import_registration_factory_pt importFactory = hashMapEntry_getValue(entry);
+
+ if (importFactory != NULL) {
+ int i;
+ for (i = 0; i < arrayList_size(importFactory->registrations); i++)
+ {
+ import_registration_pt importRegistration = arrayList_get(importFactory->registrations, i);
+
+ if (importFactory->trackedFactory != NULL)
+ {
+ importFactory->trackedFactory->unregisterProxyService(importFactory->trackedFactory->factory, importRegistration->endpointDescription);
+ }
+ }
+
+ serviceTracker_close(importFactory->proxyFactoryTracker);
+ importRegistrationFactory_close(importFactory);
+
+ hashMapIterator_remove(iter);
+ importRegistrationFactory_destroy(&importFactory);
+ }
+ }
+ hashMapIterator_destroy(iter);
+ 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);
+ hashMap_destroy(admin->importedServices, false, false);
+
+ 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) {
+
+static int remoteServiceAdmin_callback(struct mg_connection *conn) {
+ int result = 0; // 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';
+ long serviceId = atol(service);
+
+ 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);
+ if (serviceId == check->endpointDescription->serviceId) {
+ export = check;
+ break;
+ }
+ }
+ }
+ 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;
+
+ //FIXME assuming add signature (add(double, double) : double)
+ /*TODO
+ export->endpoint->handleRequest(export->endpoint->endpoint, data, &response);
+ */
+
+
+ //retreive schema.
+ char *schema = NULL;
+ schema = properties_get(export->endpointDescription->properties, "protocol.schema");
+ printf("RSA: got schema %s\n", schema);
+
+
+ printf("Parsing data: %s\n", data);
+ json_error_t error;
+ json_t *js_request = json_loads(data, 0, &error);
+ const char *sig;
+ if (js_request) {
+ if (json_unpack(js_request, "{s:s}", "m", &sig) != 0) {
+ printf("RSA: Got error '%s'\n", error.text);
+ }
+ } else {
+ printf("RSA: got error '%s' for '%s'\n", error.text, data);
+ return 0;
+ }
+
+ printf("RSA: Looking for method %s\n", sig);
+
+ json_t *js_schema = json_loads(schema, 0, &error);
+ int methodIndex = -1;
+ if (js_schema) {
+ //TODO parse schema and create cif
+ size_t index;
+ json_t *value;
+ json_array_foreach(js_schema, index, value) {
+ if (strcmp(sig, json_string_value(value)) == 0) {
+ //found match
+ methodIndex = index;
+ break;
+ }
+ }
+ } else {
+ printf("RSA: got error '%s' for '%s'\n", error.text, schema);
+ return 0;
+ }
+
+ if (methodIndex < 0) {
+ printf("RSA: cannot find method '%s'\n", sig);
+ return 1;
+ }
+
+ size_t sigLength = strlen(sig);
+ char provArgs[sigLength];
+ bool startFound = false;
+ int i = 0;
+ int argIndex = 0;
+ for (; i < sigLength; i += 1) {
+ if (!startFound) {
+ if (sig[i] == '(') {
+ startFound = true;
+ }
+ } else {
+ if (sig[i] != ')') {
+ provArgs[argIndex++] = sig[i];
+ }
+ }
+ }
+ provArgs[argIndex] = '\0';
+ size_t provArgsLength = strlen(provArgs) -1;
+ printf("method index is %i and args are '%s'\n", methodIndex, provArgs);
+
+
+ //FFI part
+ ffi_cif cif;
+ ffi_type *argTypes[provArgsLength + 2]; //e.g. void *handle (extra), double a, double b, double *result (extra)
+ void *valuePointers[provArgsLength + 2];
+ //note assuming doubles!!
+ double values[provArgsLength];
+ double result = 0.0;
+ double *resultPointer = &result;
+ int rvalue = 0;
+
+ argTypes[0] = &ffi_type_pointer;
+ argTypes[provArgsLength +1] = &ffi_type_pointer; //last argument is return value, handled as a pointer
+ for (i = 0; i < provArgsLength; i += 1) {
+ //FIXME for now assuming double as arguments
+ argTypes[i+1] = &ffi_type_double;
+ }
+
+ valuePointers[0] = NULL;
+ valuePointers[provArgsLength+1] = &resultPointer;
+ for (i = 0; i < provArgsLength; i += 1) {
+ values[i] = 0.0;
+ valuePointers[i+1] = &(values[i]);
+ }
+
+ json_t *arguments = json_object_get(js_request, "a");
+ json_t *value;
+ size_t index;
+ json_array_foreach(arguments, index, value) {
+ values[index] = json_real_value(value); //setting values, again assuming double
+ }
+
+ json_decref(js_schema);
+ json_decref(js_request);
+
+ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, provArgsLength + 2,
+ &ffi_type_sint, argTypes) == FFI_OK)
+ {
+ printf("RSA: FFI PREP OK\n");
+
+ //TRYING TO CALL Calculate service
+ void *service = NULL;
+ bundleContext_getService(rsa->context, export->reference, &service);
+ if (service == NULL) {
+ printf("RSA: Ouch service is NULL\n");
+ return 0;
+ } else {
+ printf("RSA: service ok\n");
+ }
+
+ struct generic_service_layout *serv = service;
+
+ printf("RSA:Trying to call service using ffi\n");
+ valuePointers[0] = serv->handle;
+ ffi_call(&cif, serv->functions[methodIndex], &rvalue, valuePointers);
+ printf("RSA: Done calling service through ffi, got value %f\n", result);
+
+ json_t *resultRoot;
+ resultRoot = json_pack("{s:f}", "r", result);
+ response = json_dumps(resultRoot, 0);
+ json_decref(resultRoot);
+ }
+
+ if (response != NULL) {
+ mg_write(conn, data_response_headers, strlen(data_response_headers));
+// mg_write(conn, no_content_response_headers, strlen(no_content_response_headers));
+ mg_write(conn, response, strlen(response));
+// mg_send_data(conn, response, strlen(response));
+// mg_write_data(conn, response, strlen(response));
+
+ free(response);
+ } else {
+ mg_write(conn, no_content_response_headers, strlen(no_content_response_headers));
+ }
+ result = 0;
+
+ free(data);
+ } else {
+ //TODO log warning
+ }
+
+ celixThreadMutex_unlock(&rsa->exportedServicesLock);
+
+ }
+ }
+
+ return 1;
+}
+
+celix_status_t remoteServiceAdmin_handleRequest(remote_service_admin_pt rsa, char *service, char *data, char **reply) {
+ celixThreadMutex_lock(&rsa->exportedServicesLock);
+
+ 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 export = arrayList_get(exports, expIt);
+ if (strcmp(service, export->endpointDescription->service) == 0) {
+ export->endpoint->handleRequest(export->endpoint->endpoint, data, reply);
+ }
+ }
+ }
+ hashMapIterator_destroy(iter);
+
+ celixThreadMutex_unlock(&rsa->exportedServicesLock);
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t remoteServiceAdmin_exportService(remote_service_admin_pt admin, char *serviceId, properties_pt properties, array_list_pt *registrations) {
+ celix_status_t status = CELIX_SUCCESS;
+ 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);
+
+ bundleContext_getServiceReferences(admin->context, NULL, filter, &references); //FIXME not safe
+
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "RSA: exportService called for serviceId %s", serviceId);
+
+ if (arrayList_size(references) >= 1) {
+ reference = arrayList_get(references, 0);
+ }
+
+ if(references!=NULL){
+ arrayList_destroy(references);
+ }
+
+ if (reference == NULL) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "ERROR: expected a reference for service id %s.", serviceId);
+ return CELIX_ILLEGAL_STATE;
+ }
+
+ char *exports = NULL;
+ char *provided = NULL;
+ char *schema = NULL;
+ serviceReference_getProperty(reference, (char *) OSGI_RSA_SERVICE_EXPORTED_INTERFACES, &exports);
+ serviceReference_getProperty(reference, (char *) OSGI_FRAMEWORK_OBJECTCLASS, &provided);
+ serviceReference_getProperty(reference, (char *) "protocol.schema", &schema);
+
+ if (exports == NULL || provided == NULL) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_WARNING, "RSA: No Services to export.");
+ status = CELIX_ILLEGAL_STATE;
+ } else {
+ if (schema == NULL) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_WARNING, "RSA: no protocol.schema found.");
+ status = CELIX_ILLEGAL_STATE;
+ } else {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Export service (%s)", provided);
+
+ char *interface = provided;
+ endpoint_description_pt endpoint = NULL;
+ export_registration_pt registration = NULL;
+
+ remoteServiceAdmin_createEndpointDescription(admin, reference, interface, &endpoint);
+ printf("RSA: Creating export registration with endpoint pointer %p\n", endpoint);
+ exportRegistration_create(admin->loghelper, reference, endpoint, admin, admin->context, ®istration);
+ arrayList_add(*registrations, registration);
+
+ exportRegistration_open(registration);
+ exportRegistration_startTracking(registration);
+
+ celixThreadMutex_lock(&admin->exportedServicesLock);
+ hashMap_put(admin->exportedServices, reference, *registrations);
+ celixThreadMutex_unlock(&admin->exportedServicesLock);
+ }
+ }
+ return status;
+}
+
+celix_status_t remoteServiceAdmin_removeExportedService(export_registration_pt registration) {
+ celix_status_t status = CELIX_SUCCESS;
+ remote_service_admin_pt admin = registration->rsa;
+
+ celixThreadMutex_lock(&admin->exportedServicesLock);
+
+ hashMap_remove(admin->exportedServices, registration->reference);
+
+ celixThreadMutex_unlock(&admin->exportedServicesLock);
+
+ return status;
+}
+
+static celix_status_t remoteServiceAdmin_createEndpointDescription(remote_service_admin_pt admin, service_reference_pt reference, 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];
+ 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);
+ printf("Added property '%s' with value '%s'\n", 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);
+ 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);
+
+
+
+ *endpoint = calloc(1, sizeof(**endpoint));
+ if (!*endpoint) {
+ status = CELIX_ENOMEM;
+ } else {
+ (*endpoint)->id = properties_get(endpointProperties, (char*) OSGI_RSA_ENDPOINT_ID);
+ char *serviceId = NULL;
+ serviceReference_getProperty(reference, (char*) OSGI_FRAMEWORK_SERVICE_ID, &serviceId);
+ (*endpoint)->serviceId = strtoull(serviceId, NULL, 0);
+ (*endpoint)->frameworkUUID = properties_get(endpointProperties, (char*) OSGI_RSA_ENDPOINT_FRAMEWORK_UUID);
+ (*endpoint)->service = interface;
+ (*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);
+
+ 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;
+}
+
+
+static int remoteServiceAdmin_remoteFunctionProxy(ffi_cif *cif, int *ret, void* args[], void *userData); //TODO MOVE
+static int remoteServiceAdmin_remoteFunctionProxy(ffi_cif *cif, int *ret, void* args[], void *userData) {
+ void **handle = args[0];
+ remote_service_admin_pt admin = (*handle);
+
+ struct proxy *proxy = userData;
+
+ printf("ffi closure got called for method sig %s with index %i\n", proxy->sig, proxy->index);
+
+ json_t *root = json_object();
+ json_t *sig = json_string(proxy->sig);
+ json_object_set(root, "m", sig);
+
+ json_t *arguments = json_array();
+ int i;
+ for (i = 1; i < proxy->cif.nargs -1; i += 1) {
+ //NOTE assuming double
+ double *dval = args[i];
+ json_t *value = json_real(*dval);
+ json_array_append(arguments, value);
+ }
+ json_object_set(root, "a", arguments);
+
+ char *data = json_dumps(root, 0);
+ char *reply = NULL;
+ int replyStatus;
+
+ remoteServiceAdmin_send(proxy->admin, proxy->endpointDescription, data, &reply, &replyStatus);
+ (*ret) = replyStatus;
+ printf("got reply from server '%s'\n", reply);
+
+ json_error_t error;
+ json_t *js_reply = json_loads(reply, JSON_DECODE_ANY, &error);
+ if (js_reply) {
+ //note assuming double
+ double **result = args[proxy->cif.nargs - 1];
+ json_unpack(js_reply, "{s:f}", "r", *result);
+ json_decref(js_reply);
+ } else {
+ printf("PROXY: got error '%s' for '%s'\n", error.text, reply);
+ }
+
+ json_decref(root);
+
+ free(data);
+ free(reply);
+
+ return 0;
+}
+
+
+celix_status_t remoteServiceAdmin_importService(remote_service_admin_pt admin, endpoint_description_pt endpointDescription, import_registration_pt *registration) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Import service %s", endpointDescription->service);
+
+ char *schema = properties_get(endpointDescription->properties, "protocol.schema");
+ if (schema == NULL) {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_WARNING, "RSA: protocol schema not found for endpoint\n");
+ return CELIX_SUCCESS;
+ }
+
+ printf("protocol.schema is '%s'\n", schema);
+ json_error_t error;
+ json_t *js_schema = json_loads(schema, 0, &error);
+ if (js_schema) {
+ //TODO parse schema and create cif
+ size_t numOfMethods = json_array_size(js_schema);
+ printf("RSA: num of method for proxy is %i\n", (int) numOfMethods);
+
+ struct generic_service_layout *service = calloc(1, sizeof(*service) + (numOfMethods-1) * sizeof(GEN_FUNC_TYPE));
+ service->handle = admin;
+
+ //struct generic_service_layout {
+ // void *handle;
+ // GEN_FUNC_TYPE functions[];
+ //};
+
+ size_t index;
+ json_t *value;
+ json_array_foreach(js_schema, index, value) {
+ //create closure
+
+ char *sig = json_string_value(value);
+ size_t sigLength = strlen(sig);
+ char provArgs[sigLength];
+ bool startFound = false;
+ int i = 0;
+ int argIndex = 0;
+ for (; i < sigLength; i += 1) {
+ if (!startFound) {
+ if (sig[i] == '(') {
+ startFound = true;
+ }
+ } else {
+ if (sig[i] != ')') {
+ provArgs[argIndex++] = sig[i];
+ }
+ }
+ }
+ provArgs[argIndex] = '\0';
+ printf("method index is %i and args are '%s'\n", index, provArgs);
+
+ int provArgLength = strlen(provArgs) -1;
+
+ struct proxy *proxy = malloc(sizeof(*proxy));
+ proxy->admin = admin;
+ proxy->sig = strdup(sig);
+ proxy->index = index;
+ proxy->endpointDescription = endpointDescription;
+
+ ffi_type **args = calloc(provArgLength +2, sizeof(ffi_type)); //TODO test if this can be on the stack
+
+ void (*function)(void);
+ proxy->closure = ffi_closure_alloc(sizeof(ffi_closure), &function);
+ service->functions[index] = function;
+
+ /* Initialize the argument info vectors */
+ args[0] = &ffi_type_pointer;
+ args[provArgLength + 1] = &ffi_type_pointer;
+ for (i = 0; i < provArgLength; i += 1) {
+ args[i+1] = &ffi_type_double;
+ }
+
+ if (proxy->closure) {
+ if (ffi_prep_cif(&proxy->cif, FFI_DEFAULT_ABI, provArgLength + 2, &ffi_type_sint, args) == FFI_OK) {
+ if (ffi_prep_closure_loc(proxy->closure, &proxy->cif, remoteServiceAdmin_remoteFunctionProxy, proxy, function) == FFI_OK) {
+ printf("RSA: created closure for method '%s'\n", sig);
+ }
+ }
+ }
+ }
+
+ //TODO register with imported properties
+ char *objectClass = properties_get(endpointDescription->properties, "objectClass");
+ service_registration_pt reg = NULL;
+ bundleContext_registerService(admin->context, objectClass, service, NULL, ®);
+ printf("registered proxy service with objectclass '%s'\n", objectClass);
+
+ } else {
+ printf("RSA: got error '%s' for '%s'\n", error.text, schema);
+ return CELIX_ILLEGAL_STATE;
+ }
+
+
+ //celixThreadMutex_lock(&admin->importedServicesLock);
+ //celixThreadMutex_unlock(&admin->importedServicesLock);
+
+
+ return status;
+ /*
+
+ celixThreadMutex_lock(&admin->importedServicesLock);
+
+ import_registration_factory_pt registration_factory = (import_registration_factory_pt) hashMap_get(admin->importedServices, endpointDescription->service);
+
+ // check whether we already have a registration_factory registered in the hashmap
+ if (registration_factory == NULL)
+ {
+ status = importRegistrationFactory_install(admin->loghelper, endpointDescription->service, admin->context, ®istration_factory);
+ if (status == CELIX_SUCCESS) {
+ hashMap_put(admin->importedServices, endpointDescription->service, registration_factory);
+ }
+ }
+
+ // factory available
+ if (status != CELIX_SUCCESS || (registration_factory->trackedFactory == NULL))
+ {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_WARNING, "RSA: no proxyFactory available.");
+ if (status == CELIX_SUCCESS) {
+ status = CELIX_SERVICE_EXCEPTION;
+ }
+ }
+ else
+ {
+ // we create an importRegistration per imported service
+ importRegistration_create(endpointDescription, admin, (sendToHandle) &remoteServiceAdmin_send, admin->context, registration);
+ registration_factory->trackedFactory->registerProxyService(registration_factory->trackedFactory->factory, endpointDescription, admin, (sendToHandle) &remoteServiceAdmin_send);
+
+ arrayList_add(registration_factory->registrations, *registration);
+ }
+
+ celixThreadMutex_unlock(&admin->importedServicesLock);
+
+
+ return status;
+ */
+}
+
+
+celix_status_t remoteServiceAdmin_removeImportedService(remote_service_admin_pt admin, import_registration_pt registration) {
+ celix_status_t status = CELIX_SUCCESS;
+ return status;
+ /*
+
+ endpoint_description_pt endpointDescription = (endpoint_description_pt) registration->endpointDescription;
+ import_registration_factory_pt registration_factory = NULL;
+
+ celixThreadMutex_lock(&admin->importedServicesLock);
+
+ registration_factory = (import_registration_factory_pt) hashMap_get(admin->importedServices, endpointDescription->service);
+
+ // factory available
+ if ((registration_factory == NULL) || (registration_factory->trackedFactory == NULL))
+ {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "RSA: Error while retrieving registration factory for imported service %s", endpointDescription->service);
+ }
+ else
+ {
+ registration_factory->trackedFactory->unregisterProxyService(registration_factory->trackedFactory->factory, endpointDescription);
+ arrayList_removeElement(registration_factory->registrations, registration);
+ importRegistration_destroy(registration);
+
+ if (arrayList_isEmpty(registration_factory->registrations))
+ {
+ logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA: closing proxy.");
+
+ serviceTracker_close(registration_factory->proxyFactoryTracker);
+ importRegistrationFactory_close(registration_factory);
+
+ hashMap_remove(admin->importedServices, endpointDescription->service);
+
+ importRegistrationFactory_destroy(®istration_factory);
+ }
+ }
+
+ celixThreadMutex_unlock(&admin->importedServicesLock);
+
+ return status;
+ */
+}
+
+
+celix_status_t remoteServiceAdmin_send(remote_service_admin_pt rsa, endpoint_description_pt endpointDescription, char *request, char **reply, int* replyStatus) {
+
+ struct post post;
+ post.readptr = request;
+ post.size = strlen(request);
+
+ struct get get;
+ get.size = 0;
+ get.writeptr = malloc(1);
+
+ char *serviceUrl = properties_get(endpointDescription->properties, (char*) ENDPOINT_URL);
+ char url[256];
+ snprintf(url, 256, "%s", serviceUrl);
+
+ // assume the default timeout
+ int timeout = DEFAULT_TIMEOUT;
+
+ char *timeoutStr = NULL;
+ // Check if the endpoint has a timeout, if so, use it.
+ timeoutStr = 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_TIMEOUT, timeout);
+ curl_easy_setopt(curl, CURLOPT_URL, &url[0]);
+ 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);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+
+ *reply = get.writeptr;
+ *replyStatus = res;
+ }
+
+ 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;
+}
+
+
+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) {
+ celix_status_t status = CELIX_SUCCESS;
+ 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/387f7792/remote_services/topology_manager/private/src/topology_manager.c
----------------------------------------------------------------------
diff --git a/remote_services/topology_manager/private/src/topology_manager.c b/remote_services/topology_manager/private/src/topology_manager.c
index c0ec7d1..1a67b4c 100644
--- a/remote_services/topology_manager/private/src/topology_manager.c
+++ b/remote_services/topology_manager/private/src/topology_manager.c
@@ -25,6 +25,7 @@
*/
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "topology_manager.h"
#include "bundle_context.h"
@@ -228,6 +229,7 @@ celix_status_t topologyManager_rsaAdded(void * handle, service_reference_pt refe
serviceReference_getProperty(reference, (char *)OSGI_FRAMEWORK_SERVICE_ID, &serviceId);
array_list_pt endpoints = NULL;
+
status = rsa->exportService(rsa->admin, serviceId, NULL, &endpoints);
if (status == CELIX_SUCCESS) {
@@ -465,6 +467,7 @@ celix_status_t topologyManager_addExportedService(topology_manager_pt manager, s
remote_service_admin_service_pt rsa = arrayList_get(localRSAs, iter);
array_list_pt endpoints = NULL;
+
status = rsa->exportService(rsa->admin, serviceId, NULL, &endpoints);
if (status == CELIX_SUCCESS) {
@@ -529,6 +532,7 @@ celix_status_t topologyManager_getEndpointDescriptionForExportRegistration(remot
export_reference_pt reference = NULL;
status = rsa->exportRegistration_getExportReference(export, &reference);
+
if (status == CELIX_SUCCESS) {
status = rsa->exportReference_getExportedEndpoint(reference, endpoint);
}
@@ -570,8 +574,7 @@ celix_status_t topologyManager_notifyListenersEndpointAdded(topology_manager_pt
status = topologyManager_getEndpointDescriptionForExportRegistration(rsa, export, &endpoint);
if (status != CELIX_SUCCESS || !endpoint) {
continue;
- }
-
+ }
bool matchResult = false;
filter_match(filter, endpoint->properties, &matchResult);
if (matchResult) {
[2/2] celix git commit: CELIX-237: initial drop. Contains a ffi based
rsa.
Posted by pn...@apache.org.
CELIX-237: initial drop. Contains a ffi based rsa.
The rsa is still incomplete and buggy, but has a working a client server examples with proxy/endpoint.
The rsa tree also contains a dyn_type and json_serialize code which together with a provided schema can be used for dynamic type serialization.
Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/387f7792
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/387f7792
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/387f7792
Branch: refs/heads/feature/CELIX-237_rsa-ffi
Commit: 387f7792d88cc6eab1202a3e9cd48167af44058a
Parents: 3acf970
Author: Pepijn Noltes <pe...@gmail.com>
Authored: Sun May 31 20:26:19 2015 +0200
Committer: Pepijn Noltes <pe...@gmail.com>
Committed: Sun May 31 20:26:19 2015 +0200
----------------------------------------------------------------------
.gitignore | 2 +
remote_services/CMakeLists.txt | 13 +-
remote_services/dyn_type/CMakeLists.txt | 9 +
remote_services/dyn_type/dyn_type.c | 551 +++++++++
remote_services/dyn_type/dyn_type.h | 78 ++
remote_services/dyn_type/json_serializer.c | 123 ++
remote_services/dyn_type/json_serializer.h | 9 +
remote_services/dyn_type/struct_tests.c | 159 +++
.../private/src/calculator_proxy_impl.c | 2 +-
.../private/src/calculator_activator.c | 1 +
.../public/include/calculator_service.h | 31 +-
.../calculator_shell/private/src/add_command.c | 3 +-
.../calculator_shell/private/src/sqrt_command.c | 2 +-
.../calculator_shell/private/src/sub_command.c | 2 +-
remote_services/examples/deploy.cmake | 38 +-
.../private/src/export_registration_impl.c | 4 +-
.../CMakeLists.txt | 49 +
.../include/remote_service_admin_http_impl.h | 52 +
.../src/remote_service_admin_activator.c | 122 ++
.../private/src/remote_service_admin_impl.c | 1085 ++++++++++++++++++
.../private/src/topology_manager.c | 7 +-
21 files changed, 2291 insertions(+), 51 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index eb89068..f77383b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,5 @@
/.project
.DS_Store
build
+*~
+*.swp
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/CMakeLists.txt b/remote_services/CMakeLists.txt
index abb6024..9f56b58 100644
--- a/remote_services/CMakeLists.txt
+++ b/remote_services/CMakeLists.txt
@@ -33,13 +33,16 @@ if (REMOTE_SERVICE_ADMIN)
add_subdirectory(topology_manager)
- add_subdirectory(remote_service_admin)
- add_subdirectory(remote_service_admin_http)
- add_subdirectory(remote_service_admin_shm)
+ #add_subdirectory(remote_service_admin)
+ #add_subdirectory(remote_service_admin_http)
+ add_subdirectory(remote_service_admin_http_ffi)
+ #add_subdirectory(remote_service_admin_shm)
- add_subdirectory(discovery_configured)
+ #add_subdirectory(discovery_configured)
add_subdirectory(discovery_etcd)
- add_subdirectory(discovery_shm)
+ #add_subdirectory(discovery_shm)
+
+ add_subdirectory(dyn_type)
endif (REMOTE_SERVICE_ADMIN)
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/dyn_type/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/dyn_type/CMakeLists.txt b/remote_services/dyn_type/CMakeLists.txt
new file mode 100644
index 0000000..8b5b78f
--- /dev/null
+++ b/remote_services/dyn_type/CMakeLists.txt
@@ -0,0 +1,9 @@
+find_package(Jansson REQUIRED)
+
+add_executable(struct_tests
+ struct_tests.c
+ dyn_type.c
+ json_serializer.c
+)
+
+target_link_libraries(struct_tests ${JANSSON_LIBRARIES} /lib64/libffi.so )
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/dyn_type/dyn_type.c
----------------------------------------------------------------------
diff --git a/remote_services/dyn_type/dyn_type.c b/remote_services/dyn_type/dyn_type.c
new file mode 100644
index 0000000..fe4c9bc
--- /dev/null
+++ b/remote_services/dyn_type/dyn_type.c
@@ -0,0 +1,551 @@
+#include "dyn_type.h"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdbool.h>
+#include <assert.h>
+
+
+//place in dyn_type.h?
+struct generic_sequence {
+ uint32_t _cap;
+ uint32_t _len;
+ void *buf;
+};
+
+struct _dyn_type {
+ int type;
+ union {
+ struct {
+ ffi_type *ffiType;
+ } simple;
+
+ struct {
+ ffi_type ffiType;
+ char **names;
+ dyn_type **nested_types;
+ } complex;
+
+ struct {
+ ffi_type seqStruct;
+ dyn_type *dynType; //set if sequence is of a complex type
+ ffi_type *simpleType; //set if sequence is of a simple type
+ } sequence;
+ };
+};
+
+static char dynType_schemaType(dyn_type *dynType, ffi_type *ffiType);
+
+static void dynType_print_sequence(dyn_type *type, int depth);
+static void dynType_print_complex(dyn_type *type, int depth);
+static void dynType_print_any(dyn_type *type, int depth);
+
+static unsigned short get_offset_at(ffi_type *type, int index);
+static void dynType_trim(const char *str, size_t len, int *start, int *end);
+
+static int dynType_complex_create(char *schema, dyn_type **result);
+static int dynType_sequence_create(char *schema, dyn_type **result);
+static int dynType_simple_create(char t, dyn_type **result);
+
+static ffi_type* dynType_ffiType_for(char c);
+
+int dynType_create(const char *schema, dyn_type **result) {
+ //trim white space
+ int status = 0;
+ int offset, len;
+ dynType_trim(schema, strlen(schema), &offset, &len);
+
+ /*
+ char test[len+1];
+ memcpy(test, schema + offset, len);
+ test[len] = '\0';
+ printf("trimmed schema is %s\n", test);
+ */
+
+ if (schema[offset] == '{' && schema[offset + len -1] == '}') {
+ //complex
+
+ //removing prefix { and postfix }
+ offset += 1;
+ len -= 2;
+
+ int offsetType;
+ int lenType;
+ //trim again
+ dynType_trim(schema + offset, len , &offsetType, &lenType);
+
+ char type[lenType + 1];
+ memcpy(type, schema + offset + offsetType, lenType);
+ type[lenType] = '\0';
+ status = dynType_complex_create(type, result);
+ } else if (schema[offset] == '[') {
+ //sequence
+ //fixme assuming simple type
+ offset += 1; //remove [
+ len -= 1;
+ char type[len + 1];
+ memcpy(type, schema + offset, len);
+ type[len] = '\0';
+ status = dynType_sequence_create(type, result);
+ } else if (len == 1){
+ //simple
+ status = dynType_simple_create(schema[offset], result);
+ } else {
+ printf("invalid schema '%s'\n", schema);
+ }
+
+ return status;
+}
+
+static int dynType_simple_create(char t, dyn_type **result) {
+ int status = 0;
+ ffi_type *ffiType = dynType_ffiType_for(t);
+ dyn_type *simple = NULL;
+ if (ffiType != NULL) {
+ dyn_type *simple = calloc(1,sizeof(*simple));
+ simple->type = DYN_TYPE_SIMPLE;
+ simple->simple.ffiType = ffiType;
+ }
+ if (ffiType != NULL && simple != NULL) {
+ *result = simple;
+ }
+ return status;
+}
+
+static int dynType_sequence_create(char *schema, dyn_type **result) {
+ int status = 0;
+ dyn_type *type = calloc(1, sizeof(*type));
+
+ type->type = DYN_TYPE_SEQUENCE;
+ type->sequence.seqStruct.elements = calloc(4, sizeof(ffi_type));
+ type->sequence.seqStruct.elements[0] = &ffi_type_uint32; //_cap
+ type->sequence.seqStruct.elements[1] = &ffi_type_uint32; //_len
+ type->sequence.seqStruct.elements[2] = &ffi_type_pointer;
+ type->sequence.seqStruct.elements[3] = NULL;
+
+ if (schema[0] == '{') { //complex type
+ int len = strlen(schema) -2;
+ char complexSchema[len + 1];
+ memcpy(complexSchema, schema + 1, len);
+ complexSchema[len] = '\0';
+ status = dynType_complex_create(complexSchema, &type->sequence.dynType);
+ } else { //simple type
+ type->sequence.simpleType = dynType_ffiType_for(schema[0]);
+ }
+ //TODO sequence of sequence
+
+ if (status == 0) {
+ //dummy cif prep to ensure size for struct ffi_type is set
+ ffi_cif cif;
+ ffi_type *args[1];
+ args[0] = &type->sequence.seqStruct;
+ ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_uint, args);
+
+ *result = type;
+ return 0;
+ } else {
+ printf("DYN_TYPE: invalid type schema\n");
+ return 1;
+ }
+
+ return status;
+}
+
+static int dynType_complex_create(char *schema, dyn_type **result) {
+ bool valid = true;
+ size_t len = strlen(schema);
+ int i = 0;
+
+ dyn_type *type = calloc(1, sizeof(*type));
+ type->type = DYN_TYPE_COMPLEX;
+ if (type == NULL) {
+ return -1;
+ }
+
+ //count elements
+ int k;
+ size_t count = 0;
+ for (k=i; k < len && !isspace(schema[k]); k += 1) {
+ if (schema[k] == '[') {
+ k += 1;
+ } else if (schema[k] == '{') {
+ for (; schema[k] != '}'; k += 1) ;
+ }
+ count += 1;
+ }
+
+ type->complex.ffiType.elements = calloc(count + 1, sizeof(ffi_type));
+ type->complex.nested_types = calloc(count + 1, sizeof(dyn_type *));
+ int index = 0;
+ for (k=0; k+i < len && !isspace(schema[k+i]); k += 1, index += 1) {
+ if (schema[k+i] == '[') { //sequence
+ //FIXME assume simple type
+ dyn_type *seqType;
+ char seq[2];
+ seq[0] = schema[k+i+1];
+ seq[1] = '\0';
+ dynType_sequence_create(seq, &seqType);
+
+ type->complex.nested_types[index] = seqType;
+ type->complex.ffiType.elements[index] = &seqType->sequence.seqStruct;
+ k += 1;
+ } else if (schema[k+i] == '{') { //nested complex
+ int start = k+i;
+ int end;
+ for (; schema[k+i] != '}' && k+i < len; k +=1) ;
+ if (schema[k+i] == '}') {
+ end = k+i;
+ size_t len = end-start + 1 -2; //without {}
+ char nested[len+1];
+ memcpy(nested, schema + start + 1, len);
+ nested[len] = '\0';
+ dyn_type *nestedType = NULL;
+ dynType_complex_create(nested, &nestedType); //TODO use status result
+ type->complex.nested_types[index] = nestedType;
+ type->complex.ffiType.elements[index] = &ffi_type_pointer;
+ } else {
+ printf("invalid schema. object not closed '%s'\n", schema);
+ }
+ } else {
+ ffi_type *elType = NULL;
+ elType = dynType_ffiType_for(schema[k+i]);
+ if (elType != NULL) {
+ type->complex.ffiType.elements[index] = elType;
+ } else {
+ valid=false;
+ }
+ }
+ }
+
+
+ //eat { and }
+ int j;
+ int nrOfBraces = 0;
+ for (j = 0; j < len; j += 1) { //TODO make safer
+ if (isspace(schema[j]) && nrOfBraces == 0) {
+ break;
+ }
+ if (schema[j] == '{') {
+ nrOfBraces += 1;
+ } else if (schema[j] == '}') {
+ nrOfBraces -=1 ;
+ }
+ }
+
+ char *names = schema + j +1;
+
+ type->complex.names = calloc(count, sizeof(char *));
+ k = 0;
+ char *savePtr;
+ char *token = NULL;
+ token = strtok_r(names, " ", &savePtr);
+ while (token != NULL && k < count) {
+ type->complex.names[k] = strdup(token);
+ k += 1;
+ token = strtok_r(NULL, " ", &savePtr);
+ }
+ if ( k != count || token != NULL) {
+ valid =false;
+ }
+
+ if (valid) {
+ //dummy cif prep to ensure size for struct ffi_type is set
+ ffi_cif cif;
+ ffi_type *args[1];
+ args[0] = &type->complex.ffiType;
+ ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_uint, args);
+
+ *result = type;
+ return 0;
+ } else {
+ printf("DYN_TYPE: invalid type schema '%s'\n", schema);
+ return 1;
+ }
+}
+
+int dynType_destroy(dyn_type *type) {
+ //TODO
+ return 0;
+}
+
+void * dynType_alloc(dyn_type *type) {
+ assert(type != NULL);
+ void *result = NULL;
+ switch(type->type) {
+ case DYN_TYPE_COMPLEX :
+ result = calloc(1, type->complex.ffiType.size);
+ break;
+ case DYN_TYPE_SEQUENCE :
+ result = calloc(1, type->sequence.seqStruct.size);
+ break;
+ case DYN_TYPE_SIMPLE :
+ result = calloc(1, type->simple.ffiType->size);
+ break;
+ default :
+ printf("DYN_TYPE: unsupported type %i\n", type->type);
+ break;
+ }
+ return result;
+}
+
+static ffi_type* dynType_ffiType_for(char c) {
+ ffi_type *type = NULL;
+ switch (c) {
+ case 'F' :
+ type = &ffi_type_float;
+ break;
+ case 'D' :
+ type = &ffi_type_double;
+ break;
+ case 'B' :
+ type = &ffi_type_sint8;
+ break;
+ case 'S' :
+ type = &ffi_type_sint16;
+ break;
+ case 'I' :
+ type = &ffi_type_sint32;
+ break;
+ case 'J' :
+ type = &ffi_type_sint64;
+ break;
+ default:
+ printf("unsupported type %c\n", c);
+ }
+ return type;
+}
+
+static unsigned short get_offset_at(ffi_type *type, int index) {
+ unsigned short offset = 0;
+
+ int i;
+ for (i = 0; i <= index && type->elements[i] != NULL; i += 1) {
+ size_t size = type->elements[i]->size;
+ unsigned short alignment = type->elements[i]->alignment;
+ int alignment_diff = offset % alignment;
+ if (alignment_diff > 0) {
+ offset += (alignment - alignment_diff);
+ }
+ if (i < index) {
+ offset += size;
+ }
+ }
+
+ //TODO check if last element is not reached
+
+ return offset;
+}
+
+int dynType_complex_set_value_at(dyn_type *type, int index, void *start, void *in) {
+ assert(type->type == DYN_TYPE_COMPLEX);
+ char *loc = ((char *)start) + get_offset_at(&type->complex.ffiType, index);
+ size_t size = type->complex.ffiType.elements[index]->size;
+ memcpy(loc, in, size);
+ return 0;
+}
+
+int dynType_complex_index_for_name(dyn_type *type, const char *name) {
+ assert(type->type == DYN_TYPE_COMPLEX);
+ int i;
+ int index = -1;
+ for (i = 0; type->complex.ffiType.elements[i] != NULL; i += 1) {
+ if (strcmp(type->complex.names[i], name) == 0) {
+ index = i;
+ break;
+ }
+ }
+ return index;
+}
+
+char dynType_complex_schemaType_at(dyn_type *complexType, int index) {
+ assert(complexType->type == DYN_TYPE_COMPLEX);
+
+ ffi_type *type = complexType->complex.ffiType.elements[index];
+ dyn_type *nestedType = complexType->complex.nested_types[index];
+
+ return dynType_schemaType(nestedType, type);
+}
+
+static char dynType_schemaType(dyn_type *dynType, ffi_type *ffiType) {
+ char result = '\0';
+ if (dynType != NULL) {
+ switch(dynType->type) {
+ case DYN_TYPE_SIMPLE :
+ result = dynType_schemaType(NULL, dynType->simple.ffiType);
+ break;
+ case DYN_TYPE_COMPLEX :
+ result = '{';
+ break;
+ case DYN_TYPE_SEQUENCE :
+ result = '[';
+ break;
+ }
+ } else if (ffiType != NULL) {
+ switch(ffiType->type) {
+ case FFI_TYPE_FLOAT :
+ result = 'F';
+ break;
+ case FFI_TYPE_DOUBLE :
+ result = 'D';
+ break;
+ case FFI_TYPE_SINT8 :
+ result = 'B';
+ break;
+ case FFI_TYPE_SINT16 :
+ result = 'S';
+ break;
+ case FFI_TYPE_SINT32 :
+ result = 'I';
+ break;
+ case FFI_TYPE_SINT64 :
+ result = 'J';
+ break;
+ default :
+ printf("Unsurported ffi type encounted. ffi type is %u\n", ffiType->type);
+ }
+ }
+ return result;
+}
+
+dyn_type * dynType_complex_dynType_at(dyn_type *type, int index) {
+ assert(type->type == DYN_TYPE_COMPLEX);
+ return type->complex.nested_types[index];
+}
+
+void * dynType_complex_val_loc_at(dyn_type *type, void *inst_loc, int index) {
+ assert(type->type == DYN_TYPE_COMPLEX);
+ char *l = inst_loc;
+ return (void *)(l + get_offset_at(&type->complex.ffiType, index));
+}
+
+int dynType_simple_set_value(dyn_type *type, void *typeLoc, void *in) {
+ //TODO
+ return 0;
+}
+
+static void dynType_print_sequence(dyn_type *type, int depth) {
+ assert(type->type == DYN_TYPE_SEQUENCE);
+ static const char const *SEQ_NAMES[] = {"_cap", "_len", "buf"};
+
+ int i;
+ for (i = 0; i < 3 ; i += 1) {
+ int k;
+ for (k = 0; k < depth; k += 1) {
+ printf("\t");
+ }
+ printf("element %i with name '%s': size is %zu, allignment is %i and offset is %i\n", i,
+ SEQ_NAMES[i], type->sequence.seqStruct.elements[i]->size, type->sequence.seqStruct.elements[i]->alignment, get_offset_at(&type->sequence.seqStruct, i));
+ }
+}
+
+static void dynType_print_complex(dyn_type *type, int depth) {
+ assert(type->type == DYN_TYPE_COMPLEX);
+ int i, k;
+ for (k = 0; k < depth; k += 1) {
+ printf("\t");
+ }
+ printf("printing ffi type. size is %zu, allignment is %i :\n", type->complex.ffiType.size, type->complex.ffiType.alignment);
+ for (i = 0; type->complex.ffiType.elements[i] != NULL; i += 1) {
+ for (k = 0; k < depth; k += 1) {
+ printf("\t");
+ }
+ printf(" element %i with name '%s': size is %zu, allignment is %i and offset is %i\n", i,
+ type->complex.names[i], type->complex.ffiType.elements[i]->size, type->complex.ffiType.elements[i]->alignment, get_offset_at(&type->complex.ffiType, i));
+ if (type->complex.nested_types[i] != NULL) {
+ dynType_print_any(type->complex.nested_types[i], depth + 1);
+ }
+ }
+}
+
+static void dynType_print_any(dyn_type *type, int depth) {
+ switch (type->type) {
+ case DYN_TYPE_COMPLEX :
+ dynType_print_complex(type, depth);
+ break;
+ case DYN_TYPE_SEQUENCE :
+ dynType_print_sequence(type, depth);
+ break;
+ default :
+ printf("Unsurported dyn type %i\n", type->type);
+ }
+}
+
+void dynType_print(dyn_type *type) {
+ dynType_print_any(type, 0);
+}
+
+size_t dynType_size(dyn_type *type) {
+ assert(type != NULL);
+ size_t size = 0;
+ switch (type->type) {
+ case DYN_TYPE_COMPLEX :
+ size = type->complex.ffiType.size;
+ break;
+ case DYN_TYPE_SEQUENCE :
+ size = type->sequence.seqStruct.size;
+ break;
+ case DYN_TYPE_SIMPLE :
+ size = type->simple.ffiType->size;
+ break;
+ default :
+ printf("Error unsupported type %i\n", type->type);
+ break;
+ }
+ return size;
+}
+
+int dynType_type(dyn_type *type) {
+ return type->type;
+}
+
+static void dynType_trim(const char *str, size_t strLen, int *offset, int *len) {
+ int i;
+ for (i = 0; i < strLen && isspace(str[i]); i += 1) {
+ ;
+ }
+ *offset = i;
+
+ for (i = strLen-1; i >= 0 && isspace(str[i]); i -= 1) {
+ ;
+ }
+ *len = i - (*offset) + 1;
+}
+
+
+void* dynType_sequence_init(dyn_type *type, void *inst, size_t cap) {
+ assert(type->type == DYN_TYPE_SEQUENCE);
+ char *result;
+ struct generic_sequence *seq = inst;
+ if (seq != NULL) {
+ size_t size = type->sequence.simpleType != NULL ? type->sequence.simpleType->size : dynType_size(type->sequence.dynType);
+ seq->buf = calloc(cap, size);
+ seq->_cap = cap;
+ result = seq->buf;
+ }
+ return result;
+}
+
+char dynType_sequence_elementSchemaType(dyn_type *type) {
+ assert(type->type == DYN_TYPE_SEQUENCE);
+ return dynType_schemaType(type->sequence.dynType, type->sequence.simpleType);
+}
+
+int dynType_sequence_append(dyn_type *type, void *inst, void *in) {
+ int index = -1;
+ struct generic_sequence *seq = inst;
+ if (seq->_len + 1 <= seq->_cap) {
+ index = seq->_len;
+ seq->_len += 1;
+ char *buf = seq->buf;
+ size_t elSize = type->sequence.dynType != NULL ? dynType_size(type->sequence.dynType) : type->sequence.simpleType->size;
+ size_t offset = (elSize * index);
+ memcpy(buf + offset, in, elSize);
+ } else {
+ printf("DYN_TYPE: sequence out of capacity\n");
+ //todo resize ?
+ }
+ return index;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/dyn_type/dyn_type.h
----------------------------------------------------------------------
diff --git a/remote_services/dyn_type/dyn_type.h b/remote_services/dyn_type/dyn_type.h
new file mode 100644
index 0000000..5877fdf
--- /dev/null
+++ b/remote_services/dyn_type/dyn_type.h
@@ -0,0 +1,78 @@
+#ifndef __DYN_TYPE_H_
+#define __DYN_TYPE_H_
+
+#include <ffi.h>
+
+
+/*Schema description
+ *
+ * Type = SimpleType | ComplexType | ArrayType
+ * Name = alpha[(alpha|numeric)*]
+ * SPACE = ' '
+ *
+ * SimplesTypes (based on java bytecode method signatures)
+ * //Java based:
+ * B char
+ * C (not supported)
+ * D double
+ * F float
+ * I int //TODO use int32_t instead?
+ * J long //TODO use int64_t intead?
+ * S short //TODO use int16_t instead?
+ * V void
+ * Z boolean
+ * //Extended
+ * b unsigned char
+ * i unsigned int (see I)
+ * j unsigned long (see J)
+ * s unsigned short (see S)
+ * P pointer
+ * T char* string
+ *
+ *
+ * ComplexTypes
+ * {[Type]+} [(Name)(SPACE)]+
+ *
+ * SequenceType
+ * [(Type)
+ *
+ * examples
+ * "{DDII a b c d}" -> struct { double a; double b; int c; int d; };
+ * "{DD{FF c1 c2} a b c" -> struct { double a; double b; struct c { float c1; float c2; }; };
+ *
+ *
+ */
+
+#define DYN_TYPE_SIMPLE 1
+#define DYN_TYPE_COMPLEX 2
+#define DYN_TYPE_SEQUENCE 3
+
+typedef struct _dyn_type dyn_type;
+
+int dynType_create(const char *schema, dyn_type **type);
+int dynType_destroy(dyn_type *type);
+
+//generic
+void dynType_print(dyn_type *type);
+size_t dynType_size(dyn_type *type);
+int dynType_type(dyn_type *type);
+void * dynType_alloc(dyn_type *type);
+//TODO void dynType_free(dyn_type *type, void *inst);
+
+//complex
+int dynType_complex_index_for_name(dyn_type *type, const char *name);
+char dynType_complex_schemaType_at(dyn_type *type, int index);
+dyn_type * dynType_complex_dynType_at(dyn_type *type, int index);
+void * dynType_complex_val_loc_at(dyn_type *type, void *inst_loc, int index);
+int dynType_complex_set_value_at(dyn_type *type, int index, void *start_loc_type, void *in);
+
+//sequence
+void * dynType_sequence_init(dyn_type *type, void *seqInst, size_t cap); //note assume seq struct at seqLoc. only allocates buf
+char dynType_sequence_elementSchemaType(dyn_type *type);
+int dynType_sequence_append(dyn_type *type, void *inst, void *in);
+
+//simple
+int dynType_simple_set_value(dyn_type *type, void *typeLoc, void *in);
+
+
+#endif
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/dyn_type/json_serializer.c
----------------------------------------------------------------------
diff --git a/remote_services/dyn_type/json_serializer.c b/remote_services/dyn_type/json_serializer.c
new file mode 100644
index 0000000..e198445
--- /dev/null
+++ b/remote_services/dyn_type/json_serializer.c
@@ -0,0 +1,123 @@
+#include "json_serializer.h"
+
+#include <jansson.h>
+#include <assert.h>
+
+static int json_serializer_writeObject(dyn_type *type, json_t *object, void **result);
+static void json_serializer_writeObjectMember(dyn_type *type, const char *name, json_t *val, void *inst);
+static void json_serializer_writeSequence(json_t *array, dyn_type *seq, void *seqLoc);
+
+int json_deserialize(dyn_type *type, const char *input, void **result) {
+ //FIXME function is assuming complex type
+ int status = 0;
+
+
+ json_error_t error;
+ json_t *root = json_loads(input, JSON_DECODE_ANY, &error);
+
+ if (root != NULL) {
+ status = json_serializer_writeObject(type, root, result);
+ json_decref(root);
+ } else {
+ status = 1;
+ printf("JSON_SERIALIZER: error parsing json input '%s'. Error is %s\n", input, error.text);
+ }
+
+ return status;
+}
+
+static int json_serializer_writeObject(dyn_type *type, json_t *object, void **result) {
+ assert(object != NULL);
+ int status = 0;
+
+ void *inst = dynType_alloc(type);
+ json_t *value;
+ const char *key;
+
+ if (inst != NULL) {
+ json_object_foreach(object, key, value) {
+ json_serializer_writeObjectMember(type, key, value, inst);
+ }
+ *result = inst;
+ } else {
+ status = 1;
+ printf("JSON_SERIALIZER: Error allocating memory\n");
+ }
+
+ return status;
+}
+
+static void json_serializer_writeObjectMember(dyn_type *type, const char *name, json_t *val, void *inst) {
+ //TODO rename to complex. write generic write
+ int index = dynType_complex_index_for_name(type, name);
+ char charType = dynType_complex_schemaType_at(type, index);
+ void *valp = dynType_complex_val_loc_at(type, inst, index);
+
+
+ float *f;
+ double *d;
+ char *c;
+ short *s;
+ int *i;
+ long *l;
+ dyn_type *nested;
+
+ switch (charType) {
+ case 'F' :
+ f = valp;
+ *f = json_real_value(val);
+ break;
+ case 'D' :
+ d = valp;
+ *d = json_real_value(val);
+ break;
+ case 'B' :
+ c = valp;
+ *c = json_integer_value(val);
+ break;
+ case 'S' :
+ s = valp;
+ *s = json_integer_value(val);
+ break;
+ case 'I' :
+ i = valp;
+ *i = json_integer_value(val);
+ break;
+ case 'J' :
+ l = valp;
+ *l = json_integer_value(val);
+ break;
+ case '[' :
+ nested = dynType_complex_dynType_at(type, index);
+ json_serializer_writeSequence(val, nested, valp);
+ break;
+ case '{' :
+ nested = dynType_complex_dynType_at(type, index);
+ json_serializer_writeObject(nested, val, (void **)valp);
+ break;
+ default :
+ printf("JSON_SERIALIZER: error provided type '%c' not supported\n", charType);
+ printf("Skipping\n");
+ }
+}
+
+static void json_serializer_writeSequence(json_t *array, dyn_type *seq, void *seqLoc) {
+ assert(dynType_type(seq) == DYN_TYPE_SEQUENCE);
+ size_t size = json_array_size(array);
+ //char seqType = dynType_sequence_elementSchemaType(seq);
+
+ dynType_sequence_init(seq, seqLoc, size); //seq is already allocated. only need to allocate the buf
+
+ //assuming int
+ int32_t i;
+ int index;
+ json_t *val;
+ json_array_foreach(array, index, val) {
+ i = json_number_value(val);
+ dynType_sequence_append(seq, seqLoc, &i);
+ }
+}
+
+int json_serialize(dyn_type *type, void *input, char **output, size_t *size) {
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/dyn_type/json_serializer.h
----------------------------------------------------------------------
diff --git a/remote_services/dyn_type/json_serializer.h b/remote_services/dyn_type/json_serializer.h
new file mode 100644
index 0000000..edc87af
--- /dev/null
+++ b/remote_services/dyn_type/json_serializer.h
@@ -0,0 +1,9 @@
+#ifndef __JSON_SERIALIZER_H_
+#define __JSON_SERIALIZER_H_
+
+#include "dyn_type.h"
+
+int json_deserialize(dyn_type *type, const char *input, void **result);
+int json_serialize(dyn_type *type, void *input, char **output, size_t *size);
+
+#endif
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/dyn_type/struct_tests.c
----------------------------------------------------------------------
diff --git a/remote_services/dyn_type/struct_tests.c b/remote_services/dyn_type/struct_tests.c
new file mode 100644
index 0000000..ecf1fd4
--- /dev/null
+++ b/remote_services/dyn_type/struct_tests.c
@@ -0,0 +1,159 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <ffi.h>
+
+#include "dyn_type.h"
+#include "json_serializer.h"
+
+/*********** example 1 ************************/
+/** struct type ******************************/
+const char *example1_schema = "{DJISF a b c d e}";
+
+const char *example1_input = "{ \
+ \"a\" : 1.0, \
+ \"b\" : 22, \
+ \"c\" : 32, \
+ \"d\" : 42, \
+ \"e\" : 4.4 \
+}";
+
+struct example1 {
+ double a; //0
+ int64_t b; //1
+ int32_t c; //2
+ int16_t d; //3
+ float e; //4
+};
+
+void print_example1(void *data) {
+ struct example1 *ex = data;
+ printf("example1: a:%f, b:%li, c:%i, d:%i, e:%f\n", ex->a, ex->b, ex->c, ex->d, ex->e);
+}
+
+/*********** example 2 ************************/
+/** struct type with some extra whitespace*/
+const char *example2_schema = " { BJJDFD byte long1 long2 double1 float1 double2 } ";
+
+const char *example2_input = "{ \
+ \"byte\" : 42, \
+ \"long1\" : 232, \
+ \"long2\" : 242, \
+ \"double1\" : 4.2, \
+ \"float1\" : 3.2, \
+ \"double2\" : 4.4 \
+}";
+
+struct example2 {
+ char byte; //0
+ int64_t long1; //1
+ int64_t long2; //2
+ double double1; //3
+ float float1; //4
+ double double2; //5
+};
+
+void print_example2(void *data) {
+ struct example2 *ex = data;
+ printf("example2: byte:%i, long1:%li, long2:%li, double1:%f, float1:%f, double2:%f\n", ex->byte, ex->long1, ex->long2, ex->double1, ex->float1, ex->double2);
+}
+
+
+/*********** example 3 ************************/
+/** sequence with a simple type **************/
+const char *example3_schema = "{[I numbers}";
+
+const char *example3_input = "{ \
+ \"numbers\" : [22,32,42] \
+}";
+
+struct example3 {
+ struct {
+ uint32_t _cap;
+ uint32_t _len;
+ int32_t *buf;
+ } numbers;
+};
+
+void print_example3(void *data) {
+ struct example3 *ex = data;
+ printf("example3: numbers length is %u and cap is %u and pointer buf is %p\n", ex->numbers._len, ex->numbers._cap, ex->numbers.buf);
+ int i;
+ for (i = 0; i < ex->numbers._len; i += 1) {
+ printf("\telement %i : %i\n", i, ex->numbers.buf[i]);
+ }
+}
+
+/*********** example 4 ************************/
+/** structs within a struct (by reference)*******/
+//TODO think about references in schema e.g "{Lleaf;Lleaf; left right}\nleaf{IDD index val1 val2}"
+const char *example4_schema = "{{IDD index val1 val2}{IDD index val1 val2} left right}";
+
+const char *example4_input = "{ \
+ \"left\" : {\"index\":1, \"val1\":1.0, \"val2\":2.0 }, \
+ \"right\" : {\"index\":2, \"val1\":5.0, \"val2\":4.0 } \
+}";
+
+struct leaf {
+ int32_t index;
+ double val1;
+ double val2;
+};
+
+struct example4 {
+ struct leaf *left;
+ struct leaf *right;
+};
+
+void print_example4(void *data) {
+ struct example4 *ex = data;
+ printf("example4: left { index:%i, val1:%f, val2:%f }, right { index;%i, val1:%f, val2:%f }\n", ex->left->index, ex->left->val1, ex->left->val2, ex->right->index, ex->right->val1, ex->right->val2);
+}
+
+int main() {
+ printf("Starting ffi struct test\n");
+ dyn_type *type;
+ void *inst;
+
+ type = NULL;
+ inst = NULL;
+ dynType_create(example1_schema, &type);
+ printf("-- example 1\n");
+ dynType_print(type);
+ json_deserialize(type, example1_input, &inst);
+ print_example1(inst);
+ printf("--\n\n");
+
+
+ type = NULL;
+ inst = NULL;
+ dynType_create(example2_schema, &type);
+ printf("-- example 2\n");
+ dynType_print(type);
+ json_deserialize(type, example2_input, &inst);
+ print_example2(inst);
+ printf("--\n\n");
+
+ type = NULL;
+ inst = NULL;
+ dynType_create(example3_schema, &type);
+ printf("-- example 3\n");
+ dynType_print(type);
+ json_deserialize(type, example3_input, &inst);
+ print_example3(inst);
+ printf("--\n\n");
+
+ type = NULL;
+ inst = NULL;
+ dynType_create(example4_schema, &type);
+ printf("-- example 4\n");
+ dynType_print(type);
+ json_deserialize(type, example4_input, &inst);
+ print_example4(inst);
+ printf("--\n\n");
+
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/examples/calculator_proxy/private/src/calculator_proxy_impl.c
----------------------------------------------------------------------
diff --git a/remote_services/examples/calculator_proxy/private/src/calculator_proxy_impl.c b/remote_services/examples/calculator_proxy/private/src/calculator_proxy_impl.c
index fc21412..af2cfc3 100644
--- a/remote_services/examples/calculator_proxy/private/src/calculator_proxy_impl.c
+++ b/remote_services/examples/calculator_proxy/private/src/calculator_proxy_impl.c
@@ -68,7 +68,7 @@ celix_status_t calculatorProxy_add(calculator_pt calculator, double a, double b,
if (calculator->endpoint != NULL) {
json_t *root;
- root = json_pack("{s:s, s:[ff]}", "m", "add(DD)D", "a", a, b);
+ root = json_pack("{s:s, s:[fmt]}", "m", "add(DD)D", "a", a, b);
char *data = json_dumps(root, 0);
char *reply = NULL;
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/examples/calculator_service/private/src/calculator_activator.c
----------------------------------------------------------------------
diff --git a/remote_services/examples/calculator_service/private/src/calculator_activator.c b/remote_services/examples/calculator_service/private/src/calculator_activator.c
index 22f72b5..d280eaa 100644
--- a/remote_services/examples/calculator_service/private/src/calculator_activator.c
+++ b/remote_services/examples/calculator_service/private/src/calculator_activator.c
@@ -75,6 +75,7 @@ celix_status_t bundleActivator_start(void * userData, bundle_context_pt context)
properties = properties_create();
properties_set(properties, (char *) OSGI_RSA_SERVICE_EXPORTED_INTERFACES, (char *) CALCULATOR_SERVICE);
+ properties_set(properties, (char *) "protocol.schema", (char *)CALC_SCHEMA);
bundleContext_registerService(context, (char *) CALCULATOR_SERVICE, activator->service, properties, &activator->calculatorReg);
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/examples/calculator_service/public/include/calculator_service.h
----------------------------------------------------------------------
diff --git a/remote_services/examples/calculator_service/public/include/calculator_service.h b/remote_services/examples/calculator_service/public/include/calculator_service.h
index 0a802d2..3219c64 100644
--- a/remote_services/examples/calculator_service/public/include/calculator_service.h
+++ b/remote_services/examples/calculator_service/public/include/calculator_service.h
@@ -33,6 +33,31 @@ typedef struct calculator *calculator_pt;
typedef struct calculator_service *calculator_service_pt;
+#define CALC_SCHEMA "[\"add(DD)D\",\"sub(DD)D\",\"sqrt(D)D\"]"
+
+/*
+purpose different schema setup
+{
+ "methods" : [ "add(DD)D", "sub(DD)D", "sqrt(D)D", abc(Labc_input;)D", sum([D)D" ],
+ "types" : {
+ "abc_input" : "DDD a b c"
+ }
+}
+
+struct abc_input {
+ double a;
+ double b;
+ double c;
+}
+
+//for [D the following struct layout will be assumed
+struct double_sequence {
+ size_t _max;
+ size_t _length;
+ double *buffer;
+};
+*/
+
/*
* The calculator service definition corresponds to the following Java interface:
*
@@ -44,9 +69,9 @@ typedef struct calculator_service *calculator_service_pt;
*/
struct calculator_service {
calculator_pt calculator;
- celix_status_t (*add)(calculator_pt calculator, double a, double b, double *result);
- celix_status_t (*sub)(calculator_pt calculator, double a, double b, double *result);
- celix_status_t (*sqrt)(calculator_pt calculator, double a, double *result);
+ int (*add)(calculator_pt calculator, double a, double b, double *result);
+ int (*sub)(calculator_pt calculator, double a, double b, double *result);
+ int (*sqrt)(calculator_pt calculator, double a, double *result);
};
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/examples/calculator_shell/private/src/add_command.c
----------------------------------------------------------------------
diff --git a/remote_services/examples/calculator_shell/private/src/add_command.c b/remote_services/examples/calculator_shell/private/src/add_command.c
index 13071cf..260add3 100644
--- a/remote_services/examples/calculator_shell/private/src/add_command.c
+++ b/remote_services/examples/calculator_shell/private/src/add_command.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include <ctype.h>
+#include <string.h>
#include "array_list.h"
#include "bundle_context.h"
@@ -58,7 +59,7 @@ void addCommand_execute(command_pt command, char *line, void (*out)(char *), voi
status = bundleContext_getServiceReference(command->bundleContext, (char *) CALCULATOR_SERVICE, &calculatorService);
if (status == CELIX_SUCCESS) {
- char *token;
+ char *token = line;
strtok_r(line, " ", &token);
char *aStr = strtok_r(NULL, " ", &token);
bool numeric;
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/examples/calculator_shell/private/src/sqrt_command.c
----------------------------------------------------------------------
diff --git a/remote_services/examples/calculator_shell/private/src/sqrt_command.c b/remote_services/examples/calculator_shell/private/src/sqrt_command.c
index bdb809a..af770d1 100644
--- a/remote_services/examples/calculator_shell/private/src/sqrt_command.c
+++ b/remote_services/examples/calculator_shell/private/src/sqrt_command.c
@@ -58,7 +58,7 @@ void sqrtCommand_execute(command_pt command, char *line, void (*out)(char *), vo
status = bundleContext_getServiceReference(command->bundleContext, (char *) CALCULATOR_SERVICE, &calculatorService);
if (status == CELIX_SUCCESS) {
- char *token;
+ char *token = line;
strtok_r(line, " ", &token);
char *aStr = strtok_r(NULL, " ", &token);
bool numeric;
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/examples/calculator_shell/private/src/sub_command.c
----------------------------------------------------------------------
diff --git a/remote_services/examples/calculator_shell/private/src/sub_command.c b/remote_services/examples/calculator_shell/private/src/sub_command.c
index 8ba8a9e..b4dc95a 100644
--- a/remote_services/examples/calculator_shell/private/src/sub_command.c
+++ b/remote_services/examples/calculator_shell/private/src/sub_command.c
@@ -58,7 +58,7 @@ void subCommand_execute(command_pt command, char *line, void (*out)(char *), voi
status = bundleContext_getServiceReference(command->bundleContext, (char *) CALCULATOR_SERVICE, &calculatorService);
if (status == CELIX_SUCCESS) {
- char *token;
+ char *token = line;
strtok_r(line, " ", &token);
char *aStr = strtok_r(NULL, " ", &token);
bool numeric;
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/examples/deploy.cmake
----------------------------------------------------------------------
diff --git a/remote_services/examples/deploy.cmake b/remote_services/examples/deploy.cmake
index 9f254d7..0b17811 100644
--- a/remote_services/examples/deploy.cmake
+++ b/remote_services/examples/deploy.cmake
@@ -16,44 +16,10 @@
# under the License.
is_enabled(RSA_EXAMPLES)
if (RSA_EXAMPLES)
- is_enabled(RSA_REMOTE_SERVICE_ADMIN_HTTP)
- if (RSA_REMOTE_SERVICE_ADMIN_HTTP)
- is_enabled(RSA_DISCOVERY_CONFIGURED)
- if (RSA_DISCOVERY_CONFIGURED)
- deploy("remote-services-cfg" BUNDLES discovery_configured topology_manager remote_service_admin_http calculator shell shell_tui log_service log_writer
- ENDPOINTS
- org.apache.celix.calc.api.Calculator_endpoint
- org.apache.celix.calc.api.Calculator2_endpoint
- PROPERTIES
- RSA_PORT=8001
- DISCOVERY_CFG_POLL_ENDPOINTS=http://localhost:8082/org.apache.celix.discovery.configured
- DISCOVERY_CFG_SERVER_PORT=8081)
- deploy("remote-services-cfg-client" BUNDLES topology_manager remote_service_admin_http shell shell_tui log_service log_writer calculator_shell discovery_configured
- ENDPOINTS org.apache.celix.calc.api.Calculator_proxy org.apache.celix.calc.api.Calculator2_proxy
- PROPERTIES
- RSA_PORT=8002
- DISCOVERY_CFG_POLL_ENDPOINTS=http://localhost:8081/org.apache.celix.discovery.configured
- DISCOVERY_CFG_SERVER_PORT=8082)
- endif ()
- endif ()
-
- is_enabled(RSA_REMOTE_SERVICE_ADMIN_SHM)
- if (RSA_REMOTE_SERVICE_ADMIN_SHM)
- is_enabled(RSA_DISCOVERY_SHM)
- if (RSA_DISCOVERY_SHM)
- deploy("remote-services-shm" BUNDLES discovery_shm topology_manager remote_service_admin_shm calculator shell shell_tui log_service log_writer
- ENDPOINTS org.apache.celix.calc.api.Calculator_endpoint)
- deploy("remote-services-shm-client" BUNDLES topology_manager remote_service_admin_shm shell shell_tui log_service log_writer calculator_shell discovery_shm
- ENDPOINTS org.apache.celix.calc.api.Calculator_proxy)
- endif ()
- endif ()
-
is_enabled(RSA_DISCOVERY_ETCD)
if (RSA_DISCOVERY_ETCD)
- deploy("remote-services-etcd" BUNDLES discovery_etcd topology_manager remote_service_admin_http calculator shell shell_tui log_service log_writer
- ENDPOINTS org.apache.celix.calc.api.Calculator_endpoint)
- deploy("remote-services-etcd-client" BUNDLES topology_manager remote_service_admin_http shell shell_tui log_service log_writer calculator_shell discovery_etcd
- ENDPOINTS org.apache.celix.calc.api.Calculator_proxy)
+ deploy("remote-services-etcd" BUNDLES discovery_etcd topology_manager remote_service_admin_http calculator shell shell_tui log_service log_writer)
+ deploy("remote-services-etcd-client" BUNDLES topology_manager remote_service_admin_http shell shell_tui log_service log_writer calculator_shell discovery_etcd)
endif ()
endif (RSA_EXAMPLES)
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/remote_service_admin/private/src/export_registration_impl.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin/private/src/export_registration_impl.c b/remote_services/remote_service_admin/private/src/export_registration_impl.c
index 7011104..d6ce934 100644
--- a/remote_services/remote_service_admin/private/src/export_registration_impl.c
+++ b/remote_services/remote_service_admin/private/src/export_registration_impl.c
@@ -174,7 +174,8 @@ celix_status_t exportRegistration_endpointRemoved(void * handle, service_referen
}
celix_status_t exportRegistration_open(export_registration_pt registration) {
- celix_status_t status;
+ celix_status_t status = CELIX_SUCCESS;
+ /*
char *bundleStore = NULL;
bundleContext_getProperty(registration->context, BUNDLE_STORE_PROPERTY_NAME, &bundleStore);
@@ -192,6 +193,7 @@ celix_status_t exportRegistration_open(export_registration_pt registration) {
if (status == CELIX_SUCCESS) {
}
}
+ */
return status;
}
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/remote_service_admin_http_ffi/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_http_ffi/CMakeLists.txt b/remote_services/remote_service_admin_http_ffi/CMakeLists.txt
new file mode 100644
index 0000000..ea94b16
--- /dev/null
+++ b/remote_services/remote_service_admin_http_ffi/CMakeLists.txt
@@ -0,0 +1,49 @@
+# 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.
+celix_subproject(RSA_REMOTE_SERVICE_ADMIN_HTTP "Option to enable building the Remote Service Admin Service HTTP ffi" OFF)
+if (RSA_REMOTE_SERVICE_ADMIN_HTTP)
+ find_package(CURL REQUIRED)
+ find_package(Jansson REQUIRED)
+
+ include_directories(${CURL_INCLUDE_DIRS})
+ include_directories(${Jansson})
+ include_directories("${PROJECT_SOURCE_DIR}/utils/public/include")
+ include_directories("${PROJECT_SOURCE_DIR}/log_service/public/include")
+ include_directories("${PROJECT_SOURCE_DIR}/remote_services/utils/private/include")
+ include_directories("${PROJECT_SOURCE_DIR}/remote_services/utils/public/include")
+ include_directories("${PROJECT_SOURCE_DIR}/remote_services/remote_service_admin/public/include")
+ include_directories("${PROJECT_SOURCE_DIR}/remote_services/remote_service_admin/private/include")
+ include_directories("${PROJECT_SOURCE_DIR}/remote_services/remote_service_admin_http/private/include")
+ include_directories("${PROJECT_SOURCE_DIR}/remote_services/endpoint_listener/public/include")
+
+ SET_HEADER(BUNDLE_SYMBOLICNAME "apache_celix_remote_service_admin_http_ffi")
+ SET(BUNDLE_VERSION "0.0.1")
+ SET_HEADERS("Bundle-Name: Apache Celix Remote Service Admin HTTP for ffi")
+
+ bundle(remote_service_admin_http SOURCES
+ private/src/remote_service_admin_impl
+ private/src/remote_service_admin_activator
+ ${PROJECT_SOURCE_DIR}/remote_services/remote_service_admin/private/src/export_registration_impl
+ ${PROJECT_SOURCE_DIR}/remote_services/remote_service_admin/private/src/import_registration_impl
+ ${PROJECT_SOURCE_DIR}/remote_services/utils/private/src/civetweb.c
+ ${PROJECT_SOURCE_DIR}/log_service/public/src/log_helper.c
+ )
+
+ install_bundle(remote_service_admin_http)
+
+ target_link_libraries(remote_service_admin_http celix_framework ${CURL_LIBRARIES} ${JANSSON_LIBRARIES} /lib64/libffi.so )
+endif (RSA_REMOTE_SERVICE_ADMIN_HTTP)
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/remote_service_admin_http_ffi/private/include/remote_service_admin_http_impl.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_http_ffi/private/include/remote_service_admin_http_impl.h b/remote_services/remote_service_admin_http_ffi/private/include/remote_service_admin_http_impl.h
new file mode 100644
index 0000000..dbf71c9
--- /dev/null
+++ b/remote_services/remote_service_admin_http_ffi/private/include/remote_service_admin_http_impl.h
@@ -0,0 +1,52 @@
+/**
+ *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:dev@celix.apache.org">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 "remote_service_admin_impl.h"
+#include "log_helper.h"
+#include "civetweb.h"
+
+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;
+ hash_map_pt importedServices;
+
+ char *port;
+ char *ip;
+
+ struct mg_context *ctx;
+};
+
+celix_status_t remoteServiceAdmin_stop(remote_service_admin_pt admin);
+
+#endif /* REMOTE_SERVICE_ADMIN_HTTP_IMPL_H_ */
http://git-wip-us.apache.org/repos/asf/celix/blob/387f7792/remote_services/remote_service_admin_http_ffi/private/src/remote_service_admin_activator.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_http_ffi/private/src/remote_service_admin_activator.c b/remote_services/remote_service_admin_http_ffi/private/src/remote_service_admin_activator.c
new file mode 100644
index 0000000..e4125fc
--- /dev/null
+++ b/remote_services/remote_service_admin_http_ffi/private/src/remote_service_admin_activator.c
@@ -0,0 +1,122 @@
+/**
+ *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 "bundle_activator.h"
+#include "service_registration.h"
+
+#include "remote_service_admin_http_impl.h"
+#include "export_registration_impl.h"
+#include "import_registration_impl.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 = exportRegistration_close;
+ 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;
+
+ remoteServiceAdmin_stop(activator->admin);
+ serviceRegistration_unregister(activator->registration);
+ activator->registration = NULL;
+
+ 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;
+}
+
+