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, &registration);
+            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, &reg);
+      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, &registration_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(&registration_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;
+}
+
+