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 2018/05/27 18:37:12 UTC

[29/51] [partial] celix git commit: CELIX-424: Cleans up the directory structure. Moves all libraries to the libs subdir and all bundles to the bundles subdir

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_service_admin_shm/private/src/remote_service_admin_impl.c
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_service_admin_shm/private/src/remote_service_admin_impl.c b/bundles/remote_services/remote_service_admin_shm/private/src/remote_service_admin_impl.c
new file mode 100644
index 0000000..f090223
--- /dev/null
+++ b/bundles/remote_services/remote_service_admin_shm/private/src/remote_service_admin_impl.c
@@ -0,0 +1,924 @@
+/**
+ *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       Sep 14, 2013
+ *  \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 <string.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/sem.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <unistd.h>
+#include <uuid/uuid.h>
+
+#include "remote_service_admin_shm.h"
+#include "remote_service_admin_shm_impl.h"
+
+#include "export_registration_impl.h"
+#include "import_registration_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"
+
+static celix_status_t remoteServiceAdmin_lock(int semId, int semNr);
+static celix_status_t remoteServiceAdmin_unlock(int semId, int semNr);
+static int remoteServiceAdmin_getCount(int semId, int semNr);
+
+celix_status_t remoteServiceAdmin_installEndpoint(remote_service_admin_pt admin, export_registration_pt registration, service_reference_pt reference, char *interface);
+celix_status_t remoteServiceAdmin_createEndpointDescription(remote_service_admin_pt admin, service_reference_pt reference, properties_pt endpointProperties, char *interface, endpoint_description_pt *description);
+
+celix_status_t remoteServiceAdmin_createOrAttachShm(hash_map_pt ipcSegment, remote_service_admin_pt admin, endpoint_description_pt endpointDescription, bool createIfNotFound);
+celix_status_t remoteServiceAdmin_getIpcSegment(remote_service_admin_pt admin, endpoint_description_pt endpointDescription, ipc_segment_pt* ipc);
+celix_status_t remoteServiceAdmin_detachIpcSegment(ipc_segment_pt ipc);
+celix_status_t remoteServiceAdmin_deleteIpcSegment(ipc_segment_pt ipc);
+
+celix_status_t remoteServiceAdmin_getSharedIdentifierFile(remote_service_admin_pt admin, char *fwUuid, char* servicename, char* outFile);
+celix_status_t remoteServiceAdmin_removeSharedIdentityFile(remote_service_admin_pt admin, char *fwUuid, char* servicename);
+celix_status_t remoteServiceAdmin_removeSharedIdentityFiles(remote_service_admin_pt admin);
+
+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 {
+		(*admin)->context = context;
+		(*admin)->exportedServices = hashMap_create(NULL, NULL, NULL, NULL);
+		(*admin)->importedServices = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
+		(*admin)->exportedIpcSegment = hashMap_create(NULL, NULL, NULL, NULL);
+		(*admin)->importedIpcSegment = hashMap_create(NULL, NULL, NULL, NULL);
+		(*admin)->pollThread = hashMap_create(NULL, NULL, NULL, NULL);
+		(*admin)->pollThreadRunning = hashMap_create(NULL, NULL, NULL, NULL);
+
+		if (logHelper_create(context, &(*admin)->loghelper) == CELIX_SUCCESS) {
+			logHelper_start((*admin)->loghelper);
+		}
+	}
+
+	return status;
+}
+
+celix_status_t remoteServiceAdmin_destroy(remote_service_admin_pt* admin) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	hashMap_destroy((*admin)->exportedServices, false, false);
+	hashMap_destroy((*admin)->importedServices, false, false);
+	hashMap_destroy((*admin)->exportedIpcSegment, false, false);
+	hashMap_destroy((*admin)->importedIpcSegment, false, false);
+	hashMap_destroy((*admin)->pollThread, false, false);
+	hashMap_destroy((*admin)->pollThreadRunning, false, false);
+
+	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);
+
+		char* service = hashMapEntry_getKey(entry);
+		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);
+
+			hashMap_remove(admin->importedServices, service);
+			importRegistrationFactory_destroy(&importFactory);
+		}
+	}
+	hashMapIterator_destroy(iter);
+	celixThreadMutex_unlock(&admin->importedServicesLock);
+
+	// set stop-thread-variable
+	iter = hashMapIterator_create(admin->pollThreadRunning);
+	while (hashMapIterator_hasNext(iter)) {
+		bool *pollThreadRunning = hashMapIterator_nextValue(iter);
+		*pollThreadRunning = false;
+	}
+	hashMapIterator_destroy(iter);
+
+	// release lock
+	iter = hashMapIterator_create(admin->exportedIpcSegment);
+	while (hashMapIterator_hasNext(iter)) {
+		ipc_segment_pt ipc = hashMapIterator_nextValue(iter);
+		remoteServiceAdmin_unlock(ipc->semId, 1);
+	}
+	hashMapIterator_destroy(iter);
+
+	// wait till threads has stopped
+	iter = hashMapIterator_create(admin->pollThread);
+	while (hashMapIterator_hasNext(iter)) {
+		celix_thread_t *pollThread = hashMapIterator_nextValue(iter);
+
+		if (pollThread != NULL) {
+			status = celixThread_join(*pollThread, NULL);
+		}
+	}
+	hashMapIterator_destroy(iter);
+
+	iter = hashMapIterator_create(admin->importedIpcSegment);
+	while (hashMapIterator_hasNext(iter)) {
+		ipc_segment_pt ipc = hashMapIterator_nextValue(iter);
+		remoteServiceAdmin_detachIpcSegment(ipc);
+		free(ipc);
+	}
+	hashMapIterator_destroy(iter);
+
+	iter = hashMapIterator_create(admin->exportedIpcSegment);
+	while (hashMapIterator_hasNext(iter)) {
+		ipc_segment_pt ipc = hashMapIterator_nextValue(iter);
+		remoteServiceAdmin_deleteIpcSegment(ipc);
+		free(ipc);
+	}
+	hashMapIterator_destroy(iter);
+
+	remoteServiceAdmin_removeSharedIdentityFiles(admin);
+
+	logHelper_stop(admin->loghelper);
+	logHelper_destroy(&admin->loghelper);
+	return status;
+}
+
+static int remoteServiceAdmin_getCount(int semId, int semNr) {
+	int token = -1;
+	unsigned short semVals[3];
+	union semun semArg;
+
+	semArg.array = semVals;
+
+	if (semctl(semId, 0, GETALL, semArg) == 0) {
+		token = semArg.array[semNr];
+	}
+
+	return token;
+}
+
+static celix_status_t remoteServiceAdmin_lock(int semId, int semNr) {
+	celix_status_t status = CELIX_SUCCESS;
+	int semOpStatus = 0;
+	struct sembuf semOperation;
+
+	semOperation.sem_num = semNr;
+	semOperation.sem_op = -1;
+	semOperation.sem_flg = 0;
+
+	do {
+		status = CELIX_SUCCESS;
+
+		if ((semOpStatus = semop(semId, &semOperation, 1)) != 0) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	} while (semOpStatus == -1 && errno == EINTR);
+
+	return status;
+}
+
+static celix_status_t remoteServiceAdmin_unlock(int semId, int semNr) {
+	celix_status_t status = CELIX_SUCCESS;
+	int semOpStatus = 0;
+	struct sembuf semOperation;
+
+	semOperation.sem_num = semNr;
+	semOperation.sem_op = 1;
+	semOperation.sem_flg = 0;
+
+	do {
+		status = CELIX_SUCCESS;
+
+		if ((semOpStatus = semop(semId, &semOperation, 1)) != 0) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	} while (semOpStatus == -1 && errno == EINTR);
+
+	return status;
+}
+
+celix_status_t remoteServiceAdmin_send(remote_service_admin_pt admin, endpoint_description_pt recpEndpoint, char *request, char **reply, int *replyStatus) {
+	celix_status_t status = CELIX_SUCCESS;
+	ipc_segment_pt ipc = NULL;
+
+	if ((ipc = hashMap_get(admin->importedIpcSegment, recpEndpoint->service)) != NULL) {
+		int semid = ipc->semId;
+
+		/* lock critical area */
+		remoteServiceAdmin_lock(semid, 0);
+
+		/* write method and data */
+		strcpy(ipc->shmBaseAdress, request);
+
+		/* Check the status of the send-receive semaphore and reset them if not correct */
+		if (remoteServiceAdmin_getCount(ipc->semId, 1) > 0) {
+			semctl(semid, 1, SETVAL, (int) 0);
+		}
+		if (remoteServiceAdmin_getCount(ipc->semId, 2) > 0) {
+			semctl(semid, 2, SETVAL, (int) 0);
+		}
+
+		/* Inform receiver we are invoking the remote service */
+		remoteServiceAdmin_unlock(semid, 1);
+
+		/* Wait until the receiver finished his operations */
+		remoteServiceAdmin_lock(semid, 2);
+
+		/* read reply */
+		*reply = strdup(ipc->shmBaseAdress);
+
+		/* TODO: fix replyStatus */
+		*replyStatus = 0;
+
+		/* release critical area */
+		remoteServiceAdmin_unlock(semid, 0);
+
+	} else {
+		status = CELIX_ILLEGAL_STATE; /* could not find ipc segment */
+	}
+
+	return status;
+}
+
+static void * remoteServiceAdmin_receiveFromSharedMemory(void *data) {
+	recv_shm_thread_pt thread_data = data;
+
+	remote_service_admin_pt admin = thread_data->admin;
+	endpoint_description_pt exportedEndpointDesc = thread_data->endpointDescription;
+
+	ipc_segment_pt ipc;
+
+	if ((ipc = hashMap_get(admin->exportedIpcSegment, exportedEndpointDesc->service)) != NULL) {
+		bool *pollThreadRunning = hashMap_get(admin->pollThreadRunning, exportedEndpointDesc);
+
+		while (*pollThreadRunning == true) {
+			if ((remoteServiceAdmin_lock(ipc->semId, 1) == CELIX_SUCCESS) && (*pollThreadRunning == true)) {
+
+				// TODO: align data size
+				char *data = calloc(1024, sizeof(*data));
+				strcpy(data, ipc->shmBaseAdress);
+
+				hash_map_iterator_pt iter = hashMapIterator_create(admin->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(exportedEndpointDesc->service, export->endpointDescription->service) == 0) && (export->endpoint != NULL)) {
+							char *reply = NULL;
+
+							/* TODO: fix handling of handleRequest return value*/
+									export->endpoint->handleRequest(export->endpoint->endpoint, data, &reply);
+
+									if (reply != NULL) {
+										if ((strlen(reply) * sizeof(char)) >= RSA_SHM_MEMSIZE) {
+											logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "receiveFromSharedMemory : size of message bigger than shared memory message. NOT SENDING.");
+										} else {
+											strcpy(ipc->shmBaseAdress, reply);
+										}
+										free(reply);
+									}
+						} else {
+							logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "receiveFromSharedMemory : No endpoint set for %s.", export->endpointDescription->service);
+						}
+					}
+				}
+				hashMapIterator_destroy(iter);
+				free(data);
+
+				remoteServiceAdmin_unlock(ipc->semId, 2);
+
+			}
+		}
+	}
+
+	free(data);
+
+	return NULL;
+}
+
+celix_status_t remoteServiceAdmin_getSharedIdentifierFile(remote_service_admin_pt admin, char *fwUuid, char* servicename, char* outFile) {
+	celix_status_t status = CELIX_SUCCESS;
+	snprintf(outFile, RSA_FILEPATH_LENGTH, "%s/%s/%s", P_tmpdir, fwUuid, servicename);
+
+	if (access(outFile, F_OK) != 0) {
+		char tmpDir[RSA_FILEPATH_LENGTH];
+
+		snprintf(tmpDir, RSA_FILEPATH_LENGTH, "%s/%s", P_tmpdir, fwUuid);
+
+		if(mkdir(tmpDir, 0755) == -1 ){
+			logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "error while creating directory %s (%s)", tmpDir, strerror(errno));
+		}
+		FILE *shid_file = fopen(outFile, "wb");
+		if (shid_file == NULL) {
+			logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "error while creating shared identifier file %s (%s)", outFile, strerror(errno));
+			status = CELIX_FILE_IO_EXCEPTION;
+		} else {
+			logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "create shared identifier file %s", outFile);
+			fclose(shid_file);
+		}
+	} else {
+		logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "shared identifier file %s already exists", outFile);
+	}
+
+	return status;
+}
+
+celix_status_t remoteServiceAdmin_removeSharedIdentityFile(remote_service_admin_pt admin, char *fwUuid, char* servicename) {
+	celix_status_t status = CELIX_SUCCESS;
+	char tmpPath[RSA_FILEPATH_LENGTH];
+	int retVal = 0;
+
+	snprintf(tmpPath, RSA_FILEPATH_LENGTH, "%s/%s/%s", P_tmpdir, fwUuid, servicename);
+
+	retVal = unlink(tmpPath);
+
+	if (retVal == 0) {
+		logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "Removed shared identifier file %s", tmpPath);
+	} else {
+		logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "Cannot remove shared identifier file %s", tmpPath);
+		status = CELIX_FILE_IO_EXCEPTION;
+	}
+
+	return status;
+}
+
+celix_status_t remoteServiceAdmin_removeSharedIdentityFiles(remote_service_admin_pt admin) {
+	char tmpDir[RSA_FILEPATH_LENGTH];
+	const char* fwUuid = NULL;
+	bundleContext_getProperty(admin->context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &fwUuid);
+
+	snprintf(tmpDir, RSA_FILEPATH_LENGTH, "%s/%s", P_tmpdir, fwUuid);
+
+	DIR *d = opendir(tmpDir);
+	size_t path_len = strlen(tmpDir);
+	int retVal = 0;
+
+	if (d) {
+		struct dirent *p;
+
+		while (!retVal && (p = readdir(d))) {
+			char* f_name;
+			size_t len;
+
+			if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) {
+				continue;
+			}
+
+			len = path_len + strlen(p->d_name) + 2;
+			f_name = (char*) calloc(len, 1);
+
+			if (f_name) {
+				snprintf(f_name, len, "%s/%s", tmpDir, p->d_name);
+
+				retVal = unlink(f_name);
+
+				if(retVal==0){
+					logHelper_log(admin->loghelper, OSGI_LOGSERVICE_WARNING, "Removed shared identifier file %s (unproper clean-up?)", f_name);
+				}
+				else{
+					logHelper_log(admin->loghelper, OSGI_LOGSERVICE_WARNING, "Unable to remove shared identifier file %s ", f_name);
+				}
+
+			}
+			free(f_name);
+		}
+	}
+
+	closedir(d);
+
+	if (!retVal) {
+		rmdir(tmpDir);
+	}
+
+	return retVal;
+}
+
+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];
+	const char *exportsProp = NULL;
+	const char *providedProp = NULL;
+
+	snprintf(filter, 256, "(%s=%s)", (char *) OSGI_FRAMEWORK_SERVICE_ID, serviceId);
+
+	bundleContext_getServiceReferences(admin->context, NULL, filter, &references);
+
+	if (arrayList_size(references) >= 1) {
+		reference = arrayList_get(references, 0);
+	}
+
+	arrayList_destroy(references);
+
+	serviceReference_getProperty(reference, (char *) OSGI_RSA_SERVICE_EXPORTED_INTERFACES, &exportsProp);
+	serviceReference_getProperty(reference, (char *) OSGI_FRAMEWORK_OBJECTCLASS, &providedProp);
+
+	char* exports = strndup(exportsProp, 1024*10);
+	char* provided = strndup(providedProp, 1024*10);
+
+	if (reference == NULL) {
+		logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "expected a reference for service id %s.", serviceId);
+		status = CELIX_ILLEGAL_STATE;
+	}
+	else if (exports == NULL || provided == NULL) {
+		logHelper_log(admin->loghelper, OSGI_LOGSERVICE_WARNING, "No Services to export.");
+	} else {
+		logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "Export services (%s)", exports);
+		array_list_pt interfaces = NULL;
+		arrayList_create(&interfaces);
+		if (strcmp(utils_stringTrim(exports), "*") == 0) {
+			char *provided_save_ptr = NULL;
+			char *interface = strtok_r(provided, ",", &provided_save_ptr);
+			while (interface != NULL) {
+				arrayList_add(interfaces, utils_stringTrim(interface));
+				interface = strtok_r(NULL, ",", &provided_save_ptr);
+			}
+		} else {
+			char *provided_save_ptr = NULL;
+			char *pinterface = strtok_r(provided, ",", &provided_save_ptr);
+			while (pinterface != NULL) {
+				char *exports_save_ptr = NULL;
+				char *einterface = strtok_r(exports, ",", &exports_save_ptr);
+				while (einterface != NULL) {
+					if (strcmp(einterface, pinterface) == 0) {
+						arrayList_add(interfaces, einterface);
+					}
+					einterface = strtok_r(NULL, ",", &exports_save_ptr);
+				}
+				pinterface = strtok_r(NULL, ",", &provided_save_ptr);
+			}
+		}
+
+		if (arrayList_size(interfaces) != 0) {
+			int iter = 0;
+			for (iter = 0; iter < arrayList_size(interfaces); iter++) {
+				char *interface = arrayList_get(interfaces, iter);
+				export_registration_pt registration = NULL;
+
+				exportRegistration_create(admin->loghelper, reference, NULL, admin, admin->context, &registration);
+				arrayList_add(*registrations, registration);
+
+				remoteServiceAdmin_installEndpoint(admin, registration, reference, interface);
+				exportRegistration_open(registration);
+				exportRegistration_startTracking(registration);
+
+				if (remoteServiceAdmin_createOrAttachShm(admin->exportedIpcSegment, admin, registration->endpointDescription, true) == CELIX_SUCCESS) {
+					recv_shm_thread_pt recvThreadData = NULL;
+
+					if ((recvThreadData = calloc(1, sizeof(*recvThreadData))) == NULL) {
+						status = CELIX_ENOMEM;
+					} else {
+						recvThreadData->admin = admin;
+						recvThreadData->endpointDescription = registration->endpointDescription;
+
+						celix_thread_t* pollThread = calloc(1, sizeof(*pollThread));
+						bool *pollThreadRunningPtr = calloc(1, sizeof(*pollThreadRunningPtr));
+						*pollThreadRunningPtr = true;
+
+						hashMap_put(admin->pollThreadRunning, registration->endpointDescription, pollThreadRunningPtr);
+
+						// start receiving thread
+						status = celixThread_create(pollThread, NULL, remoteServiceAdmin_receiveFromSharedMemory, recvThreadData);
+
+						hashMap_put(admin->pollThread, registration->endpointDescription, pollThread);
+					}
+				}
+			}
+
+			celixThreadMutex_lock(&admin->exportedServicesLock);
+			hashMap_put(admin->exportedServices, reference, *registrations);
+			celixThreadMutex_unlock(&admin->exportedServicesLock);
+
+		}
+		arrayList_destroy(interfaces);
+	}
+
+	free(exports);
+	free(provided);
+
+	return status;
+}
+
+celix_status_t remoteServiceAdmin_removeExportedService(remote_service_admin_pt admin, export_registration_pt registration) {
+	celix_status_t status;
+	ipc_segment_pt ipc = NULL;
+
+	export_reference_pt ref = NULL;
+	status = exportRegistration_getExportReference(registration, &ref);
+
+	if (status == CELIX_SUCCESS) {
+		bool *pollThreadRunning = NULL;
+
+		service_reference_pt servRef;
+		celixThreadMutex_lock(&admin->exportedServicesLock);
+		exportReference_getExportedService(ref, &servRef);
+
+		array_list_pt exports = (array_list_pt)hashMap_remove(admin->exportedServices, servRef);
+		if(exports!=NULL){
+			arrayList_destroy(exports);
+		}
+
+		exportRegistration_close(registration);
+
+		if ((pollThreadRunning = hashMap_get(admin->pollThreadRunning, registration->endpointDescription)) != NULL) {
+			*pollThreadRunning = false;
+
+			if ((ipc = hashMap_get(admin->exportedIpcSegment, registration->endpointDescription->service)) != NULL) {
+				celix_thread_t* pollThread;
+
+				remoteServiceAdmin_unlock(ipc->semId, 1);
+
+				if ((pollThread = hashMap_get(admin->pollThread, registration->endpointDescription)) != NULL) {
+					status = celixThread_join(*pollThread, NULL);
+
+					if (status == CELIX_SUCCESS) {
+						semctl(ipc->semId, 1 , IPC_RMID);
+						shmctl(ipc->shmId, IPC_RMID, 0);
+
+						remoteServiceAdmin_removeSharedIdentityFile(admin, registration->endpointDescription->frameworkUUID, registration->endpointDescription->service);
+
+						hashMap_remove(admin->pollThreadRunning, registration->endpointDescription);
+						hashMap_remove(admin->exportedIpcSegment, registration->endpointDescription->service);
+						hashMap_remove(admin->pollThread, registration->endpointDescription);
+
+						free(pollThreadRunning);
+						free(pollThread);
+						free(ipc);
+					}
+				}
+			}
+		}
+		exportRegistration_destroy(&registration);
+	}
+
+	if(ref!=NULL){
+		free(ref);
+	}
+
+	celixThreadMutex_unlock(&admin->exportedServicesLock);
+
+	return status;
+}
+
+celix_status_t remoteServiceAdmin_getIpcSegment(remote_service_admin_pt admin, endpoint_description_pt endpointDescription, ipc_segment_pt* ipc) {
+	(*ipc) = (hashMap_containsKey(admin->importedIpcSegment, endpointDescription) == true) ? hashMap_get(admin->importedIpcSegment, endpointDescription) : NULL;
+
+	return (*ipc != NULL) ? CELIX_SUCCESS : CELIX_ILLEGAL_ARGUMENT;
+}
+
+celix_status_t remoteServiceAdmin_detachIpcSegment(ipc_segment_pt ipc) {
+	return (shmdt(ipc->shmBaseAdress) != -1) ? CELIX_SUCCESS : CELIX_BUNDLE_EXCEPTION;
+}
+
+celix_status_t remoteServiceAdmin_deleteIpcSegment(ipc_segment_pt ipc) {
+	return ((semctl(ipc->semId, 1 /*ignored*/, IPC_RMID) != -1) && (shmctl(ipc->shmId, IPC_RMID, 0) != -1)) ? CELIX_SUCCESS : CELIX_BUNDLE_EXCEPTION;
+}
+
+celix_status_t remoteServiceAdmin_createOrAttachShm(hash_map_pt ipcSegment, remote_service_admin_pt admin, endpoint_description_pt endpointDescription, bool createIfNotFound) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	/* setup ipc sehment */
+	ipc_segment_pt ipc = NULL;
+
+	properties_pt endpointProperties = endpointDescription->properties;
+
+	char *shmPath = NULL;
+	char *shmFtokId = NULL;
+
+	char *semPath = NULL;
+	char *semFtokId = NULL;
+
+	if ((shmPath = (char*)properties_get(endpointProperties, (char *) RSA_SHM_PATH_PROPERTYNAME)) == NULL) {
+		logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "No value found for key %s in endpointProperties.", RSA_SHM_PATH_PROPERTYNAME);
+		status = CELIX_BUNDLE_EXCEPTION;
+	} else if ((shmFtokId = (char*)properties_get(endpointProperties, (char *) RSA_SHM_FTOK_ID_PROPERTYNAME)) == NULL) {
+		logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "No value found for key %s in endpointProperties.", RSA_SHM_FTOK_ID_PROPERTYNAME);
+		status = CELIX_BUNDLE_EXCEPTION;
+	} else if ((semPath = (char*)properties_get(endpointProperties, (char *) RSA_SEM_PATH_PROPERTYNAME)) == NULL) {
+		logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "No value found for key %s in endpointProperties.", RSA_SEM_PATH_PROPERTYNAME);
+		status = CELIX_BUNDLE_EXCEPTION;
+	} else if ((semFtokId = (char*)properties_get(endpointProperties, (char *) RSA_SEM_FTOK_ID_PROPERTYNAME)) == NULL) {
+		logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "No value found for key %s in endpointProperties.", RSA_SEM_FTOK_ID_PROPERTYNAME);
+		status = CELIX_BUNDLE_EXCEPTION;
+	} else {
+		key_t shmKey = ftok(shmPath, atoi(shmFtokId));
+		ipc = calloc(1, sizeof(*ipc));
+		if(ipc == NULL){
+			return CELIX_ENOMEM;
+		}
+
+		if ((ipc->shmId = shmget(shmKey, RSA_SHM_MEMSIZE, 0666)) < 0) {
+			logHelper_log(admin->loghelper, OSGI_LOGSERVICE_WARNING, "Could not attach to shared memory");
+
+			if (createIfNotFound == true) {
+				if ((ipc->shmId = shmget(shmKey, RSA_SHM_MEMSIZE, IPC_CREAT | 0666)) < 0) {
+					logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "Creation of shared memory segment failed.");
+					status = CELIX_BUNDLE_EXCEPTION;
+				} else if ((ipc->shmBaseAdress = shmat(ipc->shmId, 0, 0)) == (char *) -1) {
+					logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "Attaching of shared memory segment failed.");
+					status = CELIX_BUNDLE_EXCEPTION;
+				} else {
+					logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "shared memory segment sucessfully created at %p.", ipc->shmBaseAdress);
+				}
+			}
+		} else if ((ipc->shmBaseAdress = shmat(ipc->shmId, 0, 0)) == (char *) -1) {
+			logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "Attaching to shared memory segment failed.");
+			status = CELIX_BUNDLE_EXCEPTION;
+		} else {
+			logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "sucessfully attached to shared memory at %p.", ipc->shmBaseAdress);
+		}
+	}
+
+	if(ipc != NULL && status == CELIX_SUCCESS){
+
+		key_t semkey = ftok(semPath, atoi(semFtokId));
+		int semflg = (createIfNotFound == true) ? (0666 | IPC_CREAT) : (0666);
+		int semid = semget(semkey, 3, semflg);
+
+		if (semid != -1) {
+			// only reset semaphores if a create was supposed
+			if ((createIfNotFound == true) && ((semctl(semid, 0, SETVAL, (int) 1) == -1) || (semctl(semid, 1, SETVAL, (int) 0) == -1) || (semctl(semid, 2, SETVAL, (int) 0) == -1))) {
+				logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "error while initialize semaphores.");
+			}
+
+			logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "semaphores w/ key %s and id %i added.", endpointDescription->service, semid);
+			ipc->semId = semid;
+
+			hashMap_put(ipcSegment, endpointDescription->service, ipc);
+		} else {
+			logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "error getting semaphores.");
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	}
+
+	if(ipc != NULL && status != CELIX_SUCCESS){
+		free(ipc);
+	}
+
+	return status;
+}
+
+celix_status_t remoteServiceAdmin_installEndpoint(remote_service_admin_pt admin, export_registration_pt registration, service_reference_pt reference, char *interface) {
+	celix_status_t status = CELIX_SUCCESS;
+	properties_pt endpointProperties = properties_create();
+
+	unsigned int size = 0;
+	char **keys;
+
+	serviceReference_getPropertyKeys(reference, &keys, &size);
+	for (int i = 0; i < size; i++) {
+		char *key = keys[i];
+		const char *value = NULL;
+
+		if (serviceReference_getProperty(reference, key, &value) == CELIX_SUCCESS && strcmp(key, (char*) OSGI_RSA_SERVICE_EXPORTED_INTERFACES) != 0 && strcmp(key, (char*) OSGI_FRAMEWORK_OBJECTCLASS) != 0) {
+			properties_set(endpointProperties, key, value);
+		}
+	}
+
+	hash_map_entry_pt entry = hashMap_getEntry(endpointProperties, (void *) OSGI_FRAMEWORK_SERVICE_ID);
+
+	char* key = hashMapEntry_getKey(entry);
+	char *serviceId = (char *) hashMap_remove(endpointProperties, (void *) OSGI_FRAMEWORK_SERVICE_ID);
+	const char *uuid = NULL;
+
+	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);
+
+	if (properties_get(endpointProperties, (char *) RSA_SHM_PATH_PROPERTYNAME) == NULL) {
+		char sharedIdentifierFile[RSA_FILEPATH_LENGTH];
+
+		if (remoteServiceAdmin_getSharedIdentifierFile(admin, (char*)uuid, interface, sharedIdentifierFile) == CELIX_SUCCESS) {
+			properties_set(endpointProperties, RSA_SHM_PATH_PROPERTYNAME, sharedIdentifierFile);
+		} else {
+			properties_set(endpointProperties, (char *) RSA_SHM_PATH_PROPERTYNAME, (char *) RSA_SHM_DEFAULTPATH);
+		}
+	}
+	if (properties_get(endpointProperties, (char *) RSA_SHM_FTOK_ID_PROPERTYNAME) == NULL) {
+		properties_set(endpointProperties, (char *) RSA_SHM_FTOK_ID_PROPERTYNAME, (char *) RSA_SHM_DEFAULT_FTOK_ID);
+	}
+	if (properties_get(endpointProperties, (char *) RSA_SEM_PATH_PROPERTYNAME) == NULL) {
+		char sharedIdentifierFile[RSA_FILEPATH_LENGTH];
+
+		if (remoteServiceAdmin_getSharedIdentifierFile(admin, (char*)uuid, interface, sharedIdentifierFile) == CELIX_SUCCESS) {
+			properties_set(endpointProperties, (char *) RSA_SEM_PATH_PROPERTYNAME, sharedIdentifierFile);
+		} else {
+			properties_set(endpointProperties, (char *) RSA_SEM_PATH_PROPERTYNAME, (char *) RSA_SEM_DEFAULTPATH);
+		}
+	}
+	if (properties_get(endpointProperties, (char *) RSA_SEM_FTOK_ID_PROPERTYNAME) == NULL) {
+		properties_set(endpointProperties, (char *) RSA_SEM_FTOK_ID_PROPERTYNAME, (char *) RSA_SEM_DEFAULT_FTOK_ID);
+	}
+
+	endpoint_description_pt endpointDescription = NULL;
+	remoteServiceAdmin_createEndpointDescription(admin, reference, endpointProperties, interface, &endpointDescription);
+	exportRegistration_setEndpointDescription(registration, endpointDescription);
+
+	free(key);
+	free(serviceId);
+	free(keys);
+
+	return status;
+}
+
+celix_status_t remoteServiceAdmin_createEndpointDescription(remote_service_admin_pt admin, service_reference_pt reference, properties_pt endpointProperties, char *interface, endpoint_description_pt *description) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	*description = calloc(1, sizeof(**description));
+	if (!*description) {
+		status = CELIX_ENOMEM;
+	} else {
+		if (status == CELIX_SUCCESS) {
+			(*description)->properties = endpointProperties;
+			(*description)->frameworkUUID = (char*)properties_get(endpointProperties, (char*) OSGI_RSA_ENDPOINT_FRAMEWORK_UUID);
+			const char *serviceId = NULL;
+			serviceReference_getProperty(reference, (char*)OSGI_FRAMEWORK_SERVICE_ID, &serviceId);
+			(*description)->serviceId = strtoull(serviceId, NULL, 0);
+			(*description)->id = (char*)properties_get(endpointProperties, (char*) OSGI_RSA_ENDPOINT_ID);
+			(*description)->service = strndup(interface, 1024*10);
+		}
+	}
+
+	return status;
+}
+
+celix_status_t remoteServiceAdmin_destroyEndpointDescription(endpoint_description_pt *description) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	properties_destroy((*description)->properties);
+	free((*description)->service);
+	free(*description);
+
+	return status;
+}
+
+celix_status_t remoteServiceAdmin_getExportedServices(remote_service_admin_pt admin, array_list_pt *services) {
+	celix_status_t status = CELIX_SUCCESS;
+	return status;
+}
+
+celix_status_t remoteServiceAdmin_getImportedEndpoints(remote_service_admin_pt admin, array_list_pt *services) {
+	celix_status_t status = CELIX_SUCCESS;
+	return status;
+}
+
+celix_status_t remoteServiceAdmin_importService(remote_service_admin_pt admin, endpoint_description_pt endpointDescription, import_registration_pt *registration) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Import service %s", endpointDescription->service);
+
+	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);
+		remoteServiceAdmin_createOrAttachShm(admin->importedIpcSegment, admin, endpointDescription, false);
+	}
+
+	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;
+
+	if (registration != NULL) {
+
+		celixThreadMutex_lock(&admin->importedServicesLock);
+
+		ipc_segment_pt ipc = NULL;
+		endpoint_description_pt endpointDescription = (endpoint_description_pt) registration->endpointDescription;
+		import_registration_factory_pt registration_factory = (import_registration_factory_pt) hashMap_get(admin->importedServices, endpointDescription->service);
+
+		// detach from IPC
+		if (remoteServiceAdmin_getIpcSegment(admin, endpointDescription, &ipc) != CELIX_SUCCESS) {
+			logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "Error while retrieving IPC segment for imported service %s.", endpointDescription->service);
+		} else if (remoteServiceAdmin_detachIpcSegment(ipc) != CELIX_SUCCESS) {
+			logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "Error while detaching IPC segment for imported service %s.", endpointDescription->service);
+		}
+
+		ipc = hashMap_remove(admin->importedIpcSegment,endpointDescription);
+		if(ipc!=NULL){
+			free(ipc);
+		}
+
+		// factory available
+		if ((registration_factory == NULL) || (registration_factory->trackedFactory == NULL)) {
+			logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "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) == true) {
+				logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "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;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_service_admin_shm/private/test/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_service_admin_shm/private/test/CMakeLists.txt b/bundles/remote_services/remote_service_admin_shm/private/test/CMakeLists.txt
new file mode 100644
index 0000000..5e32643
--- /dev/null
+++ b/bundles/remote_services/remote_service_admin_shm/private/test/CMakeLists.txt
@@ -0,0 +1,58 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+include_directories(
+    ${PROJECT_SOURCE_DIR}/framework/public/include
+    ${PROJECT_SOURCE_DIR}/utils/public/include
+    ${PROJECT_SOURCE_DIR}/utils/public/include
+    ${PROJECT_SOURCE_DIR}/remote_services/remote_service_admin/public/include
+    ${PROJECT_SOURCE_DIR}/remote_services/examples/calculator_service/public/include
+    bundle
+)
+
+
+SET(CMAKE_SKIP_BUILD_RPATH  FALSE) #TODO needed?
+SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) #TODO needed?
+SET(CMAKE_INSTALL_RPATH "${PROJECT_BINARY_DIR}/framework" "${PROJECT_BINARY_DIR}/utils")
+
+add_executable(test_rsa_shm
+    run_tests.cpp
+    rsa_client_server_tests.cpp
+
+    ${PROJECT_SOURCE_DIR}/remote_services/remote_service_admin/private/src/endpoint_description.c
+)
+target_link_libraries(test_rsa_shm celix_framework celix_utils ${CURL_LIBRARIES} ${CPPUTEST_LIBRARY})
+
+get_property(rsa_bundle_file TARGET remote_service_admin_shm PROPERTY BUNDLE_FILE)
+get_property(calc_bundle_file TARGET calculator PROPERTY BUNDLE_FILE)
+get_property(calculator_shell_bundle_file TARGET calculator_shell PROPERTY BUNDLE_FILE)
+get_property(discovery_shm_bundle_file TARGET discovery_shm PROPERTY BUNDLE_FILE)
+get_property(topology_manager_bundle_file TARGET topology_manager PROPERTY BUNDLE_FILE)
+get_property(calc_proxy_bundle_file TARGET org.apache.celix.calc.api.Calculator_proxy PROPERTY BUNDLE_FILE)
+get_property(calc_endpoint_bundle_file TARGET  org.apache.celix.calc.api.Calculator_endpoint PROPERTY BUNDLE_FILE)
+
+get_filename_component(client_endpoints ${calc_proxy_bundle_file} PATH)
+get_filename_component(server_endpoints ${calc_endpoint_bundle_file} PATH)
+
+configure_file(client.properties.in client.properties)
+configure_file(server.properties.in server.properties)
+
+add_dependencies(test_rsa_shm remote_service_admin_shm calculator org.apache.celix.calc.api.Calculator_proxy org.apache.celix.calc.api.Calculator_endpoint)
+ 
+#add_test(NAME run_test_rsa_shm COMMAND test_rsa_shm)
+#SETUP_TARGET_FOR_COVERAGE(test_rsa_shm_cov test_rsa_shm ${CMAKE_BINARY_DIR}/coverage/test_rsa_shm/test_rsa_shm)
+

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_service_admin_shm/private/test/client.properties.in
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_service_admin_shm/private/test/client.properties.in b/bundles/remote_services/remote_service_admin_shm/private/test/client.properties.in
new file mode 100644
index 0000000..d4eb239
--- /dev/null
+++ b/bundles/remote_services/remote_service_admin_shm/private/test/client.properties.in
@@ -0,0 +1,25 @@
+# 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.
+
+cosgi.auto.start.1=${rsa_bundle_file} ${calculator_shell_bundle_file} ${discovery_shm_bundle_file} ${topology_manager_bundle_file} ${tst_bundle_file}
+LOGHELPER_ENABLE_STDOUT_FALLBACK=true
+ENDPOINTS=@client_endpoints@
+RSA_PORT=50881
+DISCOVERY_CFG_SERVER_PORT=50993
+org.osgi.framework.storage.clean=onFirstInit
+org.osgi.framework.storage=.cacheClient
+DISCOVERY_CFG_POLL_INTERVAL=1

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_service_admin_shm/private/test/rsa_client_server_tests.cpp
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_service_admin_shm/private/test/rsa_client_server_tests.cpp b/bundles/remote_services/remote_service_admin_shm/private/test/rsa_client_server_tests.cpp
new file mode 100644
index 0000000..13c6941
--- /dev/null
+++ b/bundles/remote_services/remote_service_admin_shm/private/test/rsa_client_server_tests.cpp
@@ -0,0 +1,496 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+#include <CppUTest/TestHarness.h>
+#include <remote_constants.h>
+#include <constants.h>
+#include "CppUTest/CommandLineTestRunner.h"
+#include "../../../examples/calculator_service/public/include/calculator_service.h"
+
+extern "C" {
+
+	#include <stdio.h>
+	#include <stdint.h>
+	#include <stdlib.h>
+	#include <string.h>
+	#include <ctype.h>
+	#include <unistd.h>
+
+	#include "celix_launcher.h"
+	#include "framework.h"
+	#include "remote_service_admin.h"
+	#include "calculator_service.h"
+	#include "bundle.h"
+
+	#define DISCOVERY_CFG_NAME      "apache_celix_rsa_discovery_shm"
+	#define RSA_HTTP_NAME           "apache_celix_remote_service_admin_shm"
+	#define TOPOLOGY_MANAGER_NAME   "apache_celix_rs_topology_manager"
+	#define CALCULATOR_PROXY   		"apache_celix_remoting_calculator_proxy"
+	#define CALCULATOR_ENDPOINT   	"apache_celix_remoting_calculator_endpoint"
+
+	static framework_pt	serverFramework = NULL;
+	static bundle_context_pt serverContext = NULL;
+
+	static framework_pt clientFramework = NULL;
+	static bundle_context_pt clientContext = NULL;
+
+	static void setupFm(void) {
+		int rc = 0;
+		bundle_pt bundle = NULL;
+
+		//server
+		rc = celixLauncher_launch("server.properties", &serverFramework);
+		CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+		bundle = NULL;
+		rc = framework_getFrameworkBundle(serverFramework, &bundle);
+		CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+		rc = bundle_getContext(bundle, &serverContext);
+		CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+		//client
+		rc = celixLauncher_launch("client.properties", &clientFramework);
+		CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+		bundle = NULL;
+		rc = framework_getFrameworkBundle(clientFramework, &bundle);
+		CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+		rc = bundle_getContext(bundle, &clientContext);
+		CHECK_EQUAL(CELIX_SUCCESS, rc);
+	}
+
+	static void teardownFm(void) {
+		celixLauncher_stop(serverFramework);
+		celixLauncher_waitForShutdown(serverFramework);
+		celixLauncher_destroy(serverFramework);
+
+		celixLauncher_stop(clientFramework);
+		celixLauncher_waitForShutdown(clientFramework);
+		celixLauncher_destroy(clientFramework);
+
+		serverContext = NULL;
+		serverFramework = NULL;
+		clientContext = NULL;
+		clientFramework = NULL;
+	}
+
+	static void test1(void) {
+		celix_status_t status;
+		service_reference_pt ref = NULL;
+		calculator_service_pt calcService = NULL;
+		int retries = 6;
+
+        while (ref == NULL && retries > 0) {
+            printf("Waiting for service .. %d\n", retries);
+            status = bundleContext_getServiceReference(clientContext, (char *) CALCULATOR_SERVICE, &ref);
+            usleep(1000000);
+            --retries;
+        }
+
+
+		CHECK_EQUAL(CELIX_SUCCESS, status);
+		CHECK(ref != NULL);
+
+		status = bundleContext_getService(clientContext, ref, (void **) &calcService);
+		CHECK_EQUAL(CELIX_SUCCESS, status);
+		CHECK(calcService != NULL);
+
+		double result = 0;
+		status = calcService->add(calcService->calculator, 2.0, 5.0, &result);
+		CHECK_EQUAL(CELIX_SUCCESS, status);
+		CHECK_EQUAL(7.0, result);
+
+		bundleContext_ungetService(clientContext, ref, NULL);
+		bundleContext_ungetServiceReference(clientContext, ref);
+	}
+
+
+	static celix_status_t getPermutations(array_list_pt bundleIds, int from, int to, array_list_pt permutations) {
+		celix_status_t status = CELIX_SUCCESS;
+		int i = 0;
+
+		if (from == to) {
+			long* permutation = (long*) calloc(to + 1, sizeof(*permutation));
+
+			if (!permutation) {
+				status = CELIX_ENOMEM;
+			} else {
+				for (; i <= to; i++) {
+					permutation[i] = (long) arrayList_get(bundleIds, i);
+				}
+
+				arrayList_add(permutations, permutation);
+			}
+		} else {
+			for (i = from; i <= to; i++) {
+				long fromOrg = (long) arrayList_get(bundleIds, from);
+				long iOrg = (long) arrayList_get(bundleIds, i);
+
+				arrayList_set(bundleIds, from, (void*) iOrg);
+				arrayList_set(bundleIds, i, (void*) fromOrg);
+
+				status = getPermutations(bundleIds, from + 1, to, permutations);
+
+				arrayList_set(bundleIds, from, (void*) fromOrg);
+				arrayList_set(bundleIds, i, (void*) iOrg);
+			}
+		}
+
+		return status;
+	}
+
+	static celix_status_t getSpecifiedBundles(bundle_context_pt context, array_list_pt bundleNames, array_list_pt retrievedBundles) {
+		celix_status_t status;
+		array_list_pt bundles = NULL;
+
+		status = bundleContext_getBundles(context, &bundles);
+
+		if (status == CELIX_SUCCESS) {
+			unsigned int size = arrayList_size(bundles);
+			unsigned int i;
+
+			for (i = 0; i < size; i++) {
+				module_pt module = NULL;
+				const char *name = NULL;
+
+				bundle_pt bundle = (bundle_pt) arrayList_get(bundles, i);
+
+				status = bundle_getCurrentModule(bundle, &module);
+
+				if (status == CELIX_SUCCESS) {
+					status = module_getSymbolicName(module, &name);
+				}
+
+				if (status == CELIX_SUCCESS) {
+					array_list_iterator_pt iter = arrayListIterator_create(bundleNames);
+
+					while(arrayListIterator_hasNext(iter)) {
+						char* bundleName = (char*) arrayListIterator_next(iter);
+
+						if ((strcmp(name, bundleName) == 0)) {
+
+							bundle_archive_pt bundleArchive = NULL;
+							long bundleId = -1;
+
+							status = bundle_getArchive(bundle, &bundleArchive);
+
+							if (status == CELIX_SUCCESS) {
+								status = bundleArchive_getId(bundleArchive, &bundleId);
+							}
+
+							if (status == CELIX_SUCCESS) {
+								arrayList_add(retrievedBundles, (void*) bundleId);
+								break;
+							}
+						}
+					}
+
+					arrayListIterator_destroy(iter);
+
+				}
+			}
+
+			arrayList_destroy(bundles);
+		}
+
+		return status;
+	}
+
+	static celix_status_t stopStartPermutation(bundle_context_pt context, long* permutation, int size) {
+		celix_status_t status = CELIX_SUCCESS;
+		int y = 0;
+
+		printf("Test stop/start permutation: ");
+
+		for (y = 0; (y < size) && (status == CELIX_SUCCESS); y++) {
+			bundle_pt bundle = NULL;
+
+			status = bundleContext_getBundleById(context, permutation[y], &bundle);
+
+			if (status == CELIX_SUCCESS) {
+				module_pt module = NULL;
+				const char *name = NULL;
+
+				status = bundle_getCurrentModule(bundle, &module);
+
+				if (status == CELIX_SUCCESS) {
+					status = module_getSymbolicName(module, &name);
+					printf("%s (%ld) ", name, permutation[y]);
+				}
+			}
+		}
+		printf("\n");
+
+		// stop all bundles
+		if (status == CELIX_SUCCESS) {
+			for (y = 0; (y < size) && (status == CELIX_SUCCESS); y++) {
+				bundle_pt bundle = NULL;
+
+				status = bundleContext_getBundleById(context, permutation[y], &bundle);
+
+				if (status == CELIX_SUCCESS) {
+					printf("stop bundle: %ld\n", permutation[y]);
+					status = bundle_stop(bundle);
+				}
+			}
+		}
+
+		// verify stop state
+		if (status == CELIX_SUCCESS) {
+			for (y = 0; (y < size) && (status == CELIX_SUCCESS); y++) {
+				bundle_pt bundle = NULL;
+
+				status = bundleContext_getBundleById(context, permutation[y], &bundle);
+
+				if (status == CELIX_SUCCESS) {
+					bundle_state_e state;
+					status = bundle_getState(bundle, &state);
+
+					if (state != OSGI_FRAMEWORK_BUNDLE_RESOLVED) {
+						printf("bundle %ld has state %d (should be %d) \n", permutation[y], state, OSGI_FRAMEWORK_BUNDLE_RESOLVED);
+						status = CELIX_ILLEGAL_STATE;
+					}
+				}
+			}
+		}
+
+		// start all bundles
+		if (status == CELIX_SUCCESS) {
+
+			for (y = 0; (y < size) && (status == CELIX_SUCCESS); y++) {
+				bundle_pt bundle = NULL;
+
+				status = bundleContext_getBundleById(context, permutation[y], &bundle);
+
+				if (status == CELIX_SUCCESS) {
+					printf("start bundle: %ld\n", permutation[y]);
+					status = bundle_start(bundle);
+				}
+			}
+		}
+
+		// verify started state
+		if (status == CELIX_SUCCESS) {
+			for (y = 0; (y < size) && (status == CELIX_SUCCESS); y++) {
+				bundle_pt bundle = NULL;
+
+				status = bundleContext_getBundleById(context, permutation[y], &bundle);
+
+				if (status == CELIX_SUCCESS) {
+					bundle_state_e state;
+					status = bundle_getState(bundle, &state);
+
+					if (state != OSGI_FRAMEWORK_BUNDLE_ACTIVE) {
+						printf("bundle %ld has state %d (should be %d) \n", permutation[y], state, OSGI_FRAMEWORK_BUNDLE_ACTIVE);
+						status = CELIX_ILLEGAL_STATE;
+					}
+				}
+			}
+		}
+
+		return status;
+	}
+
+	static void testImport(void) {
+		celix_status_t status;
+		array_list_pt bundleNames = NULL;
+		array_list_pt bundlePermutations = NULL;
+		array_list_pt rsaBundles = NULL;
+		unsigned int i, size;
+
+		arrayList_create(&bundleNames);
+		arrayList_create(&bundlePermutations);
+		arrayList_create(&rsaBundles);
+
+		arrayList_add(bundleNames, (void*) DISCOVERY_CFG_NAME);
+		arrayList_add(bundleNames, (void*) RSA_HTTP_NAME);
+		arrayList_add(bundleNames, (void*) TOPOLOGY_MANAGER_NAME);
+
+		status = getSpecifiedBundles(clientContext, bundleNames, rsaBundles);
+		CHECK_EQUAL(CELIX_SUCCESS, status);
+		CHECK_EQUAL(arrayList_size(rsaBundles), arrayList_size(bundleNames));
+
+		status = getPermutations(rsaBundles, 0, arrayList_size(rsaBundles) - 1, bundlePermutations);
+		CHECK_EQUAL(CELIX_SUCCESS, status);
+
+		size = arrayList_size(bundlePermutations);
+
+		for (i = 0; i < size; ++i) {
+			long* singlePermutation = (long*) arrayList_get(bundlePermutations, i);
+
+			status = stopStartPermutation(clientContext, singlePermutation, arrayList_size(rsaBundles));
+			CHECK_EQUAL(CELIX_SUCCESS, status);
+
+			// check whether calc service is available
+			test1();
+
+			free(singlePermutation);
+		}
+
+		arrayList_destroy(bundlePermutations);
+		arrayList_destroy(bundleNames);
+		arrayList_destroy(rsaBundles);
+	}
+
+	static void testExport(void) {
+		celix_status_t status;
+		array_list_pt bundleNames = NULL;
+		array_list_pt bundlePermutations = NULL;
+		array_list_pt rsaBundles = NULL;
+
+		unsigned int i, size;
+
+		arrayList_create(&bundleNames);
+		arrayList_create(&bundlePermutations);
+		arrayList_create(&rsaBundles);
+
+		arrayList_add(bundleNames, (void*) DISCOVERY_CFG_NAME);
+		arrayList_add(bundleNames, (void*) RSA_HTTP_NAME);
+		arrayList_add(bundleNames, (void*) TOPOLOGY_MANAGER_NAME);
+
+		status = getSpecifiedBundles(serverContext, bundleNames, rsaBundles);
+		CHECK_EQUAL(CELIX_SUCCESS, status);
+		CHECK_EQUAL(arrayList_size(rsaBundles), arrayList_size(bundleNames));
+
+		status = getPermutations(rsaBundles, 0, arrayList_size(rsaBundles) - 1, bundlePermutations);
+		CHECK_EQUAL(CELIX_SUCCESS, status);
+
+		size = arrayList_size(bundlePermutations);
+
+		for (i = 0; i < size; ++i) {
+			long* singlePermutation = (long*) arrayList_get(bundlePermutations, i);
+
+			status = stopStartPermutation(serverContext, singlePermutation, arrayList_size(rsaBundles));
+			CHECK_EQUAL(CELIX_SUCCESS, status);
+
+            /* we need to sleep here for a bit to ensure
+             * that the client has flushed the old discovery
+             * values
+             */
+            sleep(2);
+
+			// check whether calc service is available
+			test1();
+
+			free(singlePermutation);
+		}
+
+		arrayList_destroy(bundlePermutations);
+		arrayList_destroy(bundleNames);
+		arrayList_destroy(rsaBundles);
+	}
+
+	/*
+	static void testProxyRemoval(void) {
+		celix_status_t status;
+		bundle_pt bundle = NULL;
+		array_list_pt bundleNames = NULL;
+		array_list_pt proxyBundle = NULL;
+		service_reference_pt ref = NULL;
+
+		arrayList_create(&bundleNames);
+		arrayList_create(&proxyBundle);
+
+		arrayList_add(bundleNames, (void*) CALCULATOR_PROXY);
+		status = getSpecifiedBundles(clientContext, bundleNames, proxyBundle);
+		CHECK_EQUAL(CELIX_SUCCESS, status);
+		CHECK_EQUAL(arrayList_size(proxyBundle), arrayList_size(bundleNames));
+
+		status = bundleContext_getBundleById(clientContext, (long) arrayList_get(proxyBundle, 0), &bundle);
+		CHECK_EQUAL(CELIX_SUCCESS, status);
+
+		status = bundle_stop(bundle);
+		CHECK_EQUAL(CELIX_SUCCESS, status);
+
+		status = bundleContext_getServiceReference(clientContext, (char *) CALCULATOR_SERVICE, &ref);
+		CHECK_EQUAL(CELIX_SUCCESS, status);
+		CHECK(ref == NULL);
+
+		arrayList_destroy(bundleNames);
+		arrayList_destroy(proxyBundle);
+	}
+	*/
+
+	/*
+	static void testEndpointRemoval(void) {
+		celix_status_t status;
+		bundle_pt bundle = NULL;
+		array_list_pt bundleNames = NULL;
+		array_list_pt endpointBundle = NULL;
+		service_reference_pt ref = NULL;
+
+		arrayList_create(&bundleNames);
+		arrayList_create(&endpointBundle);
+
+		arrayList_add(bundleNames, (void*) CALCULATOR_ENDPOINT);
+		status = getSpecifiedBundles(serverContext, bundleNames, endpointBundle);
+		CHECK_EQUAL(CELIX_SUCCESS, status);
+		CHECK_EQUAL(arrayList_size(endpointBundle), arrayList_size(bundleNames));
+
+		status = bundleContext_getBundleById(serverContext, (long) arrayList_get(endpointBundle, 0), &bundle);
+		CHECK_EQUAL(CELIX_SUCCESS, status);
+
+		status = bundle_stop(bundle);
+		CHECK_EQUAL(CELIX_SUCCESS, status);
+
+		status = bundleContext_getServiceReference(serverContext, (char *) CALCULATOR_SERVICE, &ref);
+		CHECK_EQUAL(CELIX_SUCCESS, status);
+		CHECK(ref == NULL);
+
+		arrayList_destroy(bundleNames);
+		arrayList_destroy(endpointBundle);
+	}
+	*/
+}
+
+	TEST_GROUP(RsaShmClientServerTests) {
+	void setup() {
+		setupFm();
+	}
+
+	void teardown() {
+		teardownFm();
+	}
+};
+
+
+TEST(RsaShmClientServerTests, Test1) {
+	test1();
+}
+
+TEST(RsaShmClientServerTests, TestImport) {
+	testImport();
+}
+
+TEST(RsaShmClientServerTests, TestExport) {
+	testExport();
+}
+
+/*
+TEST(RsaShmClientServerTests, TestProxyRemoval) {
+	// test is currenlty failing
+	// testProxyRemoval();
+}
+
+TEST(RsaShmClientServerTests, TestEndpointRemoval) {
+	// test is currenlty failing
+	//testEndpointRemoval();
+}
+*/

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_service_admin_shm/private/test/run_tests.cpp
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_service_admin_shm/private/test/run_tests.cpp b/bundles/remote_services/remote_service_admin_shm/private/test/run_tests.cpp
new file mode 100644
index 0000000..fb6ca3a
--- /dev/null
+++ b/bundles/remote_services/remote_service_admin_shm/private/test/run_tests.cpp
@@ -0,0 +1,24 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+#include <CppUTest/TestHarness.h>
+#include "CppUTest/CommandLineTestRunner.h"
+
+int main(int argc, char** argv) {
+    return RUN_ALL_TESTS(argc, argv);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_service_admin_shm/private/test/server.properties.in
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_service_admin_shm/private/test/server.properties.in b/bundles/remote_services/remote_service_admin_shm/private/test/server.properties.in
new file mode 100644
index 0000000..0b40556
--- /dev/null
+++ b/bundles/remote_services/remote_service_admin_shm/private/test/server.properties.in
@@ -0,0 +1,25 @@
+# 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.
+
+cosgi.auto.start.1=@rsa_bundle_file@ @calc_bundle_file@ @discovery_shm_bundle_file@ @topology_manager_bundle_file@
+LOGHELPER_ENABLE_STDOUT_FALLBACK=true
+ENDPOINTS=@server_endpoints@
+RSA_PORT=50882
+DISCOVERY_CFG_SERVER_PORT=50994
+org.osgi.framework.storage.clean=onFirstInit
+org.osgi.framework.storage=.cacheServer
+DISCOVERY_CFG_POLL_INTERVAL=1

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_service_admin_shm/public/include/remote_service_admin_shm.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_service_admin_shm/public/include/remote_service_admin_shm.h b/bundles/remote_services/remote_service_admin_shm/public/include/remote_service_admin_shm.h
new file mode 100644
index 0000000..676a049
--- /dev/null
+++ b/bundles/remote_services/remote_service_admin_shm/public/include/remote_service_admin_shm.h
@@ -0,0 +1,35 @@
+/**
+ *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_shm.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_SHM_H_
+#define REMOTE_SERVICE_ADMIN_SHM_H_
+
+#define RSA_FUNCTIONCALL_DATA_PROPERTYNAME "data"
+#define RSA_FUNCTIONCALL_RETURN_PROPERTYNAME "reply"
+#define RSA_FUNCTIONCALL_RETURNSTATUS_PROPERTYNAME "replyStatus"
+
+
+#endif /* REMOTE_SERVICE_ADMIN_SHM_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_services_api/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_services_api/CMakeLists.txt b/bundles/remote_services/remote_services_api/CMakeLists.txt
new file mode 100644
index 0000000..a092f59
--- /dev/null
+++ b/bundles/remote_services/remote_services_api/CMakeLists.txt
@@ -0,0 +1,28 @@
+# 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.
+
+add_library(remote_services_api INTERFACE)
+target_include_directories(remote_services_api INTERFACE
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
+    $<INSTALL_INTERFACE:include/celix/remote_service_admin>
+)
+
+install(TARGETS remote_services_api EXPORT celix DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT rsa)
+install(DIRECTORY include/ DESTINATION include/celix/remote_service_admin COMPONENT rsa)
+
+#Setup target aliases to match external usage
+add_library(Celix::remote_services_api ALIAS remote_services_api)

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_services_api/README.md
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_services_api/README.md b/bundles/remote_services/remote_services_api/README.md
new file mode 100644
index 0000000..2e3d268
--- /dev/null
+++ b/bundles/remote_services/remote_services_api/README.md
@@ -0,0 +1,11 @@
+# Remote Service Admin
+
+The Remote Service Admin (RSA) provides the mechanisms to import and export services when instructed to do so by the Topology Manager. 
+
+To delegate method calls to the actual service implementation, the RSA_SHM and the RSA_HTTP are using "endpoint/proxy" bundles, which has all the knowledge about the marshalling and unmarshalling of data for the service. The RSA_DFI implementation combines a [foreign function interface](https://en.wikipedia.org/wiki/Foreign_function_interface) technique together with manualy created descriptors.  
+
+Note that this folder contains code commonly used by the RSA implementations and therefore does not include any CMAKE configuration.
+
+## Properties
+    ENDPOINTS				 defines the relative directory where endpoints and proxys can be found (default: endpoints)
+    CELIX_FRAMEWORK_EXTENDER_PATH  Used in RSA_DFI only. Can be used to define a path to use as an extender path point for the framework bundle. For normal bundles the bundle cache is used. 

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/remote_services_api/include/remote_constants.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/remote_services_api/include/remote_constants.h b/bundles/remote_services/remote_services_api/include/remote_constants.h
new file mode 100644
index 0000000..277f837
--- /dev/null
+++ b/bundles/remote_services/remote_services_api/include/remote_constants.h
@@ -0,0 +1,31 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef REMOTE_CONSTANTS_H_
+#define REMOTE_CONSTANTS_H_
+
+static const char * const OSGI_RSA_SERVICE_EXPORTED_INTERFACES = "service.exported.interfaces";
+static const char * const OSGI_RSA_ENDPOINT_FRAMEWORK_UUID = "endpoint.framework.uuid";
+static const char * const OSGI_RSA_ENDPOINT_SERVICE_ID = "endpoint.service.id";
+static const char * const OSGI_RSA_ENDPOINT_ID = "endpoint.id";
+static const char * const OSGI_RSA_SERVICE_IMPORTED = "service.imported";
+static const char * const OSGI_RSA_SERVICE_IMPORTED_CONFIGS = "service.imported.configs";
+static const char * const OSGI_RSA_SERVICE_LOCATION = "service.location";
+
+#endif /* REMOTE_CONSTANTS_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_common/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_common/CMakeLists.txt b/bundles/remote_services/rsa_common/CMakeLists.txt
new file mode 100644
index 0000000..397fa8c
--- /dev/null
+++ b/bundles/remote_services/rsa_common/CMakeLists.txt
@@ -0,0 +1,30 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_library(rsa_common STATIC
+    src/endpoint_description.c
+    src/export_registration_impl.c
+    src/import_registration_impl.c
+)
+set_target_properties(rsa_common PROPERTIES OUTPUT_NAME "celix_rsa_common")
+target_include_directories(rsa_common PRIVATE src)
+target_link_libraries(rsa_common PUBLIC Celix::framework Celix::rsa_spi Celix::log_helper)
+
+#install(TARGETS rsa_common EXPORT celix COMPONENT rsa DESTINATION ${CMAKE_INSTALL_LIBDIR})
+
+#Setup target aliases to match external usage
+add_library(Celix::rsa_common ALIAS rsa_common)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_common/src/endpoint_description.c
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_common/src/endpoint_description.c b/bundles/remote_services/rsa_common/src/endpoint_description.c
new file mode 100644
index 0000000..0d8b684
--- /dev/null
+++ b/bundles/remote_services/rsa_common/src/endpoint_description.c
@@ -0,0 +1,89 @@
+/**
+ *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.
+ */
+/*
+ * endpoint_description.c
+ *
+ *  \date       25 Jul 2014
+ *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright  Apache License, Version 2.0
+ */
+#include <stdlib.h>
+#include <string.h>
+
+#include "celix_errno.h"
+#include "celix_log.h"
+
+#include "endpoint_description.h"
+#include "remote_constants.h"
+#include "constants.h"
+
+static celix_status_t endpointDescription_verifyLongProperty(properties_pt properties, char *propertyName, unsigned long *longProperty);
+
+celix_status_t endpointDescription_create(properties_pt properties, endpoint_description_pt *endpointDescription) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	unsigned long serviceId = 0UL;
+	status = endpointDescription_verifyLongProperty(properties, (char *) OSGI_RSA_ENDPOINT_SERVICE_ID, &serviceId);
+	if (status != CELIX_SUCCESS) {
+		return status;
+	}
+
+	endpoint_description_pt ep = calloc(1,sizeof(*ep));
+
+    ep->properties = properties;
+    ep->frameworkUUID = (char*)properties_get(properties, OSGI_RSA_ENDPOINT_FRAMEWORK_UUID);
+    ep->id = (char*)properties_get(properties, OSGI_RSA_ENDPOINT_ID);
+    ep->service = strndup(properties_get(properties, OSGI_FRAMEWORK_OBJECTCLASS), 1024*10);
+    ep->serviceId = serviceId;
+
+    if (!(ep->frameworkUUID) || !(ep->id) || !(ep->service) ) {
+    	fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "ENDPOINT_DESCRIPTION: incomplete description!.");
+    	status = CELIX_BUNDLE_EXCEPTION;
+    }
+
+    if(status == CELIX_SUCCESS){
+	*endpointDescription = ep;
+    }
+    else{
+	*endpointDescription = NULL;
+	free(ep);
+    }
+
+    return status;
+}
+
+celix_status_t endpointDescription_destroy(endpoint_description_pt description) {
+    properties_destroy(description->properties);
+    free(description->service);
+    free(description);
+    return CELIX_SUCCESS;
+}
+
+static celix_status_t endpointDescription_verifyLongProperty(properties_pt properties, char *propertyName, unsigned long *longProperty) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    const char *value = properties_get(properties, propertyName);
+    if (value == NULL) {
+        *longProperty = 0UL;
+    } else {
+        *longProperty = strtoul(value,NULL,10);
+    }
+
+    return status;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_common/src/export_registration_impl.c
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_common/src/export_registration_impl.c b/bundles/remote_services/rsa_common/src/export_registration_impl.c
new file mode 100644
index 0000000..1c684e7
--- /dev/null
+++ b/bundles/remote_services/rsa_common/src/export_registration_impl.c
@@ -0,0 +1,257 @@
+/**
+ *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.
+ */
+/*
+ * export_registration_impl.c
+ *
+ *  \date       Oct 6, 2011
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+#include <stdlib.h>
+
+#include "constants.h"
+
+#include "celix_errno.h"
+
+#include "export_registration_impl.h"
+#include "remote_service_admin_impl.h"
+
+
+struct export_reference {
+	endpoint_description_pt endpoint;
+	service_reference_pt reference;
+};
+
+celix_status_t exportRegistration_endpointAdding(void * handle, service_reference_pt reference, void **service);
+celix_status_t exportRegistration_endpointAdded(void * handle, service_reference_pt reference, void *service);
+celix_status_t exportRegistration_endpointModified(void * handle, service_reference_pt reference, void *service);
+celix_status_t exportRegistration_endpointRemoved(void * handle, service_reference_pt reference, void *service);
+
+celix_status_t exportRegistration_createEndpointTracker(export_registration_pt registration, service_tracker_pt *tracker);
+
+celix_status_t exportRegistration_create(log_helper_pt helper, service_reference_pt reference, endpoint_description_pt endpoint, remote_service_admin_pt rsa, bundle_context_pt context, export_registration_pt *registration) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	*registration = calloc(1, sizeof(**registration));
+	if (!*registration) {
+		status = CELIX_ENOMEM;
+	} else {
+		(*registration)->context = context;
+		(*registration)->closed = false;
+		(*registration)->endpointDescription = endpoint;
+		(*registration)->reference = reference;
+		(*registration)->rsa = rsa;
+		(*registration)->tracker = NULL;
+		(*registration)->endpoint = NULL;
+		(*registration)->endpointTracker = NULL;
+		(*registration)->exportReference = NULL;
+		(*registration)->bundle = NULL;
+		(*registration)->loghelper = helper;
+	}
+
+	return status;
+}
+
+celix_status_t exportRegistration_destroy(export_registration_pt *registration) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	remoteServiceAdmin_destroyEndpointDescription(&(*registration)->endpointDescription);
+	free(*registration);
+
+	return status;
+}
+
+celix_status_t exportRegistration_startTracking(export_registration_pt registration) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (registration->endpointTracker == NULL) {
+		status = exportRegistration_createEndpointTracker(registration, &registration->endpointTracker);
+		if (status == CELIX_SUCCESS) {
+			status = serviceTracker_open(registration->endpointTracker);
+		}
+	}
+
+	return status;
+}
+
+celix_status_t exportRegistration_stopTracking(export_registration_pt registration) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (registration->endpointTracker != NULL) {
+		status = serviceTracker_close(registration->endpointTracker);
+		if (status != CELIX_SUCCESS) {
+		    logHelper_log(registration->loghelper, OSGI_LOGSERVICE_ERROR, "EXPORT_REGISTRATION: Could not close endpoint tracker");
+		}
+		else {
+			status = serviceTracker_destroy(registration->endpointTracker);
+		}
+	}
+	if (registration->tracker != NULL) {
+		status = serviceTracker_close(registration->tracker);
+		if (status != CELIX_SUCCESS) {
+			logHelper_log(registration->loghelper, OSGI_LOGSERVICE_ERROR, "EXPORT_REGISTRATION: Could not close service tracker");
+		}
+		else {
+			status = serviceTracker_destroy(registration->tracker);
+		}
+	}
+
+	return status;
+}
+
+celix_status_t exportRegistration_createEndpointTracker(export_registration_pt registration, service_tracker_pt *tracker) {
+	celix_status_t status;
+
+	service_tracker_customizer_pt customizer = NULL;
+
+	status = serviceTrackerCustomizer_create(registration, exportRegistration_endpointAdding,
+			exportRegistration_endpointAdded, exportRegistration_endpointModified, exportRegistration_endpointRemoved, &customizer);
+
+	if (status == CELIX_SUCCESS) {
+		char filter[512];
+
+		snprintf(filter, 512, "(&(%s=%s)(remote.interface=%s))", (char*) OSGI_FRAMEWORK_OBJECTCLASS, (char*) OSGI_RSA_REMOTE_ENDPOINT, registration->endpointDescription->service);
+		status = serviceTracker_createWithFilter(registration->context, filter, customizer, tracker);
+	}
+
+	return status;
+}
+
+celix_status_t exportRegistration_endpointAdding(void * handle, service_reference_pt reference, void **service) {
+	celix_status_t status;
+	export_registration_pt registration = handle;
+
+	status = bundleContext_getService(registration->context, reference, service);
+
+	return status;
+}
+
+celix_status_t exportRegistration_endpointAdded(void * handle, service_reference_pt reference, void *endpoint_service) {
+	celix_status_t status = CELIX_SUCCESS;
+	export_registration_pt registration = handle;
+
+	remote_endpoint_service_pt endpoint = endpoint_service;
+	if (registration->endpoint == NULL) {
+		registration->endpoint = endpoint;
+		void *service = NULL;
+		status = bundleContext_getService(registration->context, registration->reference, &service);
+		if (status == CELIX_SUCCESS) {
+			endpoint->setService(endpoint->endpoint, service);
+		}
+	}
+
+	return status;
+}
+
+celix_status_t exportRegistration_endpointModified(void * handle, service_reference_pt reference, void *service) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	return status;
+}
+
+celix_status_t exportRegistration_endpointRemoved(void * handle, service_reference_pt reference, void *service) {
+	celix_status_t status = CELIX_SUCCESS;
+	export_registration_pt registration = handle;
+
+	remote_endpoint_service_pt endpoint = service;
+	if (registration->endpoint != NULL) {
+		endpoint->setService(endpoint->endpoint, NULL);
+	}
+
+	return status;
+}
+
+celix_status_t exportRegistration_open(export_registration_pt registration) {
+	celix_status_t status = CELIX_SUCCESS;
+	const char *bundleStore = NULL;
+
+	bundleContext_getProperty(registration->context, BUNDLE_STORE_PROPERTY_NAME, &bundleStore);
+
+	if (bundleStore == NULL) {
+		bundleStore = DEFAULT_BUNDLE_STORE;
+	}
+	char name[256];
+
+	snprintf(name, 256, "%s/%s_endpoint.zip", bundleStore, registration->endpointDescription->service);
+
+	status = bundleContext_installBundle(registration->context, name, &registration->bundle);
+	if (status == CELIX_SUCCESS) {
+		status = bundle_start(registration->bundle);
+		if (status == CELIX_SUCCESS) {
+		}
+	}
+
+	return status;
+}
+
+celix_status_t exportRegistration_close(export_registration_pt registration) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	exportRegistration_stopTracking(registration);
+
+	bundle_uninstall(registration->bundle);
+
+
+	return status;
+}
+
+celix_status_t exportRegistration_getException(export_registration_pt registration) {
+	celix_status_t status = CELIX_SUCCESS;
+	return status;
+}
+
+celix_status_t exportRegistration_getExportReference(export_registration_pt registration, export_reference_pt *reference) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	registration->exportReference = calloc(1, sizeof(*registration->exportReference));
+
+	if (registration->exportReference == NULL) {
+		status = CELIX_ENOMEM;
+	} else {
+		registration->exportReference->endpoint = registration->endpointDescription;
+		registration->exportReference->reference = registration->reference;
+	}
+	
+	*reference = registration->exportReference;
+
+	return status;
+}
+
+celix_status_t exportRegistration_setEndpointDescription(export_registration_pt registration, endpoint_description_pt endpointDescription) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	registration->endpointDescription = endpointDescription;
+
+	return status;
+}
+
+celix_status_t exportReference_getExportedEndpoint(export_reference_pt reference, endpoint_description_pt *endpoint) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	*endpoint = reference->endpoint;
+
+	return status;
+}
+
+celix_status_t exportReference_getExportedService(export_reference_pt reference, service_reference_pt *service) {
+	celix_status_t status = CELIX_SUCCESS;
+	*service = reference->reference;
+	return status;
+}
+

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_common/src/export_registration_impl.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_common/src/export_registration_impl.h b/bundles/remote_services/rsa_common/src/export_registration_impl.h
new file mode 100644
index 0000000..bb276f9
--- /dev/null
+++ b/bundles/remote_services/rsa_common/src/export_registration_impl.h
@@ -0,0 +1,61 @@
+/**
+ *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.
+ */
+/*
+ * export_registration_impl.h
+ *
+ *  \date       Oct 6, 2011
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef EXPORT_REGISTRATION_IMPL_H_
+#define EXPORT_REGISTRATION_IMPL_H_
+
+#include "remote_service_admin.h"
+#include "remote_endpoint.h"
+#include "service_tracker.h"
+#include "log_helper.h"
+
+struct export_registration {
+	bundle_context_pt context;
+	remote_service_admin_pt rsa;
+	endpoint_description_pt endpointDescription;
+	service_reference_pt reference;
+	log_helper_pt loghelper;
+
+	service_tracker_pt tracker;
+	service_tracker_pt endpointTracker;
+
+	remote_endpoint_service_pt endpoint;
+
+	export_reference_pt exportReference;
+	bundle_pt bundle;
+
+	bool closed;
+};
+
+celix_status_t exportRegistration_create(log_helper_pt helper, service_reference_pt reference, endpoint_description_pt endpoint, remote_service_admin_pt rsa, bundle_context_pt context, export_registration_pt *registration);
+celix_status_t exportRegistration_destroy(export_registration_pt *registration);
+celix_status_t exportRegistration_open(export_registration_pt registration);
+
+celix_status_t exportRegistration_setEndpointDescription(export_registration_pt registration, endpoint_description_pt endpointDescription);
+celix_status_t exportRegistration_startTracking(export_registration_pt registration);
+celix_status_t exportRegistration_stopTracking(export_registration_pt registration);
+
+#endif /* EXPORT_REGISTRATION_IMPL_H_ */