You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2017/11/24 10:59:09 UTC

[1/8] celix git commit: CELIX-417: Refactors CMake usage for the RSA bundles

Repository: celix
Updated Branches:
  refs/heads/feature/CELIX-417-cmake-refactor 2a670f265 -> 486d4f0d5


http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c b/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c
new file mode 100644
index 0000000..0b8dcf7
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c
@@ -0,0 +1,402 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <stdlib.h>
+#include <jansson.h>
+#include <json_rpc.h>
+#include <assert.h>
+#include "version.h"
+#include "json_serializer.h"
+#include "dyn_interface.h"
+#include "import_registration.h"
+#include "import_registration_dfi.h"
+
+struct import_registration {
+    bundle_context_pt context;
+    endpoint_description_pt  endpoint; //TODO owner? -> free when destroyed
+    const char *classObject; //NOTE owned by endpoint
+    version_pt version;
+
+    celix_thread_mutex_t mutex; //protects send & sendhandle
+    send_func_type send;
+    void *sendHandle;
+
+    service_factory_pt factory;
+    service_registration_pt factoryReg;
+
+    hash_map_pt proxies; //key -> bundle, value -> service_proxy
+    celix_thread_mutex_t proxiesMutex; //protects proxies
+};
+
+struct service_proxy {
+    dyn_interface_type *intf;
+    void *service;
+    size_t count;
+};
+
+static celix_status_t importRegistration_createProxy(import_registration_pt import, bundle_pt bundle,
+                                              struct service_proxy **proxy);
+static void importRegistration_proxyFunc(void *userData, void *args[], void *returnVal);
+static void importRegistration_destroyProxy(struct service_proxy *proxy);
+static void importRegistration_clearProxies(import_registration_pt import);
+
+celix_status_t importRegistration_create(bundle_context_pt context, endpoint_description_pt endpoint, const char *classObject, const char* serviceVersion,
+                                         import_registration_pt *out) {
+    celix_status_t status = CELIX_SUCCESS;
+    import_registration_pt reg = calloc(1, sizeof(*reg));
+
+    if (reg != NULL) {
+        reg->factory = calloc(1, sizeof(*reg->factory));
+    }
+
+    if (reg != NULL && reg->factory != NULL) {
+        reg->context = context;
+        reg->endpoint = endpoint;
+        reg->classObject = classObject;
+        reg->proxies = hashMap_create(NULL, NULL, NULL, NULL);
+
+        celixThreadMutex_create(&reg->mutex, NULL);
+        celixThreadMutex_create(&reg->proxiesMutex, NULL);
+        status = version_createVersionFromString((char*)serviceVersion,&(reg->version));
+
+        reg->factory->handle = reg;
+        reg->factory->getService = (void *)importRegistration_getService;
+        reg->factory->ungetService = (void *)importRegistration_ungetService;
+    } else {
+        status = CELIX_ENOMEM;
+    }
+
+    if (status == CELIX_SUCCESS) {
+        //printf("IMPORT REGISTRATION IS %p\n", reg);
+        *out = reg;
+    }
+    else{
+    	importRegistration_destroy(reg);
+    }
+
+    return status;
+}
+
+
+celix_status_t importRegistration_setSendFn(import_registration_pt reg,
+                                            send_func_type send,
+                                            void *handle) {
+    celixThreadMutex_lock(&reg->mutex);
+    reg->send = send;
+    reg->sendHandle = handle;
+    celixThreadMutex_unlock(&reg->mutex);
+
+    return CELIX_SUCCESS;
+}
+
+static void importRegistration_clearProxies(import_registration_pt import) {
+    if (import != NULL) {
+        pthread_mutex_lock(&import->proxiesMutex);
+        if (import->proxies != NULL) {
+            hash_map_iterator_pt iter = hashMapIterator_create(import->proxies);
+            while (hashMapIterator_hasNext(iter)) {
+                hash_map_entry_pt  entry = hashMapIterator_nextEntry(iter);
+                struct service_proxy *proxy = hashMapEntry_getValue(entry);
+                importRegistration_destroyProxy(proxy);
+            }
+            hashMapIterator_destroy(iter);
+        }
+        pthread_mutex_unlock(&import->proxiesMutex);
+    }
+}
+
+void importRegistration_destroy(import_registration_pt import) {
+    if (import != NULL) {
+        if (import->proxies != NULL) {
+            hashMap_destroy(import->proxies, false, false);
+            import->proxies = NULL;
+        }
+
+        pthread_mutex_destroy(&import->mutex);
+        pthread_mutex_destroy(&import->proxiesMutex);
+
+        if (import->factory != NULL) {
+            free(import->factory);
+        }
+
+        if(import->version!=NULL){
+        	version_destroy(import->version);
+        }
+        free(import);
+    }
+}
+
+celix_status_t importRegistration_start(import_registration_pt import) {
+    celix_status_t  status = CELIX_SUCCESS;
+    if (import->factoryReg == NULL && import->factory != NULL) {
+        properties_pt props = NULL;
+        properties_copy(import->endpoint->properties, &props);
+        status = bundleContext_registerServiceFactory(import->context, (char *)import->classObject, import->factory, props, &import->factoryReg);
+    } else {
+        status = CELIX_ILLEGAL_STATE;
+    }
+    return status;
+}
+
+celix_status_t importRegistration_stop(import_registration_pt import) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    if (import->factoryReg != NULL) {
+        serviceRegistration_unregister(import->factoryReg);
+        import->factoryReg = NULL;
+    }
+
+    importRegistration_clearProxies(import);
+
+    return status;
+}
+
+
+celix_status_t importRegistration_getService(import_registration_pt import, bundle_pt bundle, service_registration_pt registration, void **out) {
+    celix_status_t  status = CELIX_SUCCESS;
+
+    /*
+    module_pt module = NULL;
+    char *name = NULL;
+    bundle_getCurrentModule(bundle, &module);
+    module_getSymbolicName(module, &name);
+    printf("getting service for bundle '%s'\n", name);
+     */
+
+
+    pthread_mutex_lock(&import->proxiesMutex);
+    struct service_proxy *proxy = hashMap_get(import->proxies, bundle);
+    if (proxy == NULL) {
+        status = importRegistration_createProxy(import, bundle, &proxy);
+        if (status == CELIX_SUCCESS) {
+            hashMap_put(import->proxies, bundle, proxy);
+        }
+    }
+
+    if (status == CELIX_SUCCESS) {
+        proxy->count += 1;
+        *out = proxy->service;
+    }
+    pthread_mutex_unlock(&import->proxiesMutex);
+
+    return status;
+}
+
+static celix_status_t importRegistration_createProxy(import_registration_pt import, bundle_pt bundle, struct service_proxy **out) {
+    celix_status_t  status;
+    dyn_interface_type* intf = NULL;
+    FILE *descriptor = NULL;
+
+    status = dfi_findDescriptor(import->context, bundle, import->classObject, &descriptor);
+
+    if (status != CELIX_SUCCESS || descriptor == NULL) {
+        //TODO use log helper logHelper_log(helper, OSGI_LOGSERVICE_ERROR, "Cannot find/open descriptor for '%s'", import->classObject);
+        fprintf(stderr, "RSA_DFI: Cannot find/open descriptor for '%s'", import->classObject);
+        return CELIX_BUNDLE_EXCEPTION;
+    }
+
+    if (status == CELIX_SUCCESS) {
+        int rc = dynInterface_parse(descriptor, &intf);
+        fclose(descriptor);
+        if (rc != 0 || intf==NULL) {
+            return CELIX_BUNDLE_EXCEPTION;
+        }
+    }
+
+    /* Check if the imported service version is compatible with the one in the consumer descriptor */
+    version_pt consumerVersion = NULL;
+    bool isCompatible = false;
+    dynInterface_getVersion(intf,&consumerVersion);
+    version_isCompatible(consumerVersion,import->version,&isCompatible);
+
+    if(!isCompatible){
+    	char* cVerString = NULL;
+    	char* pVerString = NULL;
+    	version_toString(consumerVersion,&cVerString);
+    	version_toString(import->version,&pVerString);
+    	printf("Service version mismatch: consumer has %s, provider has %s. NOT creating proxy.\n",cVerString,pVerString);
+    	dynInterface_destroy(intf);
+    	free(cVerString);
+    	free(pVerString);
+    	status = CELIX_SERVICE_EXCEPTION;
+    }
+
+    struct service_proxy *proxy = NULL;
+    if (status == CELIX_SUCCESS) {
+        proxy = calloc(1, sizeof(*proxy));
+        if (proxy == NULL) {
+            status = CELIX_ENOMEM;
+        }
+    }
+
+    if (status == CELIX_SUCCESS) {
+    	proxy->intf = intf;
+        size_t count = dynInterface_nrOfMethods(proxy->intf);
+        proxy->service = calloc(1 + count, sizeof(void *));
+        if (proxy->service == NULL) {
+            status = CELIX_ENOMEM;
+        }
+    }
+
+    if (status == CELIX_SUCCESS) {
+        void **serv = proxy->service;
+        serv[0] = import;
+
+        struct methods_head *list = NULL;
+        dynInterface_methods(proxy->intf, &list);
+        struct method_entry *entry = NULL;
+        void (*fn)(void) = NULL;
+        int index = 0;
+        TAILQ_FOREACH(entry, list, entries) {
+            int rc = dynFunction_createClosure(entry->dynFunc, importRegistration_proxyFunc, entry, &fn);
+            serv[index + 1] = fn;
+            index += 1;
+
+            if (rc != 0) {
+                status = CELIX_BUNDLE_EXCEPTION;
+                break;
+            }
+        }
+    }
+
+    if (status == CELIX_SUCCESS) {
+        *out = proxy;
+    } else if (proxy != NULL) {
+        if (proxy->intf != NULL) {
+            dynInterface_destroy(proxy->intf);
+            proxy->intf = NULL;
+        }
+        free(proxy->service);
+        free(proxy);
+    }
+
+    return status;
+}
+
+static void importRegistration_proxyFunc(void *userData, void *args[], void *returnVal) {
+    int  status = CELIX_SUCCESS;
+    struct method_entry *entry = userData;
+    import_registration_pt import = *((void **)args[0]);
+
+    if (import == NULL || import->send == NULL) {
+        status = CELIX_ILLEGAL_ARGUMENT;
+    }
+
+
+    char *invokeRequest = NULL;
+    if (status == CELIX_SUCCESS) {
+        status = jsonRpc_prepareInvokeRequest(entry->dynFunc, entry->id, args, &invokeRequest);
+        //printf("Need to send following json '%s'\n", invokeRequest);
+    }
+
+
+    if (status == CELIX_SUCCESS) {
+        char *reply = NULL;
+        int rc = 0;
+        //printf("sending request\n");
+        celixThreadMutex_lock(&import->mutex);
+        if (import->send != NULL) {
+            import->send(import->sendHandle, import->endpoint, invokeRequest, &reply, &rc);
+        }
+        celixThreadMutex_unlock(&import->mutex);
+        //printf("request sended. got reply '%s' with status %i\n", reply, rc);
+
+        if (rc == 0) {
+            //fjprintf("Handling reply '%s'\n", reply);
+            status = jsonRpc_handleReply(entry->dynFunc, reply, args);
+        }
+
+        *(int *) returnVal = rc;
+
+        free(invokeRequest); //Allocated by json_dumps in jsonRpc_prepareInvokeRequest
+        free(reply); //Allocated by json_dumps in remoteServiceAdmin_send through curl call
+    }
+
+    if (status != CELIX_SUCCESS) {
+        //TODO log error
+    }
+}
+
+celix_status_t importRegistration_ungetService(import_registration_pt import, bundle_pt bundle, service_registration_pt registration, void **out) {
+    celix_status_t  status = CELIX_SUCCESS;
+
+    assert(import != NULL);
+    assert(import->proxies != NULL);
+
+    pthread_mutex_lock(&import->proxiesMutex);
+
+    struct service_proxy *proxy = hashMap_get(import->proxies, bundle);
+    if (proxy != NULL) {
+        if (*out == proxy->service) {
+            proxy->count -= 1;
+        } else {
+            status = CELIX_ILLEGAL_ARGUMENT;
+        }
+
+        if (proxy->count == 0) {
+            hashMap_remove(import->proxies, bundle);
+            importRegistration_destroyProxy(proxy);
+        }
+    }
+
+    pthread_mutex_unlock(&import->proxiesMutex);
+
+    return status;
+}
+
+static void importRegistration_destroyProxy(struct service_proxy *proxy) {
+    if (proxy != NULL) {
+        if (proxy->intf != NULL) {
+            dynInterface_destroy(proxy->intf);
+        }
+        if (proxy->service != NULL) {
+            free(proxy->service);
+        }
+        free(proxy);
+    }
+}
+
+
+celix_status_t importRegistration_close(import_registration_pt registration) {
+    celix_status_t status = CELIX_SUCCESS;
+    importRegistration_stop(registration);
+    return status;
+}
+
+celix_status_t importRegistration_getException(import_registration_pt registration) {
+    celix_status_t status = CELIX_SUCCESS;
+    //TODO
+    return status;
+}
+
+celix_status_t importRegistration_getImportReference(import_registration_pt registration, import_reference_pt *reference) {
+    celix_status_t status = CELIX_SUCCESS;
+    //TODO
+    return status;
+}
+
+celix_status_t importReference_getImportedEndpoint(import_reference_pt reference) {
+    celix_status_t status = CELIX_SUCCESS;
+    return status;
+}
+
+celix_status_t importReference_getImportedService(import_reference_pt reference) {
+    celix_status_t status = CELIX_SUCCESS;
+    return status;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/src/import_registration_dfi.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/src/import_registration_dfi.h b/remote_services/remote_service_admin_dfi/src/import_registration_dfi.h
new file mode 100644
index 0000000..aac4bc7
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/src/import_registration_dfi.h
@@ -0,0 +1,44 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CELIX_IMPORT_REGISTRATION_DFI_H
+#define CELIX_IMPORT_REGISTRATION_DFI_H
+
+#include "import_registration.h"
+#include "dfi_utils.h"
+
+#include <celix_errno.h>
+
+typedef void (*send_func_type)(void *handle, endpoint_description_pt endpointDescription, char *request, char **reply, int* replyStatus);
+
+celix_status_t importRegistration_create(bundle_context_pt context, endpoint_description_pt description, const char *classObject, const char* serviceVersion,
+                                         import_registration_pt *import);
+celix_status_t importRegistration_close(import_registration_pt import);
+void importRegistration_destroy(import_registration_pt import);
+
+celix_status_t importRegistration_setSendFn(import_registration_pt reg,
+                                            send_func_type,
+                                            void *handle);
+celix_status_t importRegistration_start(import_registration_pt import);
+celix_status_t importRegistration_stop(import_registration_pt import);
+
+celix_status_t importRegistration_getService(import_registration_pt import, bundle_pt bundle, service_registration_pt registration, void **service);
+celix_status_t importRegistration_ungetService(import_registration_pt import, bundle_pt bundle, service_registration_pt registration, void **service);
+
+#endif //CELIX_IMPORT_REGISTRATION_DFI_H

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/src/remote_service_admin_activator.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/src/remote_service_admin_activator.c b/remote_services/remote_service_admin_dfi/src/remote_service_admin_activator.c
new file mode 100644
index 0000000..d4cc765
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/src/remote_service_admin_activator.c
@@ -0,0 +1,124 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * remote_service_admin_activator.c
+ *
+ *  \date       Sep 30, 2011
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+#include <stdlib.h>
+#include <remote_service_admin.h>
+
+#include "remote_service_admin_dfi.h"
+
+#include "bundle_activator.h"
+#include "service_registration.h"
+
+#include "export_registration_dfi.h"
+#include "import_registration_dfi.h"
+
+struct activator {
+	remote_service_admin_pt admin;
+	remote_service_admin_service_pt adminService;
+	service_registration_pt registration;
+};
+
+celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) {
+	celix_status_t status = CELIX_SUCCESS;
+	struct activator *activator;
+
+	activator = calloc(1, sizeof(*activator));
+	if (!activator) {
+		status = CELIX_ENOMEM;
+	} else {
+		activator->admin = NULL;
+		activator->registration = NULL;
+
+		*userData = activator;
+	}
+
+	return status;
+}
+
+celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
+	celix_status_t status = CELIX_SUCCESS;
+	struct activator *activator = userData;
+	remote_service_admin_service_pt remoteServiceAdmin = NULL;
+
+	status = remoteServiceAdmin_create(context, &activator->admin);
+	if (status == CELIX_SUCCESS) {
+		remoteServiceAdmin = calloc(1, sizeof(*remoteServiceAdmin));
+		if (!remoteServiceAdmin) {
+			status = CELIX_ENOMEM;
+		} else {
+			remoteServiceAdmin->admin = activator->admin;
+			remoteServiceAdmin->exportService = remoteServiceAdmin_exportService;
+
+			remoteServiceAdmin->getExportedServices = remoteServiceAdmin_getExportedServices;
+			remoteServiceAdmin->getImportedEndpoints = remoteServiceAdmin_getImportedEndpoints;
+			remoteServiceAdmin->importService = remoteServiceAdmin_importService;
+
+			remoteServiceAdmin->exportReference_getExportedEndpoint = exportReference_getExportedEndpoint;
+			remoteServiceAdmin->exportReference_getExportedService = exportReference_getExportedService;
+
+			remoteServiceAdmin->exportRegistration_close = remoteServiceAdmin_removeExportedService;
+			remoteServiceAdmin->exportRegistration_getException = exportRegistration_getException;
+			remoteServiceAdmin->exportRegistration_getExportReference = exportRegistration_getExportReference;
+
+			remoteServiceAdmin->importReference_getImportedEndpoint = importReference_getImportedEndpoint;
+			remoteServiceAdmin->importReference_getImportedService = importReference_getImportedService;
+
+			remoteServiceAdmin->importRegistration_close = remoteServiceAdmin_removeImportedService;
+			remoteServiceAdmin->importRegistration_getException = importRegistration_getException;
+			remoteServiceAdmin->importRegistration_getImportReference = importRegistration_getImportReference;
+
+			status = bundleContext_registerService(context, OSGI_RSA_REMOTE_SERVICE_ADMIN, remoteServiceAdmin, NULL, &activator->registration);
+			activator->adminService = remoteServiceAdmin;
+		}
+	}
+
+	return status;
+}
+
+celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) {
+    celix_status_t status = CELIX_SUCCESS;
+    struct activator *activator = userData;
+
+    serviceRegistration_unregister(activator->registration);
+    activator->registration = NULL;
+
+    remoteServiceAdmin_stop(activator->admin);
+    remoteServiceAdmin_destroy(&activator->admin);
+
+    free(activator->adminService);
+
+    return status;
+}
+
+celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) {
+	celix_status_t status = CELIX_SUCCESS;
+	struct activator *activator = userData;
+
+	free(activator);
+
+	return status;
+}
+
+

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.c b/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.c
new file mode 100644
index 0000000..6effc94
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.c
@@ -0,0 +1,771 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * remote_service_admin_impl.c
+ *
+ *  \date       May 21, 2015
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <ifaddrs.h>
+#include <string.h>
+#include <uuid/uuid.h>
+#include <curl/curl.h>
+
+#include <jansson.h>
+#include "json_serializer.h"
+#include "remote_service_admin.h"
+
+#include "import_registration_dfi.h"
+#include "export_registration_dfi.h"
+#include "remote_service_admin_dfi.h"
+#include "json_rpc.h"
+
+#include "remote_constants.h"
+#include "constants.h"
+#include "civetweb.h"
+
+// defines how often the webserver is restarted (with an increased port number)
+#define MAX_NUMBER_OF_RESTARTS 	5
+
+
+#define RSA_LOG_ERROR(admin, msg, ...) \
+    logHelper_log((admin)->loghelper, OSGI_LOGSERVICE_ERROR, (msg),  ##__VA_ARGS__)
+
+#define RSA_LOG_WARNING(admin, msg, ...) \
+    logHelper_log((admin)->loghelper, OSGI_LOGSERVICE_ERROR, (msg),  ##__VA_ARGS__)
+
+#define RSA_LOG_DEBUG(admin, msg, ...) \
+    logHelper_log((admin)->loghelper, OSGI_LOGSERVICE_ERROR, (msg),  ##__VA_ARGS__)
+
+struct remote_service_admin {
+    bundle_context_pt context;
+    log_helper_pt loghelper;
+
+    celix_thread_mutex_t exportedServicesLock;
+    hash_map_pt exportedServices;
+
+    celix_thread_mutex_t importedServicesLock;
+    array_list_pt importedServices;
+
+    char *port;
+    char *ip;
+
+    struct mg_context *ctx;
+};
+
+struct post {
+    const char *readptr;
+    int size;
+};
+
+struct get {
+    char *writeptr;
+    int size;
+};
+
+#define OSGI_RSA_REMOTE_PROXY_FACTORY 	"remote_proxy_factory"
+#define OSGI_RSA_REMOTE_PROXY_TIMEOUT   "remote_proxy_timeout"
+
+static const char *data_response_headers =
+        "HTTP/1.1 200 OK\r\n"
+                "Cache: no-cache\r\n"
+                "Content-Type: application/json\r\n"
+                "\r\n";
+
+static const char *no_content_response_headers =
+        "HTTP/1.1 204 OK\r\n";
+
+// TODO do we need to specify a non-Amdatu specific configuration type?!
+static const char * const CONFIGURATION_TYPE = "org.amdatu.remote.admin.http";
+static const char * const ENDPOINT_URL = "org.amdatu.remote.admin.http.url";
+
+static const char *DEFAULT_PORT = "8888";
+static const char *DEFAULT_IP = "127.0.0.1";
+
+static const unsigned int DEFAULT_TIMEOUT = 0;
+
+static int remoteServiceAdmin_callback(struct mg_connection *conn);
+static celix_status_t remoteServiceAdmin_createEndpointDescription(remote_service_admin_pt admin, service_reference_pt reference, properties_pt props, char *interface, endpoint_description_pt *description);
+static celix_status_t remoteServiceAdmin_send(void *handle, endpoint_description_pt endpointDescription, char *request, char **reply, int* replyStatus);
+static celix_status_t remoteServiceAdmin_getIpAdress(char* interface, char** ip);
+static size_t remoteServiceAdmin_readCallback(void *ptr, size_t size, size_t nmemb, void *userp);
+static size_t remoteServiceAdmin_write(void *contents, size_t size, size_t nmemb, void *userp);
+static void remoteServiceAdmin_log(remote_service_admin_pt admin, int level, const char *file, int line, const char *msg, ...);
+
+celix_status_t remoteServiceAdmin_create(bundle_context_pt context, remote_service_admin_pt *admin) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    *admin = calloc(1, sizeof(**admin));
+
+    if (!*admin) {
+        status = CELIX_ENOMEM;
+    } else {
+        unsigned int port_counter = 0;
+        const char *port = NULL;
+        const char *ip = NULL;
+        char *detectedIp = NULL;
+        (*admin)->context = context;
+        (*admin)->exportedServices = hashMap_create(NULL, NULL, NULL, NULL);
+         arrayList_create(&(*admin)->importedServices);
+
+        celixThreadMutex_create(&(*admin)->exportedServicesLock, NULL);
+        celixThreadMutex_create(&(*admin)->importedServicesLock, NULL);
+
+        if (logHelper_create(context, &(*admin)->loghelper) == CELIX_SUCCESS) {
+            logHelper_start((*admin)->loghelper);
+            dynCommon_logSetup((void *)remoteServiceAdmin_log, *admin, 1);
+            dynType_logSetup((void *)remoteServiceAdmin_log, *admin, 1);
+            dynFunction_logSetup((void *)remoteServiceAdmin_log, *admin, 1);
+            dynInterface_logSetup((void *)remoteServiceAdmin_log, *admin, 1);
+            jsonSerializer_logSetup((void *)remoteServiceAdmin_log, *admin, 1);
+            jsonRpc_logSetup((void *)remoteServiceAdmin_log, *admin, 1);
+        }
+
+        bundleContext_getProperty(context, "RSA_PORT", &port);
+        if (port == NULL) {
+            port = (char *)DEFAULT_PORT;
+        }
+
+        bundleContext_getProperty(context, "RSA_IP", &ip);
+        if (ip == NULL) {
+            const char *interface = NULL;
+
+            bundleContext_getProperty(context, "RSA_INTERFACE", &interface);
+            if ((interface != NULL) && (remoteServiceAdmin_getIpAdress((char*)interface, &detectedIp) != CELIX_SUCCESS)) {
+                logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "RSA: Could not retrieve IP adress for interface %s", interface);
+            }
+
+            if (ip == NULL) {
+                remoteServiceAdmin_getIpAdress(NULL, &detectedIp);
+            }
+
+            ip = detectedIp;
+        }
+
+        if (ip != NULL) {
+            logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Using %s for service annunciation", ip);
+            (*admin)->ip = strdup(ip);
+        }
+        else {
+            logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "RSA: No IP address for service annunciation set. Using %s", DEFAULT_IP);
+            (*admin)->ip = strdup((char*) DEFAULT_IP);
+        }
+
+        if (detectedIp != NULL) {
+            free(detectedIp);
+        }
+
+        // Prepare callbacks structure. We have only one callback, the rest are NULL.
+        struct mg_callbacks callbacks;
+        memset(&callbacks, 0, sizeof(callbacks));
+        callbacks.begin_request = remoteServiceAdmin_callback;
+
+        char newPort[10];
+
+        do {
+
+            const char *options[] = { "listening_ports", port, "num_threads", "5", NULL};
+
+            (*admin)->ctx = mg_start(&callbacks, (*admin), options);
+
+            if ((*admin)->ctx != NULL) {
+                logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Start webserver: %s", port);
+                (*admin)->port = strdup(port);
+
+            }
+            else {
+            	errno = 0;
+                char* endptr = (char*)port;
+                int currentPort = strtol(port, &endptr, 10);
+
+                if (*endptr || errno != 0) {
+                    currentPort = strtol(DEFAULT_PORT, NULL, 10);
+                }
+
+                port_counter++;
+                snprintf(&newPort[0], 6,  "%d", (currentPort+1));
+
+                logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_ERROR, "Error while starting rsa server on port %s - retrying on port %s...", port, newPort);
+                port = newPort;
+            }
+        } while(((*admin)->ctx == NULL) && (port_counter < MAX_NUMBER_OF_RESTARTS));
+
+    }
+
+    return status;
+}
+
+
+celix_status_t remoteServiceAdmin_destroy(remote_service_admin_pt *admin)
+{
+    celix_status_t status = CELIX_SUCCESS;
+
+    free((*admin)->ip);
+    free((*admin)->port);
+    free(*admin);
+
+    //TODO destroy exports/imports
+
+    *admin = NULL;
+
+    return status;
+}
+
+
+celix_status_t remoteServiceAdmin_stop(remote_service_admin_pt admin) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    celixThreadMutex_lock(&admin->exportedServicesLock);
+
+    hash_map_iterator_pt iter = hashMapIterator_create(admin->exportedServices);
+    while (hashMapIterator_hasNext(iter)) {
+        array_list_pt exports = hashMapIterator_nextValue(iter);
+        int i;
+        for (i = 0; i < arrayList_size(exports); i++) {
+            export_registration_pt export = arrayList_get(exports, i);
+            if (export != NULL) {
+                exportRegistration_stop(export);
+                exportRegistration_destroy(export);
+            }
+        }
+        arrayList_destroy(exports);
+    }
+    hashMapIterator_destroy(iter);
+    celixThreadMutex_unlock(&admin->exportedServicesLock);
+
+    celixThreadMutex_lock(&admin->importedServicesLock);
+    int i;
+    int size = arrayList_size(admin->importedServices);
+    for (i = 0; i < size ; i += 1) {
+        import_registration_pt import = arrayList_get(admin->importedServices, i);
+        if (import != NULL) {
+            importRegistration_stop(import);
+            importRegistration_destroy(import);
+        }
+    }
+    celixThreadMutex_unlock(&admin->importedServicesLock);
+
+    if (admin->ctx != NULL) {
+        logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Stopping webserver...");
+        mg_stop(admin->ctx);
+        admin->ctx = NULL;
+    }
+
+    hashMap_destroy(admin->exportedServices, false, false);
+    arrayList_destroy(admin->importedServices);
+
+    logHelper_stop(admin->loghelper);
+    logHelper_destroy(&admin->loghelper);
+
+    return status;
+}
+
+/**
+ * Request: http://host:port/services/{service}/{request}
+ */
+//void *remoteServiceAdmin_callback(enum mg_event event, struct mg_connection *conn, const struct mg_request_info *request_info) {
+
+celix_status_t importRegistration_getFactory(import_registration_pt import, service_factory_pt *factory);
+
+static int remoteServiceAdmin_callback(struct mg_connection *conn) {
+    int result = 1; // zero means: let civetweb handle it further, any non-zero value means it is handled by us...
+
+    const struct mg_request_info *request_info = mg_get_request_info(conn);
+    if (request_info->uri != NULL) {
+        remote_service_admin_pt rsa = request_info->user_data;
+
+
+        if (strncmp(request_info->uri, "/service/", 9) == 0 && strcmp("POST", request_info->request_method) == 0) {
+
+            // uri = /services/myservice/call
+            const char *uri = request_info->uri;
+            // rest = myservice/call
+
+            const char *rest = uri+9;
+            char *interfaceStart = strchr(rest, '/');
+            int pos = interfaceStart - rest;
+            char service[pos+1];
+            strncpy(service, rest, pos);
+            service[pos] = '\0';
+            unsigned long serviceId = strtoul(service,NULL,10);
+
+            celixThreadMutex_lock(&rsa->exportedServicesLock);
+
+            //find endpoint
+            export_registration_pt export = NULL;
+            hash_map_iterator_pt iter = hashMapIterator_create(rsa->exportedServices);
+            while (hashMapIterator_hasNext(iter)) {
+                hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+                array_list_pt exports = hashMapEntry_getValue(entry);
+                int expIt = 0;
+                for (expIt = 0; expIt < arrayList_size(exports); expIt++) {
+                    export_registration_pt check = arrayList_get(exports, expIt);
+                    export_reference_pt  ref = NULL;
+                    exportRegistration_getExportReference(check, &ref);
+                    endpoint_description_pt  checkEndpoint = NULL;
+                    exportReference_getExportedEndpoint(ref, &checkEndpoint);
+                    if (serviceId == checkEndpoint->serviceId) {
+                        export = check;
+                        free(ref);
+                        break;
+                    }
+                    free(ref);
+                }
+            }
+            hashMapIterator_destroy(iter);
+
+            if (export != NULL) {
+
+                uint64_t datalength = request_info->content_length;
+                char* data = malloc(datalength + 1);
+                mg_read(conn, data, datalength);
+                data[datalength] = '\0';
+
+                char *response = NULL;
+                int responceLength = 0;
+                int rc = exportRegistration_call(export, data, -1, &response, &responceLength);
+                if (rc != CELIX_SUCCESS) {
+                    RSA_LOG_ERROR(rsa, "Error trying to invoke remove service, got error %i\n", rc);
+                }
+
+                if (rc == CELIX_SUCCESS && response != NULL) {
+                    mg_write(conn, data_response_headers, strlen(data_response_headers));
+                    mg_write(conn, response, strlen(response));
+                    free(response);
+                } else {
+                    mg_write(conn, no_content_response_headers, strlen(no_content_response_headers));
+                }
+                result = 1;
+
+                free(data);
+            } else {
+                result = 0;
+                RSA_LOG_WARNING(rsa, "NO export registration found for service id %lu", serviceId);
+            }
+
+            celixThreadMutex_unlock(&rsa->exportedServicesLock);
+
+        }
+    }
+
+    return result;
+}
+
+celix_status_t remoteServiceAdmin_exportService(remote_service_admin_pt admin, char *serviceId, properties_pt properties, array_list_pt *registrations) {
+    celix_status_t status;
+
+    arrayList_create(registrations);
+    array_list_pt references = NULL;
+    service_reference_pt reference = NULL;
+    char filter [256];
+
+    snprintf(filter, 256, "(%s=%s)", (char *)OSGI_FRAMEWORK_SERVICE_ID, serviceId);
+
+    status = bundleContext_getServiceReferences(admin->context, NULL, filter, &references);
+
+    logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "RSA: exportService called for serviceId %s", serviceId);
+
+    int i;
+    int size = arrayList_size(references);
+    for (i = 0; i < size; i += 1) {
+        if (i == 0) {
+            reference = arrayList_get(references, i);
+        } else {
+            bundleContext_ungetServiceReference(admin->context, arrayList_get(references, i));
+        }
+    }
+    arrayList_destroy(references);
+
+    if (reference == NULL) {
+        logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "ERROR: expected a reference for service id %s.", serviceId);
+        status = CELIX_ILLEGAL_STATE;
+    }
+
+    const char *exports = NULL;
+    const char *provided = NULL;
+    if (status == CELIX_SUCCESS) {
+        serviceReference_getProperty(reference, (char *) OSGI_RSA_SERVICE_EXPORTED_INTERFACES, &exports);
+        serviceReference_getProperty(reference, (char *) OSGI_FRAMEWORK_OBJECTCLASS, &provided);
+
+        if (exports == NULL || provided == NULL || strcmp(exports, provided) != 0) {
+            logHelper_log(admin->loghelper, OSGI_LOGSERVICE_WARNING, "RSA: No Services to export.");
+            status = CELIX_ILLEGAL_STATE;
+        } else {
+            logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Export service (%s)", provided);
+        }
+    }
+
+    if (status == CELIX_SUCCESS) {
+        const char *interface = provided;
+        endpoint_description_pt endpoint = NULL;
+        export_registration_pt registration = NULL;
+
+        remoteServiceAdmin_createEndpointDescription(admin, reference, properties, (char*)interface, &endpoint);
+        //TODO precheck if descriptor exists
+        status = exportRegistration_create(admin->loghelper, reference, endpoint, admin->context, &registration);
+        if (status == CELIX_SUCCESS) {
+            status = exportRegistration_start(registration);
+            if (status == CELIX_SUCCESS) {
+                arrayList_add(*registrations, registration);
+            }
+        }
+    }
+
+
+    if (status == CELIX_SUCCESS) {
+        celixThreadMutex_lock(&admin->exportedServicesLock);
+        hashMap_put(admin->exportedServices, reference, *registrations);
+        celixThreadMutex_unlock(&admin->exportedServicesLock);
+    }
+    else{
+    	arrayList_destroy(*registrations);
+    	*registrations = NULL;
+    }
+
+    return status;
+}
+
+celix_status_t remoteServiceAdmin_removeExportedService(remote_service_admin_pt admin, export_registration_pt registration) {
+    celix_status_t status;
+
+    logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA_DFI: Removing exported service");
+
+    export_reference_pt  ref = NULL;
+    status = exportRegistration_getExportReference(registration, &ref);
+
+    if (status == CELIX_SUCCESS && ref != NULL) {
+    	service_reference_pt servRef;
+        celixThreadMutex_lock(&admin->exportedServicesLock);
+    	exportReference_getExportedService(ref, &servRef);
+
+    	array_list_pt exports = (array_list_pt)hashMap_remove(admin->exportedServices, servRef);
+    	if(exports!=NULL){
+    		arrayList_destroy(exports);
+    	}
+
+        exportRegistration_close(registration);
+        exportRegistration_destroy(registration);
+
+        celixThreadMutex_unlock(&admin->exportedServicesLock);
+
+        free(ref);
+
+    } else {
+    	logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "Cannot find reference for registration");
+    }
+
+    return status;
+}
+
+static celix_status_t remoteServiceAdmin_createEndpointDescription(remote_service_admin_pt admin, service_reference_pt reference, properties_pt props, char *interface, endpoint_description_pt *endpoint) {
+
+    celix_status_t status = CELIX_SUCCESS;
+    properties_pt endpointProperties = properties_create();
+
+
+    unsigned int size = 0;
+    char **keys;
+
+    serviceReference_getPropertyKeys(reference, &keys, &size);
+    for (int i = 0; i < size; i++) {
+        char *key = keys[i];
+        const char *value = NULL;
+
+        if (serviceReference_getProperty(reference, key, &value) == CELIX_SUCCESS
+            && strcmp(key, (char*) OSGI_RSA_SERVICE_EXPORTED_INTERFACES) != 0
+            && strcmp(key, (char*) OSGI_FRAMEWORK_OBJECTCLASS) != 0) {
+            properties_set(endpointProperties, key, value);
+        }
+    }
+
+    hash_map_entry_pt entry = hashMap_getEntry(endpointProperties, (void *) OSGI_FRAMEWORK_SERVICE_ID);
+
+    char* key = hashMapEntry_getKey(entry);
+    char *serviceId = (char *) hashMap_remove(endpointProperties, (void *) OSGI_FRAMEWORK_SERVICE_ID);
+    const char *uuid = NULL;
+
+    char buf[512];
+    snprintf(buf, 512,  "/service/%s/%s", serviceId, interface);
+
+    char url[1024];
+    snprintf(url, 1024, "http://%s:%s%s", admin->ip, admin->port, buf);
+
+    uuid_t endpoint_uid;
+    uuid_generate(endpoint_uid);
+    char endpoint_uuid[37];
+    uuid_unparse_lower(endpoint_uid, endpoint_uuid);
+
+    bundleContext_getProperty(admin->context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &uuid);
+    properties_set(endpointProperties, (char*) OSGI_RSA_ENDPOINT_FRAMEWORK_UUID, uuid);
+    properties_set(endpointProperties, (char*) OSGI_FRAMEWORK_OBJECTCLASS, interface);
+    properties_set(endpointProperties, (char*) OSGI_RSA_ENDPOINT_SERVICE_ID, serviceId);
+    properties_set(endpointProperties, (char*) OSGI_RSA_ENDPOINT_ID, endpoint_uuid);
+    properties_set(endpointProperties, (char*) OSGI_RSA_SERVICE_IMPORTED, "true");
+    properties_set(endpointProperties, (char*) OSGI_RSA_SERVICE_IMPORTED_CONFIGS, (char*) CONFIGURATION_TYPE);
+    properties_set(endpointProperties, (char*) ENDPOINT_URL, url);
+
+    if (props != NULL) {
+        hash_map_iterator_pt propIter = hashMapIterator_create(props);
+        while (hashMapIterator_hasNext(propIter)) {
+    	    hash_map_entry_pt entry = hashMapIterator_nextEntry(propIter);
+    	    properties_set(endpointProperties, (char*)hashMapEntry_getKey(entry), (char*)hashMapEntry_getValue(entry));
+        }
+        hashMapIterator_destroy(propIter);
+    }
+
+    *endpoint = calloc(1, sizeof(**endpoint));
+    if (!*endpoint) {
+        status = CELIX_ENOMEM;
+    } else {
+        (*endpoint)->id = (char*)properties_get(endpointProperties, (char*) OSGI_RSA_ENDPOINT_ID);
+        const char *serviceId = NULL;
+        serviceReference_getProperty(reference, (char*) OSGI_FRAMEWORK_SERVICE_ID, &serviceId);
+        (*endpoint)->serviceId = strtoull(serviceId, NULL, 0);
+        (*endpoint)->frameworkUUID = (char*) properties_get(endpointProperties, (char*) OSGI_RSA_ENDPOINT_FRAMEWORK_UUID);
+        (*endpoint)->service = strndup(interface, 1024*10);
+        (*endpoint)->properties = endpointProperties;
+    }
+
+    free(key);
+    free(serviceId);
+    free(keys);
+
+    return status;
+}
+
+static celix_status_t remoteServiceAdmin_getIpAdress(char* interface, char** ip) {
+    celix_status_t status = CELIX_BUNDLE_EXCEPTION;
+
+    struct ifaddrs *ifaddr, *ifa;
+    char host[NI_MAXHOST];
+
+    if (getifaddrs(&ifaddr) != -1)
+    {
+        for (ifa = ifaddr; ifa != NULL && status != CELIX_SUCCESS; ifa = ifa->ifa_next)
+        {
+            if (ifa->ifa_addr == NULL)
+                continue;
+
+            if ((getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0) && (ifa->ifa_addr->sa_family == AF_INET)) {
+                if (interface == NULL) {
+                    *ip = strdup(host);
+                    status = CELIX_SUCCESS;
+                }
+                else if (strcmp(ifa->ifa_name, interface) == 0) {
+                    *ip = strdup(host);
+                    status = CELIX_SUCCESS;
+                }
+            }
+        }
+
+        freeifaddrs(ifaddr);
+    }
+
+    return status;
+}
+
+
+celix_status_t remoteServiceAdmin_destroyEndpointDescription(endpoint_description_pt *description)
+{
+    celix_status_t status = CELIX_SUCCESS;
+
+    properties_destroy((*description)->properties);
+    free((*description)->service);
+    free(*description);
+
+    return status;
+}
+
+
+celix_status_t remoteServiceAdmin_getExportedServices(remote_service_admin_pt admin, array_list_pt *services) {
+    celix_status_t status = CELIX_SUCCESS;
+    return status;
+}
+
+celix_status_t remoteServiceAdmin_getImportedEndpoints(remote_service_admin_pt admin, array_list_pt *services) {
+    celix_status_t status = CELIX_SUCCESS;
+    return status;
+}
+
+celix_status_t remoteServiceAdmin_importService(remote_service_admin_pt admin, endpoint_description_pt endpointDescription, import_registration_pt *out) {
+    celix_status_t status = CELIX_SUCCESS;
+    import_registration_pt import = NULL;
+
+    const char *objectClass = properties_get(endpointDescription->properties, "objectClass");
+    const char *serviceVersion = properties_get(endpointDescription->properties, (char*) CELIX_FRAMEWORK_SERVICE_VERSION);
+
+    logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Import service %s", endpointDescription->service);
+    logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "Registering service factory (proxy) for service '%s'\n", objectClass);
+
+    if (objectClass != NULL) {
+        status = importRegistration_create(admin->context, endpointDescription, objectClass, serviceVersion, &import);
+    }
+    if (status == CELIX_SUCCESS && import != NULL) {
+        importRegistration_setSendFn(import, (send_func_type) remoteServiceAdmin_send, admin);
+    }
+
+    if (status == CELIX_SUCCESS && import != NULL) {
+        status = importRegistration_start(import);
+    }
+
+    celixThreadMutex_lock(&admin->importedServicesLock);
+    arrayList_add(admin->importedServices, import);
+    celixThreadMutex_unlock(&admin->importedServicesLock);
+
+    if (status == CELIX_SUCCESS) {
+        *out = import;
+    }
+
+    return status;
+}
+
+
+celix_status_t remoteServiceAdmin_removeImportedService(remote_service_admin_pt admin, import_registration_pt registration) {
+    celix_status_t status = CELIX_SUCCESS;
+    logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA_DFI: Removing imported service");
+
+    celixThreadMutex_lock(&admin->importedServicesLock);
+    int i;
+    int size = arrayList_size(admin->importedServices);
+    import_registration_pt  current  = NULL;
+    for (i = 0; i < size; i += 1) {
+        current = arrayList_get(admin->importedServices, i);
+        if (current == registration) {
+            arrayList_remove(admin->importedServices, i);
+            importRegistration_close(current);
+            importRegistration_destroy(current);
+            break;
+        }
+    }
+    celixThreadMutex_unlock(&admin->importedServicesLock);
+
+    return status;
+}
+
+
+static celix_status_t remoteServiceAdmin_send(void *handle, endpoint_description_pt endpointDescription, char *request, char **reply, int* replyStatus) {
+    remote_service_admin_pt  rsa = handle;
+    struct post post;
+    post.readptr = request;
+    post.size = strlen(request);
+
+    struct get get;
+    get.size = 0;
+    get.writeptr = malloc(1);
+
+    char *serviceUrl = (char*)properties_get(endpointDescription->properties, (char*) ENDPOINT_URL);
+    char url[256];
+    snprintf(url, 256, "%s", serviceUrl);
+
+    // assume the default timeout
+    int timeout = DEFAULT_TIMEOUT;
+
+    const char *timeoutStr = NULL;
+    // Check if the endpoint has a timeout, if so, use it.
+    timeoutStr = (char*) properties_get(endpointDescription->properties, (char*) OSGI_RSA_REMOTE_PROXY_TIMEOUT);
+    if (timeoutStr == NULL) {
+        // If not, get the global variable and use that one.
+        bundleContext_getProperty(rsa->context, (char*) OSGI_RSA_REMOTE_PROXY_TIMEOUT, &timeoutStr);
+    }
+
+    // Update timeout if a property is used to set it.
+    if (timeoutStr != NULL) {
+        timeout = atoi(timeoutStr);
+    }
+
+    celix_status_t status = CELIX_SUCCESS;
+    CURL *curl;
+    CURLcode res;
+
+    curl = curl_easy_init();
+    if(!curl) {
+        status = CELIX_ILLEGAL_STATE;
+    } else {
+        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+        curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
+        curl_easy_setopt(curl, CURLOPT_URL, url);
+        curl_easy_setopt(curl, CURLOPT_POST, 1L);
+        curl_easy_setopt(curl, CURLOPT_READFUNCTION, remoteServiceAdmin_readCallback);
+        curl_easy_setopt(curl, CURLOPT_READDATA, &post);
+        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, remoteServiceAdmin_write);
+        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&get);
+        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (curl_off_t)post.size);
+        logHelper_log(rsa->loghelper, OSGI_LOGSERVICE_DEBUG, "RSA: Performing curl post\n");
+        res = curl_easy_perform(curl);
+
+        *reply = get.writeptr;
+        *replyStatus = res;
+
+        curl_easy_cleanup(curl);
+    }
+
+    return status;
+}
+
+static size_t remoteServiceAdmin_readCallback(void *ptr, size_t size, size_t nmemb, void *userp) {
+    struct post *post = userp;
+
+    if (post->size) {
+        *(char *) ptr = post->readptr[0];
+        post->readptr++;
+        post->size--;
+        return 1;
+    }
+
+    return 0;
+}
+
+static size_t remoteServiceAdmin_write(void *contents, size_t size, size_t nmemb, void *userp) {
+    size_t realsize = size * nmemb;
+    struct get *mem = (struct get *)userp;
+
+    mem->writeptr = realloc(mem->writeptr, mem->size + realsize + 1);
+    if (mem->writeptr == NULL) {
+        /* out of memory! */
+        printf("not enough memory (realloc returned NULL)");
+        exit(EXIT_FAILURE);
+    }
+
+    memcpy(&(mem->writeptr[mem->size]), contents, realsize);
+    mem->size += realsize;
+    mem->writeptr[mem->size] = 0;
+
+    return realsize;
+}
+
+
+static void remoteServiceAdmin_log(remote_service_admin_pt admin, int level, const char *file, int line, const char *msg, ...) {
+    va_list ap;
+    va_start(ap, msg);
+    int levels[5] = {0, OSGI_LOGSERVICE_ERROR, OSGI_LOGSERVICE_WARNING, OSGI_LOGSERVICE_INFO, OSGI_LOGSERVICE_DEBUG};
+
+    char buf1[256];
+    snprintf(buf1, 256, "FILE:%s, LINE:%i, MSG:", file, line);
+
+    char buf2[256];
+    vsnprintf(buf2, 256, msg, ap);
+    logHelper_log(admin->loghelper, levels[level], "%s%s", buf1, buf2);
+    va_end(ap);
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.h b/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.h
new file mode 100644
index 0000000..8b282f1
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.h
@@ -0,0 +1,57 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * remote_service_admin_http_impl.h
+ *
+ *  \date       Sep 30, 2011
+ *  \author    	<a href="mailto: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 "bundle_context.h"
+#include "endpoint_description.h"
+
+//typedef struct remote_service_admin *remote_service_admin_pt;
+
+celix_status_t remoteServiceAdmin_create(bundle_context_pt context, remote_service_admin_pt *admin);
+celix_status_t remoteServiceAdmin_destroy(remote_service_admin_pt *admin);
+
+celix_status_t remoteServiceAdmin_stop(remote_service_admin_pt admin);
+
+celix_status_t remoteServiceAdmin_exportService(remote_service_admin_pt admin, char *serviceId, properties_pt properties, array_list_pt *registrations);
+celix_status_t remoteServiceAdmin_removeExportedService(remote_service_admin_pt admin, export_registration_pt registration);
+celix_status_t remoteServiceAdmin_getExportedServices(remote_service_admin_pt admin, array_list_pt *services);
+celix_status_t remoteServiceAdmin_getImportedEndpoints(remote_service_admin_pt admin, array_list_pt *services);
+celix_status_t remoteServiceAdmin_importService(remote_service_admin_pt admin, endpoint_description_pt endpoint, import_registration_pt *registration);
+celix_status_t remoteServiceAdmin_removeImportedService(remote_service_admin_pt admin, import_registration_pt registration);
+
+
+celix_status_t exportReference_getExportedEndpoint(export_reference_pt reference, endpoint_description_pt *endpoint);
+celix_status_t exportReference_getExportedService(export_reference_pt reference, service_reference_pt *service);
+
+celix_status_t importReference_getImportedEndpoint(import_reference_pt reference);
+celix_status_t importReference_getImportedService(import_reference_pt reference);
+
+celix_status_t remoteServiceAdmin_destroyEndpointDescription(endpoint_description_pt *description);
+
+#endif /* REMOTE_SERVICE_ADMIN_HTTP_IMPL_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/test/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/test/CMakeLists.txt b/remote_services/remote_service_admin_dfi/test/CMakeLists.txt
new file mode 100644
index 0000000..a78a6d0
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/test/CMakeLists.txt
@@ -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.
+
+find_package(CppUTest REQUIRED)
+include_directories(${CPPUTEST_INCLUDE_DIR})
+
+add_bundle(rsa_dfi_tst_bundle
+    VERSION 0.0.1
+    SOURCES
+        src/tst_activator.c
+)
+get_target_property(DESCR calculator_api INTERFACE_CALCULATOR_DESCRIPTOR)
+bundle_files(rsa_dfi_tst_bundle ${DESCR} DESTINATION .)
+target_link_libraries(rsa_dfi_tst_bundle PRIVATE ${CPPUTEST_LIBRARY} calculator_api)
+target_include_directories(rsa_dfi_tst_bundle PRIVATE src)
+
+add_executable(test_rsa_dfi
+    src/run_tests.cpp
+    src/rsa_tests.cpp
+    src/rsa_client_server_tests.cpp
+)
+target_include_directories(test_rsa_dfi PRIVATE src)
+target_link_libraries(test_rsa_dfi PRIVATE ${CURL_LIBRARIES} ${CPPUTEST_LIBRARY}
+        Celix::framework
+        Celix::remote_service_admin_api
+        Celix::remote_service_admin_common
+        calculator_api)
+
+get_property(rsa_bundle_file TARGET remote_service_admin_dfi 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_configured_bundle_file TARGET discovery_configured PROPERTY BUNDLE_FILE)
+get_property(topology_manager_bundle_file TARGET topology_manager PROPERTY BUNDLE_FILE)
+get_property(tst_bundle_file TARGET rsa_dfi_tst_bundle PROPERTY BUNDLE_FILE)
+
+configure_file(config.properties.in config.properties)
+configure_file(client.properties.in client.properties)
+configure_file(server.properties.in server.properties)
+
+add_dependencies(test_rsa_dfi
+        remote_service_admin_dfi_bundle #note depend on the target creating the bundle zip not the lib target
+        calculator_bundle
+)
+
+add_test(NAME run_test_rsa_dfi COMMAND test_rsa_dfi)
+SETUP_TARGET_FOR_COVERAGE(test_rsa_dfi_cov test_rsa_dfi ${CMAKE_BINARY_DIR}/coverage/test_rsa_dfi/test_rsa_dfi)
+

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/test/client.properties.in
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/test/client.properties.in b/remote_services/remote_service_admin_dfi/test/client.properties.in
new file mode 100644
index 0000000..a9a06fb
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/test/client.properties.in
@@ -0,0 +1,8 @@
+cosgi.auto.start.1=@rsa_bundle_file@ @calculator_shell_bundle_file@ @discovery_configured_bundle_file@ @topology_manager_bundle_file@ @tst_bundle_file@
+LOGHELPER_ENABLE_STDOUT_FALLBACK=true
+RSA_PORT=50881
+DISCOVERY_CFG_SERVER_PORT=50991
+DISCOVERY_CFG_POLL_ENDPOINTS=http://127.0.0.1:50992/org.apache.celix.discovery.configured
+org.osgi.framework.storage.clean=onFirstInit
+org.osgi.framework.storage=.cacheClient
+DISCOVERY_CFG_POLL_INTERVAL=1
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/test/config.properties.in
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/test/config.properties.in b/remote_services/remote_service_admin_dfi/test/config.properties.in
new file mode 100644
index 0000000..5776ad8
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/test/config.properties.in
@@ -0,0 +1,20 @@
+# 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@
+LOGHELPER_ENABLE_STDOUT_FALLBACK=true
+org.osgi.framework.storage.clean=onFirstInit
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/test/server.properties.in
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/test/server.properties.in b/remote_services/remote_service_admin_dfi/test/server.properties.in
new file mode 100644
index 0000000..707c7e6
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/test/server.properties.in
@@ -0,0 +1,23 @@
+# 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_configured_bundle_file@ @topology_manager_bundle_file@
+LOGHELPER_ENABLE_STDOUT_FALLBACK=true
+RSA_PORT=50882
+DISCOVERY_CFG_SERVER_PORT=50992
+org.osgi.framework.storage.clean=onFirstInit
+org.osgi.framework.storage=.cacheServer
+DISCOVERY_CFG_POLL_INTERVAL=1
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/test/src/rsa_client_server_tests.cpp
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/test/src/rsa_client_server_tests.cpp b/remote_services/remote_service_admin_dfi/test/src/rsa_client_server_tests.cpp
new file mode 100644
index 0000000..528e6b7
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/test/src/rsa_client_server_tests.cpp
@@ -0,0 +1,133 @@
+/**
+ *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 <tst_service.h>
+#include "CppUTest/CommandLineTestRunner.h"
+#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"
+
+    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 rc;
+        service_reference_pt ref = NULL;
+        tst_service_pt tst = NULL;
+        int retries = 4;
+
+        while (ref == NULL && retries > 0) {
+            printf("Waiting for service .. %d\n", retries);
+            rc = bundleContext_getServiceReference(clientContext, (char *) TST_SERVICE_NAME, &ref);
+            usleep(1000000);
+            --retries;
+        }
+
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+        CHECK(ref != NULL);
+
+        rc = bundleContext_getService(clientContext, ref, (void **)&tst);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+        CHECK(tst != NULL);
+
+        rc = tst->test(tst->handle);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+        bool result;
+        bundleContext_ungetService(clientContext, ref, &result);
+        bundleContext_ungetServiceReference(clientContext, ref);
+    }
+
+}
+
+
+TEST_GROUP(RsaDfiClientServerTests) {
+    void setup() {
+        setupFm();
+    }
+
+    void teardown() {
+        teardownFm();
+    }
+};
+
+TEST(RsaDfiClientServerTests, Test1) {
+    test1();
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/test/src/rsa_tests.cpp
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/test/src/rsa_tests.cpp b/remote_services/remote_service_admin_dfi/test/src/rsa_tests.cpp
new file mode 100644
index 0000000..6026ac6
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/test/src/rsa_tests.cpp
@@ -0,0 +1,234 @@
+/**
+ *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 "calculator_service.h"
+
+extern "C" {
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "celix_launcher.h"
+#include "framework.h"
+#include "remote_service_admin.h"
+#include "calculator_service.h"
+
+
+    static framework_pt framework = NULL;
+    static bundle_context_pt context = NULL;
+
+    static service_reference_pt rsaRef = NULL;
+    static remote_service_admin_service_pt rsa = NULL;
+
+    static service_reference_pt calcRef = NULL;
+    static calculator_service_pt calc = NULL;
+
+    static void setupFm(void) {
+        int rc = 0;
+
+        rc = celixLauncher_launch("config.properties", &framework);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+        bundle_pt bundle = NULL;
+        rc = framework_getFrameworkBundle(framework, &bundle);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+        rc = bundle_getContext(bundle, &context);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+        rc = bundleContext_getServiceReference(context, (char *)OSGI_RSA_REMOTE_SERVICE_ADMIN, &rsaRef);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+        CHECK(rsaRef != NULL);
+
+        rc = bundleContext_getService(context, rsaRef, (void **)&rsa);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+        rc = bundleContext_getServiceReference(context, (char *)CALCULATOR2_SERVICE, &calcRef);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+        CHECK(calcRef != NULL);
+
+        rc = bundleContext_getService(context, calcRef, (void **)&calc);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+    }
+
+    static void teardownFm(void) {
+        int rc = 0;
+        rc = bundleContext_ungetService(context, rsaRef, NULL);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+        rc = bundleContext_ungetServiceReference(context, rsaRef);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+        rc = bundleContext_ungetService(context, calcRef, NULL);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+        rc = bundleContext_ungetServiceReference(context, calcRef);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+        celixLauncher_stop(framework);
+        celixLauncher_waitForShutdown(framework);
+        celixLauncher_destroy(framework);
+
+        rsaRef = NULL;
+        rsa = NULL;
+        calcRef = NULL;
+        calc = NULL;
+        context = NULL;
+        framework = NULL;
+    }
+
+    static void testServices(void) {
+        int rc = 0;
+        array_list_pt exported = NULL;
+        array_list_pt imported = NULL;
+        arrayList_create(&exported);
+        arrayList_create(&imported);
+
+        rc = rsa->getExportedServices(rsa->admin, &exported);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+        CHECK_EQUAL(0, arrayList_size(exported));
+
+        rc = rsa->getImportedEndpoints(rsa->admin, &imported);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+        CHECK_EQUAL(0, arrayList_size(imported));
+
+        double result = 0;
+        rc = calc->add(calc->calculator, 2.0, 5.0, &result);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+        CHECK_EQUAL(7.0, result);
+
+        arrayList_destroy(imported);
+        arrayList_destroy(exported);
+    }
+
+    static void testExportService(void) {
+        int rc = 0;
+        const char *calcId = NULL;
+        array_list_pt regs = NULL;
+
+        rc = serviceReference_getProperty(calcRef, (char *)"service.id", &calcId);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+        rc = rsa->exportService(rsa->admin, (char*)calcId, NULL, &regs);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+        CHECK_EQUAL(1, arrayList_size(regs));
+
+        rc = rsa->exportRegistration_close(rsa->admin,(export_registration_pt)(arrayList_get(regs,0)));
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+    }
+
+    static void testImportService(void) {
+        int rc = 0;
+        import_registration_pt reg = NULL;
+        endpoint_description_pt endpoint = NULL;
+
+        properties_pt props = properties_create();
+        properties_set(props, (char *)OSGI_RSA_ENDPOINT_SERVICE_ID, (char *)"42");
+        properties_set(props, (char *)OSGI_RSA_ENDPOINT_FRAMEWORK_UUID, (char *)"eec5404d-51d0-47ef-8d86-c825a8beda42");
+        properties_set(props, (char *)OSGI_RSA_ENDPOINT_ID, (char *)"eec5404d-51d0-47ef-8d86-c825a8beda42-42");
+        properties_set(props, (char *)OSGI_FRAMEWORK_OBJECTCLASS,(char *)"org.apache.celix.Example");
+        properties_set(props, (char *)"service.version",(char *)"1.0.0"); //TODO find out standard in osgi spec
+
+        rc = endpointDescription_create(props, &endpoint);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+        rc = rsa->importService(rsa->admin, endpoint, &reg);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+        CHECK(reg != NULL);
+
+        service_reference_pt ref = NULL;
+        rc = bundleContext_getServiceReference(context, (char *)"org.apache.celix.Example", &ref);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+        CHECK(ref != NULL);
+
+        rc = bundleContext_ungetServiceReference(context, ref);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+        rc = endpointDescription_destroy(endpoint);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+        /* Cannot test. uses requesting bundles descriptor
+        void *service = NULL;
+        rc = bundleContext_getService(context, ref, &service);
+        CHECK_EQUAL(CELIX_SUCCESS, rc);
+        CHECK(service != NULL);
+         */
+    }
+
+    static void testBundles(void) {
+        array_list_pt bundles = NULL;
+
+        int rc = bundleContext_getBundles(context, &bundles);
+        CHECK_EQUAL(0, rc);
+        CHECK_EQUAL(3, arrayList_size(bundles)); //framework, rsa_dfi & calc
+
+        /*
+        int size = arrayList_size(bundles);
+        int i;
+        for (i = 0; i < size; i += 1) {
+            bundle_pt bundle = NULL;
+            module_pt module = NULL;
+            char *name = NULL;
+
+            bundle = (bundle_pt) arrayList_get(bundles, i);
+            bundle_getCurrentModule(bundle, &module);
+            module_getSymbolicName(module, &name);
+            printf("got bundle with symbolic name '%s'", name);
+        }*/
+
+        arrayList_destroy(bundles);
+    }
+
+}
+
+
+TEST_GROUP(RsaDfiTests) {
+    void setup() {
+        setupFm();
+    }
+
+    void teardown() {
+        teardownFm();
+    }
+};
+
+TEST(RsaDfiTests, InfoTest) {
+    testServices();
+}
+
+TEST(RsaDfiTests, ExportService) {
+    testExportService();
+}
+
+TEST(RsaDfiTests, ImportService) {
+    testImportService();
+}
+
+TEST(RsaDfiTests, TestBundles) {
+    testBundles();
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/test/src/run_tests.cpp
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/test/src/run_tests.cpp b/remote_services/remote_service_admin_dfi/test/src/run_tests.cpp
new file mode 100644
index 0000000..b5fd502
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/test/src/run_tests.cpp
@@ -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.
+ */
+
+#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/27a2aa75/remote_services/remote_service_admin_dfi/test/src/tst_activator.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/test/src/tst_activator.c b/remote_services/remote_service_admin_dfi/test/src/tst_activator.c
new file mode 100644
index 0000000..3db38fb
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/test/src/tst_activator.c
@@ -0,0 +1,162 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <service_tracker_customizer.h>
+#include <service_tracker.h>
+
+#include "bundle_activator.h"
+#include "bundle_context.h"
+#include "service_registration.h"
+#include "service_reference.h"
+#include "celix_errno.h"
+
+#include "tst_service.h"
+#include "calculator_service.h"
+#include <unistd.h>
+
+
+struct activator {
+	bundle_context_pt context;
+	struct tst_service serv;
+	service_registration_pt  reg;
+
+	service_tracker_customizer_pt cust;
+	service_tracker_pt tracker;
+	calculator_service_pt calc;
+};
+
+static celix_status_t addCalc(void * handle, service_reference_pt reference, void * service);
+static celix_status_t removeCalc(void * handle, service_reference_pt reference, void * service);
+static int test(void *handle);
+
+celix_status_t bundleActivator_create(bundle_context_pt context, void **out) {
+	celix_status_t status = CELIX_SUCCESS;
+	struct activator *act = calloc(1, sizeof(*act));
+	if (act != NULL) {
+		act->context = context;
+		act->serv.handle = act;
+		act->serv.test = test;
+
+		status = serviceTrackerCustomizer_create(act, NULL, addCalc, NULL, removeCalc, &act->cust);
+		status = CELIX_DO_IF(status, serviceTracker_create(context, CALCULATOR2_SERVICE, act->cust, &act->tracker));
+
+	} else {
+		status = CELIX_ENOMEM;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		*out = act;
+	} else if (act != NULL) {
+		if (act->cust != NULL) {
+			free(act->cust);
+			act->cust = NULL;
+		}
+		if (act->tracker != NULL) {
+			serviceTracker_destroy(act->tracker);
+			act->tracker = NULL;
+		}
+		free(act);
+	}
+
+	return CELIX_SUCCESS;
+}
+
+static celix_status_t addCalc(void * handle, service_reference_pt reference, void * service) {
+	celix_status_t status = CELIX_SUCCESS;
+	struct activator * act = handle;
+	act->calc = service;
+	return status;
+}
+
+static celix_status_t removeCalc(void * handle, service_reference_pt reference, void * service) {
+	celix_status_t status = CELIX_SUCCESS;
+	struct activator * act = handle;
+	if (act->calc == service) {
+		act->calc = NULL;
+	}
+	return status;
+
+}
+
+celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
+    celix_status_t status = CELIX_SUCCESS;
+	struct activator * act = userData;
+
+	act->reg = NULL;
+	status = bundleContext_registerService(context, (char *)TST_SERVICE_NAME, &act->serv, NULL, &act->reg);
+
+	status = CELIX_DO_IF(status, serviceTracker_open(act->tracker));
+
+
+	return status;
+}
+
+
+celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) {
+    celix_status_t status = CELIX_SUCCESS;
+	struct activator * act = userData;
+
+	status = serviceRegistration_unregister(act->reg);
+	status = CELIX_DO_IF(status, serviceTracker_close(act->tracker));
+
+	return status;
+}
+
+celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) {
+	struct activator *act = userData;
+	if (act != NULL) {
+		if (act->tracker != NULL) {
+			serviceTracker_destroy(act->tracker);
+			act->tracker = NULL;
+		}
+		free(act);
+	}
+	return CELIX_SUCCESS;
+}
+
+static int test(void *handle) {
+	int status = 0;
+	struct activator *act = handle;
+
+	double result = -1.0;
+
+    int retries = 40;
+
+    while (act->calc == NULL) {
+        printf("Waiting for calc service .. %d\n", retries);
+        usleep(100000);
+        --retries;
+    }
+
+    int rc = 1;
+    if (act->calc != NULL) {
+		rc = act->calc->sqrt(act->calc->calculator, 4, &result);
+        printf("calc result is %f\n", result);
+    } else {
+        printf("calc not ready\n");
+    }
+
+	if (rc != 0 || result != 2.0) {
+		status = 1;
+	}
+	return status;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/test/src/tst_service.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/test/src/tst_service.h b/remote_services/remote_service_admin_dfi/test/src/tst_service.h
new file mode 100644
index 0000000..c8ca2e7
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/test/src/tst_service.h
@@ -0,0 +1,32 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CELIX_TST_SERVICE_H
+#define CELIX_TST_SERVICE_H
+
+#define TST_SERVICE_NAME "tst_service"
+
+struct tst_service {
+    void *handle;
+    int (*test)(void *handle);
+};
+
+typedef struct tst_service *tst_service_pt;
+
+#endif //CELIX_TST_SERVICE_H

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/topology_manager/src/topology_manager.h
----------------------------------------------------------------------
diff --git a/remote_services/topology_manager/src/topology_manager.h b/remote_services/topology_manager/src/topology_manager.h
index 7e5e917..b6ee064 100644
--- a/remote_services/topology_manager/src/topology_manager.h
+++ b/remote_services/topology_manager/src/topology_manager.h
@@ -35,6 +35,7 @@
 
 #define OSGI_RSA_REMOTE_SERVICE_ADMIN "remote_service_admin"
 
+typedef struct topology_manager topology_manager_t;
 typedef struct topology_manager *topology_manager_pt;
 
 celix_status_t topologyManager_create(bundle_context_pt context, log_helper_pt logHelper, topology_manager_pt *manager, void **scope);

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/topology_manager/tms_tst/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/topology_manager/tms_tst/CMakeLists.txt b/remote_services/topology_manager/tms_tst/CMakeLists.txt
index 6d0713c..5e27139 100644
--- a/remote_services/topology_manager/tms_tst/CMakeLists.txt
+++ b/remote_services/topology_manager/tms_tst/CMakeLists.txt
@@ -37,9 +37,18 @@ add_executable(test_tm_scoped
     run_tests.cpp
     tms_tests.cpp
 )
-target_link_libraries(test_tm_scoped Celix::framework ${CPPUTEST_LIBRARY} ${JANSSON_LIBRARY} Celix::log_helper remote_service_admin_common)
+target_include_directories(test_tm_scoped PRIVATE ../src ../include)
+target_link_libraries(test_tm_scoped PRIVATE
+        Celix::framework
+        ${CPPUTEST_LIBRARY}
+        ${JANSSON_LIBRARY}
+        Celix::log_helper
+        calculator_api
+        Celix::remote_service_admin_api
+        Celix::remote_service_admin_common
+)
 
-add_dependencies(test_tm_scoped remote_service_admin_dfi topology_manager calculator)
+add_dependencies(test_tm_scoped remote_service_admin_dfi_bundle topology_manager_bundle)
 
 file(GENERATE 
     OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/config.properties"
@@ -57,13 +66,6 @@ LOGHELPER_ENABLE_STDOUT_FALLBACK=true
 org.osgi.framework.storage.clean=onFirstInit
 ")
 
-
-#TODO improve copy commands, for now using configure_file as copy 
-#add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scope.json" COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURE_DIR}/scope.json" "${CMAKE_CURRENT_BINARY_DIR}/scope.json")
-#add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scope2.json" COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURE_DIR}/scope2.json" "${CMAKE_CURRENT_BINARY_DIR}/scope2.json")
-#add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scope3.json" COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURE_DIR}/scope3.json" "${CMAKE_CURRENT_BINARY_DIR}/scope3.json")
-#add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scope4.json" COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURE_DIR}/scope4.json" "${CMAKE_CURRENT_BINARY_DIR}/scope4.json")
-
 configure_file("scope.json" "scope.json")
 configure_file("scope2.json" "scope2.json")
 configure_file("scope3.json" "scope3.json")

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt b/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt
index fc9d9bf..551995b 100644
--- a/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt
+++ b/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt
@@ -32,4 +32,4 @@ bundle_files(topology_manager_test_bundle
     DESTINATION .
 )
 
-target_link_libraries(topology_manager_test_bundle PRIVATE ${CPPUTEST_LIBRARY} remote_service_admin calculator_api)
+target_link_libraries(topology_manager_test_bundle PRIVATE ${CPPUTEST_LIBRARY} Celix::remote_service_admin_api calculator_api)

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/topology_manager/tms_tst/disc_mock/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/topology_manager/tms_tst/disc_mock/CMakeLists.txt b/remote_services/topology_manager/tms_tst/disc_mock/CMakeLists.txt
index bfd7fc1..653b69c 100644
--- a/remote_services/topology_manager/tms_tst/disc_mock/CMakeLists.txt
+++ b/remote_services/topology_manager/tms_tst/disc_mock/CMakeLists.txt
@@ -20,7 +20,9 @@ add_bundle(topology_manager_disc_mock_bundle
     SOURCES
         disc_mock_activator.c
         disc_mock_service.c
-
 )
-target_include_directories(topology_manager_disc_mock_bundle PRIVATE ${CPPUTEST_INCLUDE_DIR})
-target_link_libraries(topology_manager_disc_mock_bundle PRIVATE ${CPPUTEST_LIBRARY} Celix::framework discovery_common)
+target_include_directories(topology_manager_disc_mock_bundle PRIVATE
+        ${CPPUTEST_INCLUDE_DIR}
+        $<TARGET_PROPERTY:discovery_common,INCLUDE_DIRECTORIES>
+)
+target_link_libraries(topology_manager_disc_mock_bundle PRIVATE ${CPPUTEST_LIBRARY} Celix::framework)

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/topology_manager/tms_tst/disc_mock/disc_mock_activator.c
----------------------------------------------------------------------
diff --git a/remote_services/topology_manager/tms_tst/disc_mock/disc_mock_activator.c b/remote_services/topology_manager/tms_tst/disc_mock/disc_mock_activator.c
index 53fccd7..d07ce02 100644
--- a/remote_services/topology_manager/tms_tst/disc_mock/disc_mock_activator.c
+++ b/remote_services/topology_manager/tms_tst/disc_mock/disc_mock_activator.c
@@ -29,7 +29,6 @@
 #include "celix_errno.h"
 
 #include "disc_mock_service.h"
-#include "discovery.h"
 #include "constants.h"
 #include "remote_constants.h"
 


[7/8] celix git commit: CELIX-417: Refactors CMake usage for the RSA bundles

Posted by pn...@apache.org.
CELIX-417: Refactors CMake usage for the RSA bundles


Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/27a2aa75
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/27a2aa75
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/27a2aa75

Branch: refs/heads/feature/CELIX-417-cmake-refactor
Commit: 27a2aa756025018dd2406cc5b423d2ff5e38cf87
Parents: 2a670f2
Author: Pepijn Noltes <pe...@gmail.com>
Authored: Fri Nov 24 11:38:49 2017 +0100
Committer: Pepijn Noltes <pe...@gmail.com>
Committed: Fri Nov 24 11:38:49 2017 +0100

----------------------------------------------------------------------
 cmake/cmake_celix/BundlePackaging.cmake         |    6 +-
 cmake/cmake_celix/DeployPackaging.cmake         |    2 +-
 dfi/CMakeLists.txt                              |   41 +-
 framework/src/bundle_context.c                  |    2 +-
 log_service/loghelper_include/log_helper.h      |    1 +
 log_writer/CMakeLists.txt                       |    2 +-
 remote_services/CMakeLists.txt                  |    2 +
 remote_services/civetweb/CMakeLists.txt         |   23 +
 remote_services/civetweb/include/civetweb.h     |  657 ++
 remote_services/civetweb/src/civetweb.c         | 7907 ++++++++++++++++++
 remote_services/civetweb/src/md5.inl            |  461 +
 remote_services/discovery_common/CMakeLists.txt |   18 +-
 .../discovery_common/include/civetweb.h         |  657 --
 .../discovery_common/include/discovery.h        |   23 +-
 .../discovery_common/include/discovery_type.h   |   27 +
 .../include/endpoint_discovery_poller.h         |    9 +-
 .../include/endpoint_discovery_server.h         |   11 +-
 remote_services/discovery_common/src/civetweb.c | 7907 ------------------
 .../discovery_common/src/discovery.c            |    1 -
 .../src/endpoint_discovery_poller.c             |    7 +-
 .../src/endpoint_discovery_server.c             |   20 +-
 remote_services/discovery_common/src/md5.inl    |  461 -
 .../discovery_configured/CMakeLists.txt         |   10 +-
 .../discovery_configured/src/discovery_impl.c   |    4 +-
 .../discovery_configured/src/discovery_impl.h   |   28 +-
 remote_services/discovery_etcd/CMakeLists.txt   |   16 +-
 .../discovery_etcd/src/discovery_impl.c         |   44 +-
 .../discovery_etcd/src/discovery_impl.h         |   16 +-
 .../discovery_etcd/src/etcd_watcher.h           |    1 +
 remote_services/discovery_shm/CMakeLists.txt    |    6 +-
 .../discovery_shm/src/discovery_impl.c          |   42 +-
 .../discovery_shm/src/discovery_impl.h          |   21 +-
 .../discovery_shm/src/discovery_shmWatcher.c    |   19 +-
 .../discovery_shm/src/discovery_shmWatcher.h    |    1 +
 .../remote_service_admin_common/CMakeLists.txt  |    4 +-
 .../remote_service_admin_dfi/CMakeLists.txt     |   32 +-
 .../remote_service_admin_dfi/rsa/CMakeLists.txt |   34 -
 .../rsa/src/dfi_utils.c                         |   98 -
 .../rsa/src/dfi_utils.h                         |   30 -
 .../rsa/src/export_registration_dfi.c           |  251 -
 .../rsa/src/export_registration_dfi.h           |   38 -
 .../rsa/src/import_registration_dfi.c           |  402 -
 .../rsa/src/import_registration_dfi.h           |   44 -
 .../rsa/src/remote_service_admin_activator.c    |  124 -
 .../rsa/src/remote_service_admin_dfi.c          |  775 --
 .../rsa/src/remote_service_admin_dfi.h          |   57 -
 .../rsa_tst/CMakeLists.txt                      |   52 -
 .../rsa_tst/bundle/CMakeLists.txt               |   29 -
 .../rsa_tst/bundle/tst_activator.c              |  153 -
 .../rsa_tst/bundle/tst_service.h                |   32 -
 .../rsa_tst/client.properties.in                |    8 -
 .../rsa_tst/config.properties.in                |   20 -
 .../rsa_tst/rsa_client_server_tests.cpp         |  133 -
 .../rsa_tst/rsa_tests.cpp                       |  234 -
 .../rsa_tst/run_tests.cpp                       |   25 -
 .../rsa_tst/server.properties.in                |   23 -
 .../remote_service_admin_dfi/src/dfi_utils.c    |  108 +
 .../remote_service_admin_dfi/src/dfi_utils.h    |   30 +
 .../src/export_registration_dfi.c               |  251 +
 .../src/export_registration_dfi.h               |   38 +
 .../src/import_registration_dfi.c               |  402 +
 .../src/import_registration_dfi.h               |   44 +
 .../src/remote_service_admin_activator.c        |  124 +
 .../src/remote_service_admin_dfi.c              |  771 ++
 .../src/remote_service_admin_dfi.h              |   57 +
 .../test/CMakeLists.txt                         |   61 +
 .../test/client.properties.in                   |    8 +
 .../test/config.properties.in                   |   20 +
 .../test/server.properties.in                   |   23 +
 .../test/src/rsa_client_server_tests.cpp        |  133 +
 .../test/src/rsa_tests.cpp                      |  234 +
 .../test/src/run_tests.cpp                      |   25 +
 .../test/src/tst_activator.c                    |  162 +
 .../test/src/tst_service.h                      |   32 +
 .../topology_manager/src/topology_manager.h     |    1 +
 .../topology_manager/tms_tst/CMakeLists.txt     |   20 +-
 .../tms_tst/bundle/CMakeLists.txt               |    2 +-
 .../tms_tst/disc_mock/CMakeLists.txt            |    8 +-
 .../tms_tst/disc_mock/disc_mock_activator.c     |    1 -
 79 files changed, 11847 insertions(+), 11759 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/cmake/cmake_celix/BundlePackaging.cmake
----------------------------------------------------------------------
diff --git a/cmake/cmake_celix/BundlePackaging.cmake b/cmake/cmake_celix/BundlePackaging.cmake
index c5d75d6..205bec1 100644
--- a/cmake/cmake_celix/BundlePackaging.cmake
+++ b/cmake/cmake_celix/BundlePackaging.cmake
@@ -145,14 +145,14 @@ function(add_bundle)
         set_library_version(${BUNDLE_TARGET_NAME} ${BUNDLE_VERSION})
         set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES
                 "BUNDLE_TARGET_IS_LIB" TRUE
-                "BUNDLE_BUILD_BUNDLE_TARGET" "${BUNDLE_TARGET_NAME}_bundle"
+                "BUNDLE_TARGET" "${BUNDLE_TARGET_NAME}_bundle"
         )
         target_link_libraries(${BUNDLE_TARGET_NAME} PRIVATE Celix::framework)
     else()
         add_custom_target(${BUNDLE_TARGET_NAME})
         set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES
                 "BUNDLE_TARGET_IS_LIB" FALSE
-                "BUNDLE_BUILD_BUNDLE_TARGET" "${BUNDLE_TARGET_NAME}_bundle"
+                "BUNDLE_TARGET" "${BUNDLE_TARGET_NAME}_bundle"
         )
     endif()
     add_custom_target(${BUNDLE_TARGET_NAME}_bundle
@@ -213,7 +213,7 @@ function(add_bundle)
     #############################
     #alreadyer set
     #   BUNDLE_TARGET_IS_LIB -> true (can be use to test if target is bundle target
-    #   BUNDLE_BUILD_BUNDLE_TARGET -> refers to the _bundle target which is responsible for building the zip file
+    #   BUNDLE_TARGET -> refers to the _bundle target which is responsible for building the zip file
     #internal use
     set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_IS_BUNDLE_TARGET" TRUE) #indicate that this is a bundle target
     set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_DEPEND_TARGETS" "") #bundle target dependencies. Note can be extended after the add_bundle call

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/cmake/cmake_celix/DeployPackaging.cmake
----------------------------------------------------------------------
diff --git a/cmake/cmake_celix/DeployPackaging.cmake b/cmake/cmake_celix/DeployPackaging.cmake
index e7f8dc6..dfef9dd 100644
--- a/cmake/cmake_celix/DeployPackaging.cmake
+++ b/cmake/cmake_celix/DeployPackaging.cmake
@@ -227,7 +227,7 @@ function(celix_container_bundles_dir)
                 COMMENT "Copying bundle '${BUNDLE}' to '${CONTAINER_LOC}/${BD_DIR_NAME}'"
                 DEPENDS $<TARGET_PROPERTY:${BUNDLE},BUNDLE_BUILD_BUNDLE_TARGET>
             )
-            get_target_property(BUILD_BUNDLE_TARGET ${BUNDLE} BUNDLE_BUILD_BUNDLE_TARGET)
+            get_target_property(BUILD_BUNDLE_TARGET ${BUNDLE} BUNDLE_TARGET)
             add_dependencies(${CONTAINER_TARGET} ${BUILD_BUNDLE_TARGET}) #ensure the the deploy depends on the _bundle target, custom_command depends on add_library
 
         endif()

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/dfi/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/dfi/CMakeLists.txt b/dfi/CMakeLists.txt
index ad3a41f..642ac68 100644
--- a/dfi/CMakeLists.txt
+++ b/dfi/CMakeLists.txt
@@ -18,36 +18,37 @@
 find_package(FFI REQUIRED)
 find_package(Jansson REQUIRED)
 
-add_library(dfi SHARED
-    src/dyn_common.c
-    src/dyn_type.c
-    src/dyn_function.c
-    src/dyn_interface.c
-    src/dyn_message.c
-    src/json_serializer.c
-    src/json_rpc.c
-)
-set_target_properties(dfi PROPERTIES OUTPUT_NAME "celix_dfi")
-
-target_include_directories(dfi PUBLIC
-	include
-	${JANSSON_INCLUDE_DIRS}
-)
-target_include_directories(dfi PRIVATE
-	src
-	${FFI_INCLUDE_DIRS}
+set(SOURCES
+	src/dyn_common.c
+	src/dyn_type.c
+	src/dyn_function.c
+	src/dyn_interface.c
+	src/dyn_message.c
+	src/json_serializer.c
+	src/json_rpc.c
 )
 
+add_library(dfi SHARED ${SOURCES})
+set_target_properties(dfi PROPERTIES OUTPUT_NAME "celix_dfi")
+target_include_directories(dfi PUBLIC include ${JANSSON_INCLUDE_DIRS})
+target_include_directories(dfi PRIVATE src ${FFI_INCLUDE_DIRS})
 target_link_libraries(dfi PUBLIC ${JANSSON_LIBRARY})
 target_link_libraries(dfi PRIVATE Celix::utils ${FFI_LIBRARIES})
-
 set_target_properties(dfi PROPERTIES "SOVERSION" 1)
 
-install(TARGETS dfi DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT framework)
+add_library(dfi_static STATIC ${SOURCES})
+set_target_properties(dfi_static PROPERTIES OUTPUT_NAME "celix_dfi_static")
+target_include_directories(dfi_static PUBLIC include ${JANSSON_INCLUDE_DIRS})
+target_include_directories(dfi_static PRIVATE src ${FFI_INCLUDE_DIRS})
+target_link_libraries(dfi_static PUBLIC ${JANSSON_LIBRARY})
+target_link_libraries(dfi_static PRIVATE Celix::utils ${FFI_LIBRARIES})
+
+install(TARGETS dfi dfi_static DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT framework)
 
 
 #Alias setup to match external usage
 add_library(Celix::dfi ALIAS dfi)
+add_library(Celix::dfi_static ALIAS dfi_static)
 
 if (ENABLE_TESTING)
     find_package(CppUTest REQUIRED)

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/framework/src/bundle_context.c
----------------------------------------------------------------------
diff --git a/framework/src/bundle_context.c b/framework/src/bundle_context.c
index face85d..928a7a4 100644
--- a/framework/src/bundle_context.c
+++ b/framework/src/bundle_context.c
@@ -222,7 +222,7 @@ celix_status_t bundleContext_ungetServiceReference(bundle_context_pt context, se
 celix_status_t bundleContext_getService(bundle_context_pt context, service_reference_pt reference, void** service_instance) {
     celix_status_t status = CELIX_SUCCESS;
 
-    if (context != NULL && reference != NULL && *service_instance == NULL) {
+    if (context != NULL && reference != NULL && service_instance != NULL) {
         /*NOTE argument service_instance should be considerd a 'const void**'. 
         To ensure backwards compatiblity a cast is made instead.
         */

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/log_service/loghelper_include/log_helper.h
----------------------------------------------------------------------
diff --git a/log_service/loghelper_include/log_helper.h b/log_service/loghelper_include/log_helper.h
index 04e4bb2..2ae9d83 100644
--- a/log_service/loghelper_include/log_helper.h
+++ b/log_service/loghelper_include/log_helper.h
@@ -24,6 +24,7 @@
 #include "bundle_context.h"
 #include "log_service.h"
 
+typedef struct log_helper log_helper_t;
 typedef struct log_helper* log_helper_pt;
 
 celix_status_t logHelper_create(bundle_context_pt context, log_helper_pt* log_helper);

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/log_writer/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/log_writer/CMakeLists.txt b/log_writer/CMakeLists.txt
index 340af15..e44ef65 100644
--- a/log_writer/CMakeLists.txt
+++ b/log_writer/CMakeLists.txt
@@ -23,5 +23,5 @@ if (LOG_WRITER)
 
     #Setup target aliases to match external usage
     add_library(Celix::log_writer_stdout ALIAS log_writer_stdout)
-    add_library(Celix::log_writer_syslog ALIAS log_writer_syslog)
+    #add_library(Celix::log_writer_syslog ALIAS log_writer_syslog)
 endif (LOG_WRITER)

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/CMakeLists.txt b/remote_services/CMakeLists.txt
index 7ca1c44..4e1f5b3 100644
--- a/remote_services/CMakeLists.txt
+++ b/remote_services/CMakeLists.txt
@@ -22,6 +22,8 @@ if (REMOTE_SERVICE_ADMIN)
 
     add_subdirectory(topology_manager)
 
+    add_subdirectory(civetweb)
+
     add_subdirectory(discovery_common)
     add_subdirectory(discovery_configured)
     add_subdirectory(discovery_etcd)

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/civetweb/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/civetweb/CMakeLists.txt b/remote_services/civetweb/CMakeLists.txt
new file mode 100644
index 0000000..e9e272e
--- /dev/null
+++ b/remote_services/civetweb/CMakeLists.txt
@@ -0,0 +1,23 @@
+# 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(civetweb OBJECT
+		src/civetweb.c
+		src/md5.inl
+)
+target_include_directories(civetweb PUBLIC include)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/civetweb/include/civetweb.h
----------------------------------------------------------------------
diff --git a/remote_services/civetweb/include/civetweb.h b/remote_services/civetweb/include/civetweb.h
new file mode 100644
index 0000000..61a8e98
--- /dev/null
+++ b/remote_services/civetweb/include/civetweb.h
@@ -0,0 +1,657 @@
+/* Copyright (c) 2013-2014 the Civetweb developers
+ * Copyright (c) 2004-2013 Sergey Lyubka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef CIVETWEB_HEADER_INCLUDED
+#define CIVETWEB_HEADER_INCLUDED
+
+#ifndef CIVETWEB_VERSION
+#define CIVETWEB_VERSION "1.7"
+#endif
+
+#ifndef CIVETWEB_API
+    #if defined(_WIN32)
+        #if defined(CIVETWEB_DLL_EXPORTS)
+            #define CIVETWEB_API __declspec(dllexport)
+        #elif defined(CIVETWEB_DLL_IMPORTS)
+            #define CIVETWEB_API __declspec(dllimport)
+        #else
+            #define CIVETWEB_API
+        #endif
+    #else
+        #define CIVETWEB_API
+    #endif
+#endif
+
+#include <stdio.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+struct mg_context;     /* Handle for the HTTP service itself */
+struct mg_connection;  /* Handle for the individual connection */
+
+
+/* This structure contains information about the HTTP request. */
+struct mg_request_info {
+    const char *request_method; /* "GET", "POST", etc */
+    const char *uri;            /* URL-decoded URI */
+    const char *http_version;   /* E.g. "1.0", "1.1" */
+    const char *query_string;   /* URL part after '?', not including '?', or
+                                   NULL */
+    const char *remote_user;    /* Authenticated user, or NULL if no auth
+                                   used */
+    char remote_addr[48];       /* Client's IP address as a string. */
+    long remote_ip;             /* Client's IP address. Deprecated: use remote_addr instead */
+
+    long long content_length;   /* Length (in bytes) of the request body,
+                                   can be -1 if no length was given. */
+    int remote_port;            /* Client's port */
+    int is_ssl;                 /* 1 if SSL-ed, 0 if not */
+    void *user_data;            /* User data pointer passed to mg_start() */
+    void *conn_data;            /* Connection-specific user data */
+
+    int num_headers;            /* Number of HTTP headers */
+    struct mg_header {
+        const char *name;       /* HTTP header name */
+        const char *value;      /* HTTP header value */
+    } http_headers[64];         /* Maximum 64 headers */
+};
+
+
+/* This structure needs to be passed to mg_start(), to let civetweb know
+   which callbacks to invoke. For a detailed description, see
+   https://github.com/bel2125/civetweb/blob/master/docs/UserManual.md */
+struct mg_callbacks {
+    /* Called when civetweb has received new HTTP request.
+       If the callback returns one, it must process the request
+       by sending valid HTTP headers and a body. Civetweb will not do
+       any further processing. Otherwise it must return zero.
+       Note that since V1.7 the "begin_request" function is called
+       before an authorization check. If an authorization check is
+       required, use a request_handler instead.
+       Return value:
+         0: civetweb will process the request itself. In this case,
+            the callback must not send any data to the client.
+         1: callback already processed the request. Civetweb will
+            not send any data after the callback returned. */
+    int  (*begin_request)(struct mg_connection *);
+
+    /* Called when civetweb has finished processing request. */
+    void (*end_request)(const struct mg_connection *, int reply_status_code);
+
+    /* Called when civetweb is about to log a message. If callback returns
+       non-zero, civetweb does not log anything. */
+    int  (*log_message)(const struct mg_connection *, const char *message);
+
+    /* Called when civetweb initializes SSL library.
+       Parameters:
+         user_data: parameter user_data passed when starting the server.
+       Return value:
+         0: civetweb will set up the SSL certificate.
+         1: civetweb assumes the callback already set up the certificate.
+        -1: initializing ssl fails. */
+    int  (*init_ssl)(void *ssl_context, void *user_data);
+
+    /* Called when websocket request is received, before websocket handshake.
+       Return value:
+         0: civetweb proceeds with websocket handshake.
+         1: connection is closed immediately. */
+    int (*websocket_connect)(const struct mg_connection *);
+
+    /* Called when websocket handshake is successfully completed, and
+       connection is ready for data exchange. */
+    void (*websocket_ready)(struct mg_connection *);
+
+    /* Called when data frame has been received from the client.
+       Parameters:
+         bits: first byte of the websocket frame, see websocket RFC at
+               http://tools.ietf.org/html/rfc6455, section 5.2
+         data, data_len: payload, with mask (if any) already applied.
+       Return value:
+         1: keep this websocket connection open.
+         0: close this websocket connection. */
+    int  (*websocket_data)(struct mg_connection *, int bits,
+                           char *data, size_t data_len);
+
+    /* Called when civetweb is closing a connection.  The per-context mutex is
+       locked when this is invoked.  This is primarily useful for noting when
+       a websocket is closing and removing it from any application-maintained
+       list of clients. */
+    void (*connection_close)(struct mg_connection *);
+
+    /* Called when civetweb tries to open a file. Used to intercept file open
+       calls, and serve file data from memory instead.
+       Parameters:
+          path:     Full path to the file to open.
+          data_len: Placeholder for the file size, if file is served from
+                    memory.
+       Return value:
+         NULL: do not serve file from memory, proceed with normal file open.
+         non-NULL: pointer to the file contents in memory. data_len must be
+           initilized with the size of the memory block. */
+    const char * (*open_file)(const struct mg_connection *,
+                              const char *path, size_t *data_len);
+
+    /* Called when civetweb is about to serve Lua server page, if
+       Lua support is enabled.
+       Parameters:
+         lua_context: "lua_State *" pointer. */
+    void (*init_lua)(struct mg_connection *, void *lua_context);
+
+    /* Called when civetweb has uploaded a file to a temporary directory as a
+       result of mg_upload() call.
+       Parameters:
+         file_name: full path name to the uploaded file. */
+    void (*upload)(struct mg_connection *, const char *file_name);
+
+    /* Called when civetweb is about to send HTTP error to the client.
+       Implementing this callback allows to create custom error pages.
+       Parameters:
+         status: HTTP error status code.
+       Return value:
+         1: run civetweb error handler.
+         0: callback already handled the error. */
+    int  (*http_error)(struct mg_connection *, int status);
+
+    /* Called after civetweb context has been created, before requests
+       are processed.
+       Parameters:
+         ctx: context handle */
+    void (*init_context)(struct mg_context * ctx);
+
+    /* Called when civetweb context is deleted.
+       Parameters:
+         ctx: context handle */
+    void (*exit_context)(struct mg_context * ctx);
+};
+
+
+/* Start web server.
+
+   Parameters:
+     callbacks: mg_callbacks structure with user-defined callbacks.
+     options: NULL terminated list of option_name, option_value pairs that
+              specify Civetweb configuration parameters.
+
+   Side-effects: on UNIX, ignores SIGCHLD and SIGPIPE signals. If custom
+      processing is required for these, signal handlers must be set up
+      after calling mg_start().
+
+
+   Example:
+     const char *options[] = {
+       "document_root", "/var/www",
+       "listening_ports", "80,443s",
+       NULL
+     };
+     struct mg_context *ctx = mg_start(&my_func, NULL, options);
+
+   Refer to https://github.com/bel2125/civetweb/blob/master/docs/UserManual.md
+   for the list of valid option and their possible values.
+
+   Return:
+     web server context, or NULL on error. */
+CIVETWEB_API struct mg_context *mg_start(const struct mg_callbacks *callbacks,
+                            void *user_data,
+                            const char **configuration_options);
+
+
+/* Stop the web server.
+
+   Must be called last, when an application wants to stop the web server and
+   release all associated resources. This function blocks until all Civetweb
+   threads are stopped. Context pointer becomes invalid. */
+CIVETWEB_API void mg_stop(struct mg_context *);
+
+
+/* mg_request_handler
+
+   Called when a new request comes in.  This callback is URI based
+   and configured with mg_set_request_handler().
+
+   Parameters:
+      conn: current connection information.
+      cbdata: the callback data configured with mg_set_request_handler().
+   Returns:
+      0: the handler could not handle the request, so fall through.
+      1: the handler processed the request. */
+typedef int (* mg_request_handler)(struct mg_connection *conn, void *cbdata);
+
+
+/* mg_set_request_handler
+
+   Sets or removes a URI mapping for a request handler.
+
+   URI's are ordered and prefixed URI's are supported. For example,
+   consider two URIs: /a/b and /a
+           /a   matches /a
+           /a/b matches /a/b
+           /a/c matches /a
+
+   Parameters:
+      ctx: server context
+      uri: the URI to configure
+      handler: the callback handler to use when the URI is requested.
+               If NULL, the URI will be removed.
+      cbdata: the callback data to give to the handler when it s requested. */
+CIVETWEB_API void mg_set_request_handler(struct mg_context *ctx, const char *uri, mg_request_handler handler, void *cbdata);
+
+
+/* Get the value of particular configuration parameter.
+   The value returned is read-only. Civetweb does not allow changing
+   configuration at run time.
+   If given parameter name is not valid, NULL is returned. For valid
+   names, return value is guaranteed to be non-NULL. If parameter is not
+   set, zero-length string is returned. */
+CIVETWEB_API const char *mg_get_option(const struct mg_context *ctx, const char *name);
+
+
+/* Get context from connection. */
+CIVETWEB_API struct mg_context *mg_get_context(struct mg_connection *conn);
+
+
+/* Get user data passed to mg_start from context. */
+CIVETWEB_API void *mg_get_user_data(struct mg_context *ctx);
+
+
+#if defined(MG_LEGACY_INTERFACE)
+/* Return array of strings that represent valid configuration options.
+   For each option, option name and default value is returned, i.e. the
+   number of entries in the array equals to number_of_options x 2.
+   Array is NULL terminated. */
+/* Deprecated: Use mg_get_valid_options instead. */
+CIVETWEB_API const char **mg_get_valid_option_names(void);
+#endif
+
+
+struct mg_option {
+    const char * name;
+    int type;
+    const char * default_value;
+};
+
+enum {
+    CONFIG_TYPE_UNKNOWN = 0x0,
+    CONFIG_TYPE_NUMBER = 0x1,
+    CONFIG_TYPE_STRING = 0x2,
+    CONFIG_TYPE_FILE = 0x3,
+    CONFIG_TYPE_DIRECTORY = 0x4,
+    CONFIG_TYPE_BOOLEAN = 0x5,
+    CONFIG_TYPE_EXT_PATTERN = 0x6
+};
+
+
+/* Return array of struct mg_option, representing all valid configuration
+   options of civetweb.c.
+   The array is terminated by a NULL name option. */
+CIVETWEB_API const struct mg_option *mg_get_valid_options(void);
+
+
+/* Get the list of ports that civetweb is listening on.
+   size is the size of the ports int array and ssl int array to fill.
+   It is the caller's responsibility to make sure ports and ssl each
+   contain at least size int elements worth of memory to write into.
+   Return value is the number of ports and ssl information filled in.
+   The value returned is read-only. Civetweb does not allow changing
+   configuration at run time. */
+CIVETWEB_API size_t mg_get_ports(const struct mg_context *ctx, size_t size, int* ports, int* ssl);
+
+
+/* Add, edit or delete the entry in the passwords file.
+
+   This function allows an application to manipulate .htpasswd files on the
+   fly by adding, deleting and changing user records. This is one of the
+   several ways of implementing authentication on the server side. For another,
+   cookie-based way please refer to the examples/chat in the source tree.
+
+   If password is not NULL, entry is added (or modified if already exists).
+   If password is NULL, entry is deleted.
+
+   Return:
+     1 on success, 0 on error. */
+CIVETWEB_API int mg_modify_passwords_file(const char *passwords_file_name,
+                                          const char *domain,
+                                          const char *user,
+                                          const char *password);
+
+
+/* Return information associated with the request. */
+CIVETWEB_API struct mg_request_info *mg_get_request_info(struct mg_connection *);
+
+
+/* Send data to the client.
+   Return:
+    0   when the connection has been closed
+    -1  on error
+    >0  number of bytes written on success */
+CIVETWEB_API int mg_write(struct mg_connection *, const void *buf, size_t len);
+
+
+/* Send data to a websocket client wrapped in a websocket frame.  Uses mg_lock
+   to ensure that the transmission is not interrupted, i.e., when the
+   application is proactively communicating and responding to a request
+   simultaneously.
+
+   Send data to a websocket client wrapped in a websocket frame.
+   This function is available when civetweb is compiled with -DUSE_WEBSOCKET
+
+   Return:
+    0   when the connection has been closed
+    -1  on error
+    >0  number of bytes written on success */
+CIVETWEB_API int mg_websocket_write(struct mg_connection* conn, int opcode,
+                                    const char *data, size_t data_len);
+
+
+/* Blocks until unique access is obtained to this connection. Intended for use
+   with websockets only.
+   Invoke this before mg_write or mg_printf when communicating with a
+   websocket if your code has server-initiated communication as well as
+   communication in direct response to a message. */
+CIVETWEB_API void mg_lock_connection(struct mg_connection* conn);
+CIVETWEB_API void mg_unlock_connection(struct mg_connection* conn);
+
+#if defined(MG_LEGACY_INTERFACE)
+#define mg_lock mg_lock_connection
+#define mg_unlock mg_unlock_connection
+#endif
+
+/* Lock server context.  This lock may be used to protect ressources
+   that are shared between different connection/worker threads. */
+CIVETWEB_API void mg_lock_context(struct mg_context* ctx);
+CIVETWEB_API void mg_unlock_context(struct mg_context* ctx);
+
+
+/* Opcodes, from http://tools.ietf.org/html/rfc6455 */
+enum {
+    WEBSOCKET_OPCODE_CONTINUATION = 0x0,
+    WEBSOCKET_OPCODE_TEXT = 0x1,
+    WEBSOCKET_OPCODE_BINARY = 0x2,
+    WEBSOCKET_OPCODE_CONNECTION_CLOSE = 0x8,
+    WEBSOCKET_OPCODE_PING = 0x9,
+    WEBSOCKET_OPCODE_PONG = 0xa
+};
+
+
+/* Macros for enabling compiler-specific checks forprintf-like arguments. */
+#undef PRINTF_FORMAT_STRING
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+#include <sal.h>
+#if defined(_MSC_VER) && _MSC_VER > 1400
+#define PRINTF_FORMAT_STRING(s) _Printf_format_string_ s
+#else
+#define PRINTF_FORMAT_STRING(s) __format_string s
+#endif
+#else
+#define PRINTF_FORMAT_STRING(s) s
+#endif
+
+#ifdef __GNUC__
+#define PRINTF_ARGS(x, y) __attribute__((format(printf, x, y)))
+#else
+#define PRINTF_ARGS(x, y)
+#endif
+
+/* Send data to the client usingprintf() semantics.
+   Works exactly like mg_write(), but allows to do message formatting. */
+CIVETWEB_API int mg_printf(struct mg_connection *,
+                           PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3);
+
+
+/* Send contents of the entire file together with HTTP headers. */
+CIVETWEB_API void mg_send_file(struct mg_connection *conn, const char *path);
+
+
+/* Read data from the remote end, return number of bytes read.
+   Return:
+     0     connection has been closed by peer. No more data could be read.
+     < 0   read error. No more data could be read from the connection.
+     > 0   number of bytes read into the buffer. */
+CIVETWEB_API int mg_read(struct mg_connection *, void *buf, size_t len);
+
+
+/* Get the value of particular HTTP header.
+
+   This is a helper function. It traverses request_info->http_headers array,
+   and if the header is present in the array, returns its value. If it is
+   not present, NULL is returned. */
+CIVETWEB_API const char *mg_get_header(const struct mg_connection *, const char *name);
+
+
+/* Get a value of particular form variable.
+
+   Parameters:
+     data: pointer to form-uri-encoded buffer. This could be either POST data,
+           or request_info.query_string.
+     data_len: length of the encoded data.
+     var_name: variable name to decode from the buffer
+     dst: destination buffer for the decoded variable
+     dst_len: length of the destination buffer
+
+   Return:
+     On success, length of the decoded variable.
+     On error:
+        -1 (variable not found).
+        -2 (destination buffer is NULL, zero length or too small to hold the
+            decoded variable).
+
+   Destination buffer is guaranteed to be '\0' - terminated if it is not
+   NULL or zero length. */
+CIVETWEB_API int mg_get_var(const char *data, size_t data_len,
+                            const char *var_name, char *dst, size_t dst_len);
+
+
+/* Get a value of particular form variable.
+
+   Parameters:
+     data: pointer to form-uri-encoded buffer. This could be either POST data,
+           or request_info.query_string.
+     data_len: length of the encoded data.
+     var_name: variable name to decode from the buffer
+     dst: destination buffer for the decoded variable
+     dst_len: length of the destination buffer
+     occurrence: which occurrence of the variable, 0 is the first, 1 the
+                 second...
+                this makes it possible to parse a query like
+                b=x&a=y&a=z which will have occurrence values b:0, a:0 and a:1
+
+   Return:
+     On success, length of the decoded variable.
+     On error:
+        -1 (variable not found).
+        -2 (destination buffer is NULL, zero length or too small to hold the
+            decoded variable).
+
+   Destination buffer is guaranteed to be '\0' - terminated if it is not
+   NULL or zero length. */
+CIVETWEB_API int mg_get_var2(const char *data, size_t data_len,
+                             const char *var_name, char *dst, size_t dst_len, size_t occurrence);
+
+
+/* Fetch value of certain cookie variable into the destination buffer.
+
+   Destination buffer is guaranteed to be '\0' - terminated. In case of
+   failure, dst[0] == '\0'. Note that RFC allows many occurrences of the same
+   parameter. This function returns only first occurrence.
+
+   Return:
+     On success, value length.
+     On error:
+        -1 (either "Cookie:" header is not present at all or the requested
+            parameter is not found).
+        -2 (destination buffer is NULL, zero length or too small to hold the
+            value). */
+CIVETWEB_API int mg_get_cookie(const char *cookie, const char *var_name,
+                               char *buf, size_t buf_len);
+
+
+/* Download data from the remote web server.
+     host: host name to connect to, e.g. "foo.com", or "10.12.40.1".
+     port: port number, e.g. 80.
+     use_ssl: wether to use SSL connection.
+     error_buffer, error_buffer_size: error message placeholder.
+     request_fmt,...: HTTP request.
+   Return:
+     On success, valid pointer to the new connection, suitable for mg_read().
+     On error, NULL. error_buffer contains error message.
+   Example:
+     char ebuf[100];
+     struct mg_connection *conn;
+     conn = mg_download("google.com", 80, 0, ebuf, sizeof(ebuf),
+                        "%s", "GET / HTTP/1.0\r\nHost: google.com\r\n\r\n");
+ */
+CIVETWEB_API struct mg_connection *mg_download(const char *host, int port, int use_ssl,
+                                               char *error_buffer, size_t error_buffer_size,
+                                               PRINTF_FORMAT_STRING(const char *request_fmt),
+                                               ...) PRINTF_ARGS(6, 7);
+
+
+/* Close the connection opened by mg_download(). */
+CIVETWEB_API void mg_close_connection(struct mg_connection *conn);
+
+
+/* File upload functionality. Each uploaded file gets saved into a temporary
+   file and MG_UPLOAD event is sent.
+   Return number of uploaded files. */
+CIVETWEB_API int mg_upload(struct mg_connection *conn, const char *destination_dir);
+
+
+/* Convenience function -- create detached thread.
+   Return: 0 on success, non-0 on error. */
+typedef void * (*mg_thread_func_t)(void *);
+CIVETWEB_API int mg_start_thread(mg_thread_func_t f, void *p);
+
+
+/* Return builtin mime type for the given file name.
+   For unrecognized extensions, "text/plain" is returned. */
+CIVETWEB_API const char *mg_get_builtin_mime_type(const char *file_name);
+
+
+/* Return Civetweb version. */
+CIVETWEB_API const char *mg_version(void);
+
+
+/* URL-decode input buffer into destination buffer.
+   0-terminate the destination buffer.
+   form-url-encoded data differs from URI encoding in a way that it
+   uses '+' as character for space, see RFC 1866 section 8.2.1
+   http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
+   Return: length of the decoded data, or -1 if dst buffer is too small. */
+CIVETWEB_API int mg_url_decode(const char *src, int src_len, char *dst,
+                               int dst_len, int is_form_url_encoded);
+
+
+/* URL-encode input buffer into destination buffer.
+   returns the length of the resulting buffer or -1
+   is the buffer is too small. */
+CIVETWEB_API int mg_url_encode(const char *src, char *dst, size_t dst_len);
+
+
+/* MD5 hash given strings.
+   Buffer 'buf' must be 33 bytes long. Varargs is a NULL terminated list of
+   ASCIIz strings. When function returns, buf will contain human-readable
+   MD5 hash. Example:
+     char buf[33];
+     mg_md5(buf, "aa", "bb", NULL); */
+CIVETWEB_API char *mg_md5(char buf[33], ...);
+
+
+/* Print error message to the opened error log stream.
+   This utilizes the provided logging configuration.
+     conn: connection
+     fmt: format string without the line return
+     ...: variable argument list
+   Example:
+     mg_cry(conn,"i like %s", "logging"); */
+CIVETWEB_API void mg_cry(struct mg_connection *conn,
+                         PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3);
+
+
+/* utility method to compare two buffers, case incensitive. */
+CIVETWEB_API int mg_strncasecmp(const char *s1, const char *s2, size_t len);
+
+/* Connect to a websocket as a client
+   Parameters:
+     host: host to connect to, i.e. "echo.websocket.org" or "192.168.1.1" or "localhost"
+     port: server port
+     use_ssl: make a secure connection to server
+     error_buffer, error_buffer_size: buffer for an error message
+     path: server path you are trying to connect to, i.e. if connection to localhost/app, path should be "/app"
+     origin: value of the Origin HTTP header
+     data_func: callback that should be used when data is received from the server
+     user_data: user supplied argument
+
+   Return:
+     On success, valid mg_connection object.
+     On error, NULL. Se error_buffer for details.
+*/
+
+typedef int  (*websocket_data_func)(struct mg_connection *, int bits,
+                           char *data, size_t data_len);
+
+typedef void (*websocket_close_func)(struct mg_connection *);
+
+CIVETWEB_API struct mg_connection *mg_connect_websocket_client(const char *host, int port, int use_ssl,
+                                               char *error_buffer, size_t error_buffer_size,
+                                               const char *path, const char *origin,
+                                               websocket_data_func data_func, websocket_close_func close_func,
+                                               void * user_data);
+
+/* Connect to a TCP server as a client (can be used to connect to a HTTP server)
+   Parameters:
+     host: host to connect to, i.e. "www.wikipedia.org" or "192.168.1.1" or "localhost"
+     port: server port
+     use_ssl: make a secure connection to server
+     error_buffer, error_buffer_size: buffer for an error message
+
+   Return:
+     On success, valid mg_connection object.
+     On error, NULL. Se error_buffer for details.
+*/
+CIVETWEB_API struct mg_connection *mg_connect_client(const char *host, int port, int use_ssl,
+                                               char *error_buffer, size_t error_buffer_size);
+
+
+enum {
+    TIMEOUT_INFINITE = -1
+};
+
+/* Wait for a response from the server
+   Parameters:
+     conn: connection
+     ebuf, ebuf_len: error message placeholder.
+     timeout: time to wait for a response in milliseconds (if < 0 then wait forever)
+
+   Return:
+     On success, >= 0
+     On error/timeout, < 0
+*/
+CIVETWEB_API int mg_get_response(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int timeout);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* CIVETWEB_HEADER_INCLUDED */


[8/8] celix git commit: CELIX-417: Renames remote services target. Mostly adding the rsa prefix

Posted by pn...@apache.org.
CELIX-417: Renames remote services target. Mostly adding the rsa prefix


Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/486d4f0d
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/486d4f0d
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/486d4f0d

Branch: refs/heads/feature/CELIX-417-cmake-refactor
Commit: 486d4f0d5c86f0770f047e3ecc4caf77af9886a7
Parents: 27a2aa7
Author: Pepijn Noltes <pe...@gmail.com>
Authored: Fri Nov 24 11:58:59 2017 +0100
Committer: Pepijn Noltes <pe...@gmail.com>
Committed: Fri Nov 24 11:58:59 2017 +0100

----------------------------------------------------------------------
 remote_services/CMakeLists.txt                  |  1 -
 remote_services/civetweb/CMakeLists.txt         |  5 +-
 remote_services/discovery_common/CMakeLists.txt | 10 +--
 .../src/endpoint_descriptor_reader.c            | 94 --------------------
 .../src/endpoint_descriptor_writer.c            | 37 --------
 .../discovery_configured/CMakeLists.txt         | 35 +++-----
 remote_services/discovery_etcd/CMakeLists.txt   | 23 ++---
 remote_services/discovery_shm/CMakeLists.txt    | 19 ++--
 remote_services/examples/CMakeLists.txt         |  4 +-
 .../examples/calculator_service/CMakeLists.txt  |  2 +-
 .../remote_service_admin_api/CMakeLists.txt     |  6 +-
 .../remote_service_admin_common/CMakeLists.txt  |  9 +-
 .../remote_service_admin_dfi/CMakeLists.txt     | 14 +--
 .../test/CMakeLists.txt                         | 11 ++-
 remote_services/topology_manager/CMakeLists.txt | 13 +--
 .../topology_manager/tms_tst/CMakeLists.txt     | 10 +--
 .../tms_tst/bundle/CMakeLists.txt               |  2 +-
 .../tms_tst/disc_mock/CMakeLists.txt            |  2 +-
 18 files changed, 79 insertions(+), 218 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/486d4f0d/remote_services/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/CMakeLists.txt b/remote_services/CMakeLists.txt
index 4e1f5b3..bb45908 100644
--- a/remote_services/CMakeLists.txt
+++ b/remote_services/CMakeLists.txt
@@ -23,7 +23,6 @@ if (REMOTE_SERVICE_ADMIN)
     add_subdirectory(topology_manager)
 
     add_subdirectory(civetweb)
-
     add_subdirectory(discovery_common)
     add_subdirectory(discovery_configured)
     add_subdirectory(discovery_etcd)

http://git-wip-us.apache.org/repos/asf/celix/blob/486d4f0d/remote_services/civetweb/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/civetweb/CMakeLists.txt b/remote_services/civetweb/CMakeLists.txt
index e9e272e..a6f7d10 100644
--- a/remote_services/civetweb/CMakeLists.txt
+++ b/remote_services/civetweb/CMakeLists.txt
@@ -20,4 +20,7 @@ add_library(civetweb OBJECT
 		src/civetweb.c
 		src/md5.inl
 )
-target_include_directories(civetweb PUBLIC include)
\ No newline at end of file
+target_include_directories(civetweb PUBLIC include)
+
+#Setup target aliases to match external usage
+add_library(Celix::civetweb ALIAS civetweb)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/486d4f0d/remote_services/discovery_common/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/discovery_common/CMakeLists.txt b/remote_services/discovery_common/CMakeLists.txt
index 5b28b13..c3242a6 100644
--- a/remote_services/discovery_common/CMakeLists.txt
+++ b/remote_services/discovery_common/CMakeLists.txt
@@ -18,7 +18,7 @@
 
 find_package(LibXml2 REQUIRED)
 
-add_library(discovery_common OBJECT
+add_library(rsa_discovery_common OBJECT
 		src/discovery.c
 		src/discovery_activator.c
 		src/endpoint_descriptor_reader.c
@@ -26,14 +26,14 @@ add_library(discovery_common OBJECT
 		src/endpoint_discovery_poller.c
 		src/endpoint_discovery_server.c
 )
-target_include_directories(discovery_common PUBLIC
+target_include_directories(rsa_discovery_common PUBLIC
 		include src
 		$<TARGET_PROPERTY:Celix::framework,INTERFACE_INCLUDE_DIRECTORIES>
 		$<TARGET_PROPERTY:Celix::utils,INTERFACE_INCLUDE_DIRECTORIES>
 		$<TARGET_PROPERTY:Celix::log_helper,INTERFACE_INCLUDE_DIRECTORIES>
-		$<TARGET_PROPERTY:Celix::remote_service_admin_api,INTERFACE_INCLUDE_DIRECTORIES>
-		$<TARGET_PROPERTY:Celix::remote_service_admin_api,INTERFACE_INCLUDE_DIRECTORIES>
+		$<TARGET_PROPERTY:Celix::rsa_api,INTERFACE_INCLUDE_DIRECTORIES>
 		$<TARGET_PROPERTY:civetweb,INCLUDE_DIRECTORIES>
 		${LIBXML2_INCLUDE_DIR})
 
-add_library(Celix::discovery_common ALIAS discovery_common)
\ No newline at end of file
+#Setup target aliases to match external usage
+add_library(Celix::rsa_discovery_common ALIAS rsa_discovery_common)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/486d4f0d/remote_services/discovery_common/src/endpoint_descriptor_reader.c
----------------------------------------------------------------------
diff --git a/remote_services/discovery_common/src/endpoint_descriptor_reader.c b/remote_services/discovery_common/src/endpoint_descriptor_reader.c
index ea176bf..887bc29 100644
--- a/remote_services/discovery_common/src/endpoint_descriptor_reader.c
+++ b/remote_services/discovery_common/src/endpoint_descriptor_reader.c
@@ -291,97 +291,3 @@ static valueType valueTypeFromString(char *name) {
     }
 }
 
-#ifdef RSA_ENDPOINT_TEST_READER
-int main() {
-    array_list_pt list = NULL;
-    endpoint_descriptor_reader_pt reader = NULL;
-
-    char *doc = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
-"<endpoint-descriptions xmlns=\"http://www.osgi.org/xmlns/rsa/v1.0.0\">"
-    "<endpoint-description>"
-    	"<property name=\"endpoint.service.id\" value-type=\"long\" value=\"6\"/>"
-		"<property name=\"endpoint.framework.uuid\" value=\"2983D849-93B1-4C2C-AC6D-5BCDA93ACB96\"/>"
-        "<property name=\"service.intents\">"
-            "<list>"
-                "<value>SOAP</value>"
-                "<value>HTTP</value>"
-            "</list>"
-        "</property>"
-        "<property name=\"endpoint.id\" value=\"11111111-1111-1111-1111-111111111111\" />"
-        "<property name=\"objectClass\"><array><value>com.acme.Foo</value></array></property>"
-        "<property name=\"endpoint.package.version.com.acme\" value=\"4.2\" />"
-        "<property name=\"service.imported.configs\" value=\"com.acme\" />"
-    	"<property name=\"service.imported\" value=\"true\"/>"
-        "<property name=\"com.acme.ws.xml\">"
-            "<xml>"
-                "<config xmlns=\"http://acme.com/defs\">"
-                    "<port>1029</port>"
-                    "<host>www.acme.com</host>"
-                "</config>"
-            "</xml>"
-        "</property>"
-    "</endpoint-description>"
-		"<endpoint-description>"
-        	"<property name=\"endpoint.service.id\" value-type=\"long\" value=\"5\"/>"
-    		"<property name=\"endpoint.framework.uuid\" value=\"2983D849-93B1-4C2C-AC6D-5BCDA93ACB96\"/>"
-			"<property name=\"service.intents\">"
-				"<list>"
-					"<value>SOAP</value>"
-					"<value>HTTP</value>"
-				"</list>"
-			"</property>"
-			"<property name=\"endpoint.id\" value=\"22222222-2222-2222-2222-222222222222\" />"
-            "<property name=\"objectClass\"><array><value>com.acme.Bar</value></array></property>"
-			"<property name=\"endpoint.package.version.com.acme\" value=\"4.2\" />"
-			"<property name=\"service.imported.configs\" value=\"com.acme\" />"
-			"<property name=\"com.acme.ws.xml\">"
-				"<xml>"
-					"<config xmlns=\"http://acme.com/defs\">"
-						"<port>1029</port>"
-						"<host>www.acme.com</host>"
-					"</config>"
-				"</xml>"
-			"</property>"
-		"</endpoint-description>"
-	"</endpoint-descriptions>";
-
-	endpointDescriptorReader_create(&reader);
-
-	endpointDescriptorReader_parseDocument(reader, doc, &list);
-
-	int i;
-	for (i = 0; i < arrayList_size(list); i++) {
-		printf("\nEndpoint description #%d:\n", (i+1));
-		endpoint_description_pt edp = arrayList_get(list, i);
-		printf("Id: %s\n", edp->id);
-		printf("Service Id: %lu\n", edp->serviceId);
-		printf("Framework UUID: %s\n", edp->frameworkUUID);
-		printf("Service: %s\n", edp->service);
-
-		properties_pt props = edp->properties;
-		if (props) {
-			printf("Service properties:\n");
-			hash_map_iterator_pt iter = hashMapIterator_create(props);
-			while (hashMapIterator_hasNext(iter)) {
-				hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
-
-				printf("- %s => '%s'\n", hashMapEntry_getKey(entry), hashMapEntry_getValue(entry));
-			}
-			hashMapIterator_destroy(iter);
-		} else {
-			printf("No service properties...\n");
-		}
-
-
-		endpointDescription_destroy(edp);
-	}
-
-	if (list != NULL) {
-		arrayList_destroy(list);
-	}
-
-	endpointDescriptorReader_destroy(reader);
-
-    return 0;
-}
-#endif

http://git-wip-us.apache.org/repos/asf/celix/blob/486d4f0d/remote_services/discovery_common/src/endpoint_descriptor_writer.c
----------------------------------------------------------------------
diff --git a/remote_services/discovery_common/src/endpoint_descriptor_writer.c b/remote_services/discovery_common/src/endpoint_descriptor_writer.c
index 71b07b4..4a5bcd7 100644
--- a/remote_services/discovery_common/src/endpoint_descriptor_writer.c
+++ b/remote_services/discovery_common/src/endpoint_descriptor_writer.c
@@ -194,40 +194,3 @@ static char* valueTypeToString(valueType type) {
 			return "string";
 	}
 }
-
-#ifdef RSA_ENDPOINT_TEST_WRITER
-int main() {
-    endpoint_descriptor_writer_pt writer = NULL;
-    endpointDescriptorWriter_create(&writer);
-    array_list_pt list = NULL;
-    arrayList_create(&list);
-
-    properties_pt props = properties_create();
-    properties_set(props, "objectClass", "com.acme.Foo");
-    properties_set(props, "endpoint.service.id", "3");
-    properties_set(props, "endpoint.id", "abcdefghijklmnopqrstuvwxyz");
-    properties_set(props, "endpoint.framework.uuid", "2983D849-93B1-4C2C-AC6D-5BCDA93ACB96");
-    endpoint_description_pt epd = NULL;
-    endpointDescription_create(props, &epd);
-    arrayList_add(list, epd);
-
-    properties_pt props2 = properties_create();
-    properties_set(props2, "objectClass", "com.acme.Bar");
-    properties_set(props, "endpoint.service.id", "4");
-    properties_set(props, "endpoint.id", "abcdefghijklmnopqrstuvwxyz");
-    properties_set(props, "endpoint.framework.uuid", "2983D849-93B1-4C2C-AC6D-5BCDA93ACB96");
-    endpoint_description_pt epd2 = NULL;
-    endpointDescription_create(props2, &epd2);
-    arrayList_add(list, epd2);
-
-    char *buffer = NULL;
-    endpointDescriptorWriter_writeDocument(writer, list, &buffer);
-
-    arrayList_destroy(list);
-    endpointDescription_destroy(epd);
-    endpointDescription_destroy(epd2);
-    endpointDescriptorWriter_destroy(writer);
-
-    printf("%s\n", buffer);
-}
-#endif

http://git-wip-us.apache.org/repos/asf/celix/blob/486d4f0d/remote_services/discovery_configured/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/discovery_configured/CMakeLists.txt b/remote_services/discovery_configured/CMakeLists.txt
index f7d104b..bea485e 100644
--- a/remote_services/discovery_configured/CMakeLists.txt
+++ b/remote_services/discovery_configured/CMakeLists.txt
@@ -19,39 +19,24 @@ if (RSA_DISCOVERY_CONFIGURED)
     find_package(CURL REQUIRED)
     find_package(LibXml2 REQUIRED)
 
-    add_bundle(discovery_configured 
+    add_bundle(rsa_discovery_configured
         VERSION 0.9.0
         SYMBOLIC_NAME "apache_celix_rsa_discovery_configured"
         NAME "Apache Celix RSA Configured Discovery"
         SOURCES
 	        src/discovery_impl.c
-            $<TARGET_OBJECTS:discovery_common>
-            $<TARGET_OBJECTS:civetweb>
+            $<TARGET_OBJECTS:Celix::rsa_discovery_common>
+            $<TARGET_OBJECTS:Celix::civetweb>
     )
-    target_include_directories(discovery_configured PRIVATE
+    target_include_directories(rsa_discovery_configured PRIVATE
             src
-            $<TARGET_PROPERTY:discovery_common,INCLUDE_DIRECTORIES>
-            $<TARGET_PROPERTY:civetweb,INCLUDE_DIRECTORIES>
+            $<TARGET_PROPERTY:Celix::rsa_discovery_common,INCLUDE_DIRECTORIES>
+            $<TARGET_PROPERTY:Celix::civetweb,INCLUDE_DIRECTORIES>
     )
-    target_link_libraries(discovery_configured PRIVATE ${CURL_LIBRARIES} ${LIBXML2_LIBRARIES} Celix::log_helper)
+    target_link_libraries(rsa_discovery_configured PRIVATE ${CURL_LIBRARIES} ${LIBXML2_LIBRARIES} Celix::log_helper)
 
-    install_bundle(discovery_configured)
+    install_bundle(rsa_discovery_configured)
 
-
-
-    if (RSA_ENDPOINT_TEST_READER)
-        add_executable(descparser
-            ${PROJECT_SOURCE_DIR}/remote_services/discovery/private/src/endpoint_descriptor_reader.c
-            ${PROJECT_SOURCE_DIR}/remote_services/remote_service_admin/private/src/endpoint_description.c)
-
-        target_link_libraries(descparser ${LIBXML2_LIBRARIES} celix_framework celix_utils)
-    endif (RSA_ENDPOINT_TEST_READER)
-
-    if (RSA_ENDPOINT_TEST_WRITER)
-        add_executable(descwriter
-            ${PROJECT_SOURCE_DIR}/remote_services/discovery/private/src/endpoint_descriptor_writer.c
-            ${PROJECT_SOURCE_DIR}/remote_services/remote_service_admin/private/src/endpoint_description.c)
-
-        target_link_libraries(descwriter ${LIBXML2_LIBRARIES} celix_framework celix_utils)
-    endif(RSA_ENDPOINT_TEST_WRITER)
+    #Setup target aliases to match external usage
+    add_library(Celix::rsa_discovery_configured ALIAS rsa_discovery_configured)
 endif (RSA_DISCOVERY_CONFIGURED)

http://git-wip-us.apache.org/repos/asf/celix/blob/486d4f0d/remote_services/discovery_etcd/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/discovery_etcd/CMakeLists.txt b/remote_services/discovery_etcd/CMakeLists.txt
index 9c8edc8..19726fc 100644
--- a/remote_services/discovery_etcd/CMakeLists.txt
+++ b/remote_services/discovery_etcd/CMakeLists.txt
@@ -21,26 +21,29 @@ if (RSA_DISCOVERY_ETCD)
 	find_package(LibXml2 REQUIRED)
 	find_package(Jansson REQUIRED)
     
-	add_bundle(discovery_etcd 
+	add_bundle(rsa_discovery_etcd
         VERSION 0.9.0
         SYMBOLIC_NAME "apache_celix_rsa_discovery_etcd"
         NAME "Apache Celix RSA Discovery ETCD"
         SOURCES
 			src/discovery_impl.c
 	    	src/etcd_watcher.c
-			$<TARGET_OBJECTS:discovery_common>
-			$<TARGET_OBJECTS:civetweb>
+			$<TARGET_OBJECTS:Celix::rsa_discovery_common>
+			$<TARGET_OBJECTS:Celix::civetweb>
 	)
-	target_link_libraries(discovery_etcd PRIVATE Celix::log_helper Celix::etcdlib_static)
-	target_include_directories(discovery_etcd PRIVATE src)
-	target_include_directories(discovery_etcd PRIVATE
-			$<TARGET_PROPERTY:discovery_common,INCLUDE_DIRECTORIES>
-			$<TARGET_PROPERTY:civetweb,INCLUDE_DIRECTORIES>
+	target_link_libraries(rsa_discovery_etcd PRIVATE Celix::log_helper Celix::etcdlib_static)
+	target_include_directories(rsa_discovery_etcd PRIVATE src)
+	target_include_directories(rsa_discovery_etcd PRIVATE
+			$<TARGET_PROPERTY:Celix::rsa_discovery_common,INCLUDE_DIRECTORIES>
+			$<TARGET_PROPERTY:Celix::civetweb,INCLUDE_DIRECTORIES>
 			${CURL_INCLUDE_DIR}
 			${JANSSON_INCLUDE_DIR}
 			${LIBXML2_INCLUDE_DIR}
 	)
-	target_link_libraries(discovery_etcd PRIVATE ${CURL_LIBRARIES} ${LIBXML2_LIBRARIES} ${JANSSON_LIBRARIES})
+	target_link_libraries(rsa_discovery_etcd PRIVATE ${CURL_LIBRARIES} ${LIBXML2_LIBRARIES} ${JANSSON_LIBRARIES})
 
-	install_bundle(discovery_etcd)
+	install_bundle(rsa_discovery_etcd)
+
+	#Setup target aliases to match external usage
+	add_library(Celix::rsa_discovery_etcd ALIAS rsa_discovery_etcd)
 endif (RSA_DISCOVERY_ETCD)

http://git-wip-us.apache.org/repos/asf/celix/blob/486d4f0d/remote_services/discovery_shm/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/discovery_shm/CMakeLists.txt b/remote_services/discovery_shm/CMakeLists.txt
index 61e54f7..fd822e6 100644
--- a/remote_services/discovery_shm/CMakeLists.txt
+++ b/remote_services/discovery_shm/CMakeLists.txt
@@ -20,7 +20,7 @@ if (RSA_DISCOVERY_SHM)
 find_package(CURL REQUIRED)
 	find_package(LibXml2 REQUIRED)
 
-	add_bundle(discovery_shm 
+	add_bundle(rsa_discovery_shm
         VERSION 0.0.1
         SYMBOLIC_NAME "apache_celix_rsa_discovery_shm"
         NAME "Apache Celix RSA Discovery SHM"
@@ -28,20 +28,21 @@ find_package(CURL REQUIRED)
 			src/discovery_shm.c
 			src/discovery_shmWatcher.c
 			src/discovery_impl.c
-			$<TARGET_OBJECTS:discovery_common>
-			$<TARGET_OBJECTS:civetweb>
+			$<TARGET_OBJECTS:Celix::rsa_discovery_common>
+			$<TARGET_OBJECTS:Celix::civetweb>
 	)
-	target_include_directories(discovery_shm PRIVATE
+	target_include_directories(rsa_discovery_shm PRIVATE
 			src
 			${LIBXML2_INCLUDE_DIR}
 			${CURL_INCLUDE_DIR}
-			$<TARGET_PROPERTY:discovery_common,INCLUDE_DIRECTORIES>
-			$<TARGET_PROPERTY:civetweb,INCLUDE_DIRECTORIES>
+			$<TARGET_PROPERTY:Celix::rsa_discovery_common,INCLUDE_DIRECTORIES>
+			$<TARGET_PROPERTY:Celix::civetweb,INCLUDE_DIRECTORIES>
 	)
-	target_link_libraries(discovery_shm PRIVATE Celix::framework ${CURL_LIBRARIES} ${LIBXML2_LIBRARIES})
+	target_link_libraries(rsa_discovery_shm PRIVATE Celix::framework ${CURL_LIBRARIES} ${LIBXML2_LIBRARIES})
 
-	install_bundle(discovery_shm)
-		
+	install_bundle(rsa_discovery_shm)
 
 
+	#Setup target aliases to match external usage
+	add_library(Celix::rsa_discovery_shm ALIAS rsa_discovery_shm)
 endif (RSA_DISCOVERY_SHM)

http://git-wip-us.apache.org/repos/asf/celix/blob/486d4f0d/remote_services/examples/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/examples/CMakeLists.txt b/remote_services/examples/CMakeLists.txt
index 2b1f35f..78bfbac 100644
--- a/remote_services/examples/CMakeLists.txt
+++ b/remote_services/examples/CMakeLists.txt
@@ -48,13 +48,13 @@ if (RSA_EXAMPLES)
         add_deploy(remote-services-dfi 
             NAME "server"
             GROUP "remote-services/remote-services-dfi"
-            BUNDLES discovery_etcd topology_manager remote_service_admin_dfi calculator Celix::shell Celix::shell_tui Celix::log_service Celix::log_writer_stdout
+            BUNDLES Celix::rsa_discovery_etcd Celix::rsa_topology_manager Celix::rsa_dfi calculator Celix::shell Celix::shell_tui Celix::log_service Celix::log_writer_stdout
         )
 
         add_deploy("remote-services-dfi-client" 
             NAME "client"
             GROUP "remote-services/remote-services-dfi"
-            BUNDLES topology_manager remote_service_admin_dfi Celix::shell Celix::shell_tui Celix::log_service Celix::log_writer_stdout calculator_shell discovery_etcd
+            BUNDLES Celix::rsa_topology_manager Celix::rsa_dfi Celix::shell Celix::shell_tui Celix::log_service Celix::log_writer_stdout calculator_shell Celix::rsa_discovery_etcd
         )
     endif ()
 endif (RSA_EXAMPLES)

http://git-wip-us.apache.org/repos/asf/celix/blob/486d4f0d/remote_services/examples/calculator_service/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/examples/calculator_service/CMakeLists.txt b/remote_services/examples/calculator_service/CMakeLists.txt
index ff4d2d7..5d97d16 100644
--- a/remote_services/examples/calculator_service/CMakeLists.txt
+++ b/remote_services/examples/calculator_service/CMakeLists.txt
@@ -23,7 +23,7 @@ add_bundle(calculator
     VERSION 0.0.1
 )
 target_include_directories(calculator PRIVATE src)
-target_link_libraries(calculator PRIVATE Celix::remote_service_admin_api calculator_api)
+target_link_libraries(calculator PRIVATE Celix::rsa_api calculator_api)
 
 get_target_property(DESCR calculator_api INTERFACE_CALCULATOR_DESCRIPTOR)
 bundle_files(calculator ${DESCR} DESTINATION .)

http://git-wip-us.apache.org/repos/asf/celix/blob/486d4f0d/remote_services/remote_service_admin_api/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_api/CMakeLists.txt b/remote_services/remote_service_admin_api/CMakeLists.txt
index a7d0640..f665576 100644
--- a/remote_services/remote_service_admin_api/CMakeLists.txt
+++ b/remote_services/remote_service_admin_api/CMakeLists.txt
@@ -15,8 +15,8 @@
 # specific language governing permissions and limitations
 # under the License.
 
-add_library(remote_service_admin_api INTERFACE)
-target_include_directories(remote_service_admin_api INTERFACE include)
+add_library(rsa_api INTERFACE)
+target_include_directories(rsa_api INTERFACE include)
 
 install (FILES 
         include/remote_endpoint_impl.h
@@ -42,4 +42,4 @@ install (FILES
 )
 
 #Setup target aliases to match external usage
-add_library(Celix::remote_service_admin_api ALIAS remote_service_admin_api)
+add_library(Celix::rsa_api ALIAS rsa_api)

http://git-wip-us.apache.org/repos/asf/celix/blob/486d4f0d/remote_services/remote_service_admin_common/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_common/CMakeLists.txt b/remote_services/remote_service_admin_common/CMakeLists.txt
index a421cda..018d868 100644
--- a/remote_services/remote_service_admin_common/CMakeLists.txt
+++ b/remote_services/remote_service_admin_common/CMakeLists.txt
@@ -15,12 +15,13 @@
 # specific language governing permissions and limitations
 # under the License.
 
-add_library(remote_service_admin_common STATIC
+add_library(rsa_common STATIC
     src/endpoint_description.c
     src/export_registration_impl.c
     src/import_registration_impl.c
 )
-target_include_directories(remote_service_admin_common PRIVATE src)
-target_link_libraries(remote_service_admin_common PUBLIC Celix::framework Celix::remote_service_admin_api Celix::log_helper)
+target_include_directories(rsa_common PRIVATE src)
+target_link_libraries(rsa_common PUBLIC Celix::framework Celix::rsa_api Celix::log_helper)
 
-add_library(Celix::remote_service_admin_common ALIAS remote_service_admin_common)
\ No newline at end of file
+#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/486d4f0d/remote_services/remote_service_admin_dfi/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/CMakeLists.txt b/remote_services/remote_service_admin_dfi/CMakeLists.txt
index 206c6dc..ea79c31 100644
--- a/remote_services/remote_service_admin_dfi/CMakeLists.txt
+++ b/remote_services/remote_service_admin_dfi/CMakeLists.txt
@@ -23,7 +23,7 @@ if (RSA_REMOTE_SERVICE_ADMIN_DFI)
     find_package(CURL REQUIRED)
     find_package(Jansson REQUIRED)
 
-    add_bundle(remote_service_admin_dfi
+    add_bundle(rsa_dfi
             VERSION 0.9.0
             SYMBOLIC_NAME "apache_celix_remote_service_admin_dfi"
             NAME "Apache Celix Remote Service Admin Dynamic Function Interface (DFI)"
@@ -33,21 +33,21 @@ if (RSA_REMOTE_SERVICE_ADMIN_DFI)
             src/export_registration_dfi.c
             src/import_registration_dfi.c
             src/dfi_utils.c
-            $<TARGET_OBJECTS:civetweb>
+            $<TARGET_OBJECTS:Celix::civetweb>
     )
-    target_include_directories(remote_service_admin_dfi PRIVATE src $<TARGET_PROPERTY:civetweb,INCLUDE_DIRECTORIES>)
-    target_link_libraries(remote_service_admin_dfi PRIVATE
+    target_include_directories(rsa_dfi PRIVATE src $<TARGET_PROPERTY:Celix::civetweb,INCLUDE_DIRECTORIES>)
+    target_link_libraries(rsa_dfi PRIVATE
             Celix::dfi_static
             Celix::log_helper
-            Celix::remote_service_admin_common
+            Celix::rsa_common
             ${CURL_LIBRARIES} ${JANSSON_LIBRARIES})
 
-    install_bundle(remote_service_admin_dfi)
+    install_bundle(rsa_dfi)
 
     if (ENABLE_TESTING)
         add_subdirectory(test)
     endif()
 
     #Setup target aliases to match external usage
-    add_library(Celix::remote_service_admin_dfi ALIAS remote_service_admin_dfi)
+    add_library(Celix::rsa_dfi ALIAS rsa_dfi)
 endif()

http://git-wip-us.apache.org/repos/asf/celix/blob/486d4f0d/remote_services/remote_service_admin_dfi/test/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/test/CMakeLists.txt b/remote_services/remote_service_admin_dfi/test/CMakeLists.txt
index a78a6d0..153b3d1 100644
--- a/remote_services/remote_service_admin_dfi/test/CMakeLists.txt
+++ b/remote_services/remote_service_admin_dfi/test/CMakeLists.txt
@@ -36,15 +36,14 @@ add_executable(test_rsa_dfi
 target_include_directories(test_rsa_dfi PRIVATE src)
 target_link_libraries(test_rsa_dfi PRIVATE ${CURL_LIBRARIES} ${CPPUTEST_LIBRARY}
         Celix::framework
-        Celix::remote_service_admin_api
-        Celix::remote_service_admin_common
+        Celix::rsa_common
         calculator_api)
 
-get_property(rsa_bundle_file TARGET remote_service_admin_dfi PROPERTY BUNDLE_FILE)
+get_property(rsa_bundle_file TARGET rsa_dfi 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_configured_bundle_file TARGET discovery_configured PROPERTY BUNDLE_FILE)
-get_property(topology_manager_bundle_file TARGET topology_manager PROPERTY BUNDLE_FILE)
+get_property(discovery_configured_bundle_file TARGET rsa_discovery_configured PROPERTY BUNDLE_FILE)
+get_property(topology_manager_bundle_file TARGET Celix::rsa_topology_manager PROPERTY BUNDLE_FILE)
 get_property(tst_bundle_file TARGET rsa_dfi_tst_bundle PROPERTY BUNDLE_FILE)
 
 configure_file(config.properties.in config.properties)
@@ -52,7 +51,7 @@ configure_file(client.properties.in client.properties)
 configure_file(server.properties.in server.properties)
 
 add_dependencies(test_rsa_dfi
-        remote_service_admin_dfi_bundle #note depend on the target creating the bundle zip not the lib target
+        rsa_dfi_bundle #note depend on the target creating the bundle zip not the lib target
         calculator_bundle
 )
 

http://git-wip-us.apache.org/repos/asf/celix/blob/486d4f0d/remote_services/topology_manager/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/topology_manager/CMakeLists.txt b/remote_services/topology_manager/CMakeLists.txt
index defee5c..568054e 100644
--- a/remote_services/topology_manager/CMakeLists.txt
+++ b/remote_services/topology_manager/CMakeLists.txt
@@ -17,7 +17,7 @@
 celix_subproject(RSA_TOPOLOGY_MANAGER "Option to enable building the Remote Service Admin Service SHM bundle" ON DEPS REMOTE_SERVICE_ADMIN_DFI)
 if (RSA_TOPOLOGY_MANAGER)
 
-    add_bundle(topology_manager
+    add_bundle(rsa_topology_manager
         SOURCES
             src/topology_manager
             src/scope
@@ -26,11 +26,11 @@ if (RSA_TOPOLOGY_MANAGER)
         SYMBOLIC_NAME "apache_celix_rs_topology_manager"
         NAME "Apache Celix RS Topology Manager"
     )
-    target_include_directories(topology_manager PRIVATE src)
-    target_include_directories(topology_manager PUBLIC include)
-    target_link_libraries(topology_manager PRIVATE Celix::log_helper remote_service_admin_api)
+    target_include_directories(rsa_topology_manager PRIVATE src)
+    target_include_directories(rsa_topology_manager PUBLIC include)
+    target_link_libraries(rsa_topology_manager PRIVATE Celix::log_helper Celix::rsa_api)
 
-    install_bundle(topology_manager)
+    install_bundle(rsa_topology_manager)
 
     if (ENABLE_TESTING)
         find_package(CppUTest REQUIRED)
@@ -41,4 +41,7 @@ if (RSA_TOPOLOGY_MANAGER)
         include_directories(${CPPUTEST_EXT_INCLUDE_DIR})
         add_subdirectory(tms_tst)
    endif (ENABLE_TESTING)
+
+    #Setup target aliases to match external usage
+    add_library(Celix::rsa_topology_manager ALIAS rsa_topology_manager)
 endif (RSA_TOPOLOGY_MANAGER)

http://git-wip-us.apache.org/repos/asf/celix/blob/486d4f0d/remote_services/topology_manager/tms_tst/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/topology_manager/tms_tst/CMakeLists.txt b/remote_services/topology_manager/tms_tst/CMakeLists.txt
index 5e27139..6dedf32 100644
--- a/remote_services/topology_manager/tms_tst/CMakeLists.txt
+++ b/remote_services/topology_manager/tms_tst/CMakeLists.txt
@@ -42,18 +42,16 @@ target_link_libraries(test_tm_scoped PRIVATE
         Celix::framework
         ${CPPUTEST_LIBRARY}
         ${JANSSON_LIBRARY}
-        Celix::log_helper
         calculator_api
-        Celix::remote_service_admin_api
-        Celix::remote_service_admin_common
+        Celix::rsa_common
 )
 
-add_dependencies(test_tm_scoped remote_service_admin_dfi_bundle topology_manager_bundle)
+add_dependencies(test_tm_scoped rsa_dfi_bundle rsa_topology_manager_bundle)
 
 file(GENERATE 
     OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/config.properties"
     CONTENT "
-cosgi.auto.start.1=$<TARGET_PROPERTY:remote_service_admin_dfi,BUNDLE_FILE> $<TARGET_PROPERTY:calculator,BUNDLE_FILE> $<TARGET_PROPERTY:topology_manager,BUNDLE_FILE> $<TARGET_PROPERTY:topology_manager_disc_mock_bundle,BUNDLE_FILE>
+cosgi.auto.start.1=$<TARGET_PROPERTY:Celix::rsa_dfi,BUNDLE_FILE> $<TARGET_PROPERTY:calculator,BUNDLE_FILE> $<TARGET_PROPERTY:Celix::rsa_topology_manager,BUNDLE_FILE> $<TARGET_PROPERTY:topology_manager_disc_mock_bundle,BUNDLE_FILE>
 LOGHELPER_ENABLE_STDOUT_FALLBACK=true
 org.osgi.framework.storage.clean=onFirstInit
 ")
@@ -61,7 +59,7 @@ org.osgi.framework.storage.clean=onFirstInit
 file(GENERATE 
     OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/config_import.properties"
     CONTENT "
-cosgi.auto.start.1=$<TARGET_PROPERTY:remote_service_admin_dfi,BUNDLE_FILE> $<TARGET_PROPERTY:calculator,BUNDLE_FILE> $<TARGET_PROPERTY:topology_manager,BUNDLE_FILE> $<TARGET_PROPERTY:topology_manager_test_bundle,BUNDLE_FILE>
+cosgi.auto.start.1=$<TARGET_PROPERTY:Celix::rsa_dfi,BUNDLE_FILE> $<TARGET_PROPERTY:calculator,BUNDLE_FILE> $<TARGET_PROPERTY:Celix::rsa_topology_manager,BUNDLE_FILE> $<TARGET_PROPERTY:topology_manager_test_bundle,BUNDLE_FILE>
 LOGHELPER_ENABLE_STDOUT_FALLBACK=true
 org.osgi.framework.storage.clean=onFirstInit
 ")

http://git-wip-us.apache.org/repos/asf/celix/blob/486d4f0d/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt b/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt
index 551995b..eaf0a26 100644
--- a/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt
+++ b/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt
@@ -32,4 +32,4 @@ bundle_files(topology_manager_test_bundle
     DESTINATION .
 )
 
-target_link_libraries(topology_manager_test_bundle PRIVATE ${CPPUTEST_LIBRARY} Celix::remote_service_admin_api calculator_api)
+target_link_libraries(topology_manager_test_bundle PRIVATE ${CPPUTEST_LIBRARY} Celix::rsa_api calculator_api)

http://git-wip-us.apache.org/repos/asf/celix/blob/486d4f0d/remote_services/topology_manager/tms_tst/disc_mock/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/topology_manager/tms_tst/disc_mock/CMakeLists.txt b/remote_services/topology_manager/tms_tst/disc_mock/CMakeLists.txt
index 653b69c..3e93174 100644
--- a/remote_services/topology_manager/tms_tst/disc_mock/CMakeLists.txt
+++ b/remote_services/topology_manager/tms_tst/disc_mock/CMakeLists.txt
@@ -23,6 +23,6 @@ add_bundle(topology_manager_disc_mock_bundle
 )
 target_include_directories(topology_manager_disc_mock_bundle PRIVATE
         ${CPPUTEST_INCLUDE_DIR}
-        $<TARGET_PROPERTY:discovery_common,INCLUDE_DIRECTORIES>
+        $<TARGET_PROPERTY:Celix::rsa_discovery_common,INCLUDE_DIRECTORIES>
 )
 target_link_libraries(topology_manager_disc_mock_bundle PRIVATE ${CPPUTEST_LIBRARY} Celix::framework)


[3/8] celix git commit: CELIX-417: Refactors CMake usage for the RSA bundles

Posted by pn...@apache.org.
http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_common/src/discovery.c
----------------------------------------------------------------------
diff --git a/remote_services/discovery_common/src/discovery.c b/remote_services/discovery_common/src/discovery.c
index d124c15..d016c09 100644
--- a/remote_services/discovery_common/src/discovery.c
+++ b/remote_services/discovery_common/src/discovery.c
@@ -33,7 +33,6 @@
 #include "log_helper.h"
 #include "discovery.h"
 #include "endpoint_discovery_server.h"
-#include "discovery_impl.h" //TODO rename impl
 
 
 celix_status_t discovery_endpointAdded(void *handle, endpoint_description_pt endpoint, char *matchedFilter) {

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_common/src/endpoint_discovery_poller.c
----------------------------------------------------------------------
diff --git a/remote_services/discovery_common/src/endpoint_discovery_poller.c b/remote_services/discovery_common/src/endpoint_discovery_poller.c
index 73fb7ba..e3f9cd4 100644
--- a/remote_services/discovery_common/src/endpoint_discovery_poller.c
+++ b/remote_services/discovery_common/src/endpoint_discovery_poller.c
@@ -35,9 +35,8 @@
 #include "log_helper.h"
 #include "utils.h"
 
-#include "discovery_impl.h"
-
 #include "endpoint_descriptor_reader.h"
+#include "discovery.h"
 
 
 #define DISCOVERY_POLL_INTERVAL "DISCOVERY_CFG_POLL_INTERVAL"
@@ -52,7 +51,7 @@ static celix_status_t endpointDiscoveryPoller_endpointDescriptionEquals(const vo
 /**
  * Allocates memory and initializes a new endpoint_discovery_poller instance.
  */
-celix_status_t endpointDiscoveryPoller_create(discovery_pt discovery, bundle_context_pt context, endpoint_discovery_poller_pt *poller) {
+celix_status_t endpointDiscoveryPoller_create(discovery_pt discovery, bundle_context_pt context, const char* defaultPollEndpoints, endpoint_discovery_poller_pt *poller) {
 	celix_status_t status;
 
 	*poller = malloc(sizeof(struct endpoint_discovery_poller));
@@ -76,7 +75,7 @@ celix_status_t endpointDiscoveryPoller_create(discovery_pt discovery, bundle_con
 	const char* endpointsProp = NULL;
 	status = bundleContext_getProperty(context, DISCOVERY_POLL_ENDPOINTS, &endpointsProp);
 	if (!endpointsProp) {
-		endpointsProp = DEFAULT_POLL_ENDPOINTS;
+		endpointsProp = defaultPollEndpoints;
 	}
 	// we're going to mutate the string with strtok, so create a copy...
 	char* endpoints = strdup(endpointsProp);

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_common/src/endpoint_discovery_server.c
----------------------------------------------------------------------
diff --git a/remote_services/discovery_common/src/endpoint_discovery_server.c b/remote_services/discovery_common/src/endpoint_discovery_server.c
index f5f82af..7620bbf 100644
--- a/remote_services/discovery_common/src/endpoint_discovery_server.c
+++ b/remote_services/discovery_common/src/endpoint_discovery_server.c
@@ -35,8 +35,6 @@
 #include "utils.h"
 #include "log_helper.h"
 #include "discovery.h"
-#include "discovery_impl.h"
-
 #include "endpoint_descriptor_writer.h"
 
 // defines how often the webserver is restarted (with an increased port number)
@@ -72,7 +70,13 @@ static char* format_path(const char* path);
 static celix_status_t endpointDiscoveryServer_getIpAdress(char* interface, char** ip);
 #endif
 
-celix_status_t endpointDiscoveryServer_create(discovery_pt discovery, bundle_context_pt context, endpoint_discovery_server_pt *server) {
+celix_status_t endpointDiscoveryServer_create(
+		discovery_pt discovery,
+		bundle_context_pt context,
+		const char* defaultServerPath,
+		const char* defaultServerPort,
+		const char* defaultServerIp,
+		endpoint_discovery_server_pt *server) {
 	celix_status_t status;
 
 	const char *port = NULL;
@@ -122,8 +126,8 @@ celix_status_t endpointDiscoveryServer_create(discovery_pt discovery, bundle_con
 		(*server)->ip = strdup(ip);
 	}
 	else {
-		logHelper_log(*(*server)->loghelper, OSGI_LOGSERVICE_WARNING, "No IP address for service annunciation set. Using %s", DEFAULT_SERVER_IP);
-		(*server)->ip = strdup((char*) DEFAULT_SERVER_IP);
+		logHelper_log(*(*server)->loghelper, OSGI_LOGSERVICE_WARNING, "No IP address for service annunciation set. Using %s", defaultServerIp);
+		(*server)->ip = strdup((char*) defaultServerIp);
 	}
 
 	if (detectedIp != NULL) {
@@ -132,12 +136,12 @@ celix_status_t endpointDiscoveryServer_create(discovery_pt discovery, bundle_con
 
 	bundleContext_getProperty(context, DISCOVERY_SERVER_PORT, &port);
 	if (port == NULL) {
-		port = DEFAULT_SERVER_PORT;
+		port = defaultServerPort;
 	}
 
 	bundleContext_getProperty(context, DISCOVERY_SERVER_PATH, &path);
 	if (path == NULL) {
-		path = DEFAULT_SERVER_PATH;
+		path = defaultServerPath;
 	}
 
 	bundleContext_getProperty(context, DISCOVERY_SERVER_MAX_EP, &retries);
@@ -177,7 +181,7 @@ celix_status_t endpointDiscoveryServer_create(discovery_pt discovery, bundle_con
 			long currentPort = strtol(port, &endptr, 10);
 
 			if (*endptr || errno != 0) {
-				currentPort = strtol(DEFAULT_SERVER_PORT, NULL, 10);
+				currentPort = strtol(defaultServerPort, NULL, 10);
 			}
 
 			port_counter++;

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_common/src/md5.inl
----------------------------------------------------------------------
diff --git a/remote_services/discovery_common/src/md5.inl b/remote_services/discovery_common/src/md5.inl
deleted file mode 100644
index 4da933d..0000000
--- a/remote_services/discovery_common/src/md5.inl
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * This an amalgamation of md5.c and md5.h into a single file
- * with all static declaration to reduce linker conflicts
- * in Civetweb.
- *
- * The MD5_STATIC declaration was added to facilitate static
- * inclusion.
- * No Face Press, LLC
- */
-
-/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
-/*
-  Independent implementation of MD5 (RFC 1321).
-
-  This code implements the MD5 Algorithm defined in RFC 1321, whose
-  text is available at
-	http://www.ietf.org/rfc/rfc1321.txt
-  The code is derived from the text of the RFC, including the test suite
-  (section A.5) but excluding the rest of Appendix A.  It does not include
-  any code or documentation that is identified in the RFC as being
-  copyrighted.
-
-  The original and principal author of md5.h is L. Peter Deutsch
-  <gh...@aladdin.com>.  Other authors are noted in the change history
-  that follows (in reverse chronological order):
-
-  2002-04-13 lpd Removed support for non-ANSI compilers; removed
-	references to Ghostscript; clarified derivation from RFC 1321;
-	now handles byte order either statically or dynamically.
-  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
-  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
-	added conditionalization for C++ compilation from Martin
-	Purschke <pu...@bnl.gov>.
-  1999-05-03 lpd Original version.
- */
-
-#ifndef md5_INCLUDED
-#  define md5_INCLUDED
-
-/*
- * This package supports both compile-time and run-time determination of CPU
- * byte order.  If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
- * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
- * defined as non-zero, the code will be compiled to run only on big-endian
- * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
- * run on either big- or little-endian CPUs, but will run slightly less
- * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
- */
-
-typedef unsigned char md5_byte_t; /* 8-bit byte */
-typedef unsigned int md5_word_t; /* 32-bit word */
-
-/* Define the state of the MD5 Algorithm. */
-typedef struct md5_state_s {
-    md5_word_t count[2];	/* message length in bits, lsw first */
-    md5_word_t abcd[4];		/* digest buffer */
-    md5_byte_t buf[64];		/* accumulate block */
-} md5_state_t;
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/* Initialize the algorithm. */
-MD5_STATIC void md5_init(md5_state_t *pms);
-
-/* Append a string to the message. */
-MD5_STATIC void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
-
-/* Finish the message and return the digest. */
-MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
-
-#ifdef __cplusplus
-}  /* end extern "C" */
-#endif
-
-#endif /* md5_INCLUDED */
-
-/*
-  Copyright (C) 1999, 2000, 2002 Aladdin Enterprises.  All rights reserved.
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-  L. Peter Deutsch
-  ghost@aladdin.com
-
- */
-/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
-/*
-  Independent implementation of MD5 (RFC 1321).
-
-  This code implements the MD5 Algorithm defined in RFC 1321, whose
-  text is available at
-	http://www.ietf.org/rfc/rfc1321.txt
-  The code is derived from the text of the RFC, including the test suite
-  (section A.5) but excluding the rest of Appendix A.  It does not include
-  any code or documentation that is identified in the RFC as being
-  copyrighted.
-
-  The original and principal author of md5.c is L. Peter Deutsch
-  <gh...@aladdin.com>.  Other authors are noted in the change history
-  that follows (in reverse chronological order):
-
-  2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
-	either statically or dynamically; added missing #include <string.h>
-	in library.
-  2002-03-11 lpd Corrected argument list for main(), and added int return
-	type, in test program and T value program.
-  2002-02-21 lpd Added missing #include <stdio.h> in test program.
-  2000-07-03 lpd Patched to eliminate warnings about "constant is
-	unsigned in ANSI C, signed in traditional"; made test program
-	self-checking.
-  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
-  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
-  1999-05-03 lpd Original version.
- */
-
-#ifndef MD5_STATIC
-#include <string.h>
-#endif
-
-#undef BYTE_ORDER	/* 1 = big-endian, -1 = little-endian, 0 = unknown */
-#ifdef ARCH_IS_BIG_ENDIAN
-#  define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
-#else
-#  define BYTE_ORDER 0
-#endif
-
-#define T_MASK ((md5_word_t)~0)
-#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
-#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
-#define T3    0x242070db
-#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
-#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
-#define T6    0x4787c62a
-#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
-#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
-#define T9    0x698098d8
-#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
-#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
-#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
-#define T13    0x6b901122
-#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
-#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
-#define T16    0x49b40821
-#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
-#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
-#define T19    0x265e5a51
-#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
-#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
-#define T22    0x02441453
-#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
-#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
-#define T25    0x21e1cde6
-#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
-#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
-#define T28    0x455a14ed
-#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
-#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
-#define T31    0x676f02d9
-#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
-#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
-#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
-#define T35    0x6d9d6122
-#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
-#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
-#define T38    0x4bdecfa9
-#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
-#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
-#define T41    0x289b7ec6
-#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
-#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
-#define T44    0x04881d05
-#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
-#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
-#define T47    0x1fa27cf8
-#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
-#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
-#define T50    0x432aff97
-#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
-#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
-#define T53    0x655b59c3
-#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
-#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
-#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
-#define T57    0x6fa87e4f
-#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
-#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
-#define T60    0x4e0811a1
-#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
-#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
-#define T63    0x2ad7d2bb
-#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
-
-
-static void
-md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
-{
-    md5_word_t
-    a = pms->abcd[0], b = pms->abcd[1],
-    c = pms->abcd[2], d = pms->abcd[3];
-    md5_word_t t;
-#if BYTE_ORDER > 0
-    /* Define storage only for big-endian CPUs. */
-    md5_word_t X[16];
-#else
-    /* Define storage for little-endian or both types of CPUs. */
-    md5_word_t xbuf[16];
-    const md5_word_t *X;
-#endif
-
-    {
-#if BYTE_ORDER == 0
-        /*
-         * Determine dynamically whether this is a big-endian or
-         * little-endian machine, since we can use a more efficient
-         * algorithm on the latter.
-         */
-        static const int w = 1;
-
-        if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
-#endif
-#if BYTE_ORDER <= 0		/* little-endian */
-        {
-            /*
-             * On little-endian machines, we can process properly aligned
-             * data without copying it.
-             */
-            if (!((data - (const md5_byte_t *)0) & 3)) {
-                /* data are properly aligned */
-                X = (const md5_word_t *)data;
-            } else {
-                /* not aligned */
-                memcpy(xbuf, data, 64);
-                X = xbuf;
-            }
-        }
-#endif
-#if BYTE_ORDER == 0
-        else			/* dynamic big-endian */
-#endif
-#if BYTE_ORDER >= 0		/* big-endian */
-        {
-            /*
-             * On big-endian machines, we must arrange the bytes in the
-             * right order.
-             */
-            const md5_byte_t *xp = data;
-            int i;
-
-#  if BYTE_ORDER == 0
-            X = xbuf;		/* (dynamic only) */
-#  else
-#    define xbuf X		/* (static only) */
-#  endif
-            for (i = 0; i < 16; ++i, xp += 4)
-                xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
-        }
-#endif
-    }
-
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
-
-    /* Round 1. */
-    /* Let [abcd k s i] denote the operation
-       a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + F(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-    /* Do the following 16 operations. */
-    SET(a, b, c, d,  0,  7,  T1);
-    SET(d, a, b, c,  1, 12,  T2);
-    SET(c, d, a, b,  2, 17,  T3);
-    SET(b, c, d, a,  3, 22,  T4);
-    SET(a, b, c, d,  4,  7,  T5);
-    SET(d, a, b, c,  5, 12,  T6);
-    SET(c, d, a, b,  6, 17,  T7);
-    SET(b, c, d, a,  7, 22,  T8);
-    SET(a, b, c, d,  8,  7,  T9);
-    SET(d, a, b, c,  9, 12, T10);
-    SET(c, d, a, b, 10, 17, T11);
-    SET(b, c, d, a, 11, 22, T12);
-    SET(a, b, c, d, 12,  7, T13);
-    SET(d, a, b, c, 13, 12, T14);
-    SET(c, d, a, b, 14, 17, T15);
-    SET(b, c, d, a, 15, 22, T16);
-#undef SET
-
-    /* Round 2. */
-    /* Let [abcd k s i] denote the operation
-         a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
-#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + G(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-    /* Do the following 16 operations. */
-    SET(a, b, c, d,  1,  5, T17);
-    SET(d, a, b, c,  6,  9, T18);
-    SET(c, d, a, b, 11, 14, T19);
-    SET(b, c, d, a,  0, 20, T20);
-    SET(a, b, c, d,  5,  5, T21);
-    SET(d, a, b, c, 10,  9, T22);
-    SET(c, d, a, b, 15, 14, T23);
-    SET(b, c, d, a,  4, 20, T24);
-    SET(a, b, c, d,  9,  5, T25);
-    SET(d, a, b, c, 14,  9, T26);
-    SET(c, d, a, b,  3, 14, T27);
-    SET(b, c, d, a,  8, 20, T28);
-    SET(a, b, c, d, 13,  5, T29);
-    SET(d, a, b, c,  2,  9, T30);
-    SET(c, d, a, b,  7, 14, T31);
-    SET(b, c, d, a, 12, 20, T32);
-#undef SET
-
-    /* Round 3. */
-    /* Let [abcd k s t] denote the operation
-         a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + H(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-    /* Do the following 16 operations. */
-    SET(a, b, c, d,  5,  4, T33);
-    SET(d, a, b, c,  8, 11, T34);
-    SET(c, d, a, b, 11, 16, T35);
-    SET(b, c, d, a, 14, 23, T36);
-    SET(a, b, c, d,  1,  4, T37);
-    SET(d, a, b, c,  4, 11, T38);
-    SET(c, d, a, b,  7, 16, T39);
-    SET(b, c, d, a, 10, 23, T40);
-    SET(a, b, c, d, 13,  4, T41);
-    SET(d, a, b, c,  0, 11, T42);
-    SET(c, d, a, b,  3, 16, T43);
-    SET(b, c, d, a,  6, 23, T44);
-    SET(a, b, c, d,  9,  4, T45);
-    SET(d, a, b, c, 12, 11, T46);
-    SET(c, d, a, b, 15, 16, T47);
-    SET(b, c, d, a,  2, 23, T48);
-#undef SET
-
-    /* Round 4. */
-    /* Let [abcd k s t] denote the operation
-         a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + I(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-    /* Do the following 16 operations. */
-    SET(a, b, c, d,  0,  6, T49);
-    SET(d, a, b, c,  7, 10, T50);
-    SET(c, d, a, b, 14, 15, T51);
-    SET(b, c, d, a,  5, 21, T52);
-    SET(a, b, c, d, 12,  6, T53);
-    SET(d, a, b, c,  3, 10, T54);
-    SET(c, d, a, b, 10, 15, T55);
-    SET(b, c, d, a,  1, 21, T56);
-    SET(a, b, c, d,  8,  6, T57);
-    SET(d, a, b, c, 15, 10, T58);
-    SET(c, d, a, b,  6, 15, T59);
-    SET(b, c, d, a, 13, 21, T60);
-    SET(a, b, c, d,  4,  6, T61);
-    SET(d, a, b, c, 11, 10, T62);
-    SET(c, d, a, b,  2, 15, T63);
-    SET(b, c, d, a,  9, 21, T64);
-#undef SET
-
-    /* Then perform the following additions. (That is increment each
-       of the four registers by the value it had before this block
-       was started.) */
-    pms->abcd[0] += a;
-    pms->abcd[1] += b;
-    pms->abcd[2] += c;
-    pms->abcd[3] += d;
-}
-
-MD5_STATIC void
-md5_init(md5_state_t *pms)
-{
-    pms->count[0] = pms->count[1] = 0;
-    pms->abcd[0] = 0x67452301;
-    pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
-    pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
-    pms->abcd[3] = 0x10325476;
-}
-
-MD5_STATIC void
-md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
-{
-    const md5_byte_t *p = data;
-    int left = nbytes;
-    int offset = (pms->count[0] >> 3) & 63;
-    md5_word_t nbits = (md5_word_t)(nbytes << 3);
-
-    if (nbytes <= 0)
-        return;
-
-    /* Update the message length. */
-    pms->count[1] += nbytes >> 29;
-    pms->count[0] += nbits;
-    if (pms->count[0] < nbits)
-        pms->count[1]++;
-
-    /* Process an initial partial block. */
-    if (offset) {
-        int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
-
-        memcpy(pms->buf + offset, p, copy);
-        if (offset + copy < 64)
-            return;
-        p += copy;
-        left -= copy;
-        md5_process(pms, pms->buf);
-    }
-
-    /* Process full blocks. */
-    for (; left >= 64; p += 64, left -= 64)
-        md5_process(pms, p);
-
-    /* Process a final partial block. */
-    if (left)
-        memcpy(pms->buf, p, left);
-}
-
-MD5_STATIC void
-md5_finish(md5_state_t *pms, md5_byte_t digest[16])
-{
-    static const md5_byte_t pad[64] = {
-        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-    };
-    md5_byte_t data[8];
-    int i;
-
-    /* Save the length before padding. */
-    for (i = 0; i < 8; ++i)
-        data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
-    /* Pad to 56 bytes mod 64. */
-    md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
-    /* Append the length. */
-    md5_append(pms, data, 8);
-    for (i = 0; i < 16; ++i)
-        digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
-}

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_configured/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/discovery_configured/CMakeLists.txt b/remote_services/discovery_configured/CMakeLists.txt
index e0f3e9b..f7d104b 100644
--- a/remote_services/discovery_configured/CMakeLists.txt
+++ b/remote_services/discovery_configured/CMakeLists.txt
@@ -25,9 +25,15 @@ if (RSA_DISCOVERY_CONFIGURED)
         NAME "Apache Celix RSA Configured Discovery"
         SOURCES
 	        src/discovery_impl.c
+            $<TARGET_OBJECTS:discovery_common>
+            $<TARGET_OBJECTS:civetweb>
     )
-    target_include_directories(discovery_configured PRIVATE src)
-    target_link_libraries(discovery_configured PRIVATE ${CURL_LIBRARIES} ${LIBXML2_LIBRARIES} Celix::log_helper discovery_common)
+    target_include_directories(discovery_configured PRIVATE
+            src
+            $<TARGET_PROPERTY:discovery_common,INCLUDE_DIRECTORIES>
+            $<TARGET_PROPERTY:civetweb,INCLUDE_DIRECTORIES>
+    )
+    target_link_libraries(discovery_configured PRIVATE ${CURL_LIBRARIES} ${LIBXML2_LIBRARIES} Celix::log_helper)
 
     install_bundle(discovery_configured)
 

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_configured/src/discovery_impl.c
----------------------------------------------------------------------
diff --git a/remote_services/discovery_configured/src/discovery_impl.c b/remote_services/discovery_configured/src/discovery_impl.c
index 35a0c71..89c777e 100644
--- a/remote_services/discovery_configured/src/discovery_impl.c
+++ b/remote_services/discovery_configured/src/discovery_impl.c
@@ -66,12 +66,12 @@ celix_status_t discovery_start(discovery_pt discovery) {
 
 	logHelper_start(discovery->loghelper);
 
-    status = endpointDiscoveryPoller_create(discovery, discovery->context, &discovery->poller);
+    status = endpointDiscoveryPoller_create(discovery, discovery->context, DEFAULT_POLL_ENDPOINTS, &discovery->poller);
     if (status != CELIX_SUCCESS) {
     	return CELIX_BUNDLE_EXCEPTION;
     }
 
-    status = endpointDiscoveryServer_create(discovery, discovery->context, &discovery->server);
+    status = endpointDiscoveryServer_create(discovery, discovery->context, DEFAULT_SERVER_PATH, DEFAULT_SERVER_PORT, DEFAULT_SERVER_IP, &discovery->server);
     if (status != CELIX_SUCCESS) {
     	return CELIX_BUNDLE_EXCEPTION;
     }

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_configured/src/discovery_impl.h
----------------------------------------------------------------------
diff --git a/remote_services/discovery_configured/src/discovery_impl.h b/remote_services/discovery_configured/src/discovery_impl.h
index 0414eac..a9d56c1 100644
--- a/remote_services/discovery_configured/src/discovery_impl.h
+++ b/remote_services/discovery_configured/src/discovery_impl.h
@@ -44,19 +44,19 @@
 #define DEFAULT_POLL_ENDPOINTS "http://localhost:9999/org.apache.celix.discovery.configured"
 
 
-struct discovery {
-	bundle_context_pt context;
-
-	celix_thread_mutex_t listenerReferencesMutex;
-	celix_thread_mutex_t discoveredServicesMutex;
-
-	hash_map_pt listenerReferences; //key=serviceReference, value=nop
-	hash_map_pt discoveredServices; //key=endpointId (string), value=endpoint_description_pt
-
-	endpoint_discovery_poller_pt poller;
-	endpoint_discovery_server_pt server;
-
-	log_helper_pt loghelper;
-};
+//struct discovery_impl {
+//	bundle_context_pt context;
+//
+//	celix_thread_mutex_t listenerReferencesMutex;
+//	celix_thread_mutex_t discoveredServicesMutex;
+//
+//	hash_map_pt listenerReferences; //key=serviceReference, value=nop
+//	hash_map_pt discoveredServices; //key=endpointId (string), value=endpoint_description_pt
+//
+//	endpoint_discovery_poller_pt poller;
+//	endpoint_discovery_server_pt server;
+//
+//	log_helper_pt loghelper;
+//};
 
 #endif /* DISCOVERY_IMPL_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_etcd/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/discovery_etcd/CMakeLists.txt b/remote_services/discovery_etcd/CMakeLists.txt
index 4168281..9c8edc8 100644
--- a/remote_services/discovery_etcd/CMakeLists.txt
+++ b/remote_services/discovery_etcd/CMakeLists.txt
@@ -28,11 +28,19 @@ if (RSA_DISCOVERY_ETCD)
         SOURCES
 			src/discovery_impl.c
 	    	src/etcd_watcher.c
+			$<TARGET_OBJECTS:discovery_common>
+			$<TARGET_OBJECTS:civetweb>
 	)
-	target_link_libraries(discovery_etcd PRIVATE Celix::log_helper)
-	target_include_directories(discovery_etcd PRIVATE src )
-	target_include_directories(discovery_etcd PRIVATE ${CURL_INCLUDE_DIR} ${JANSSON_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR})
-	target_link_libraries(discovery_etcd PRIVATE ${CURL_LIBRARIES} ${LIBXML2_LIBRARIES} ${JANSSON_LIBRARIES} discovery_common)
+	target_link_libraries(discovery_etcd PRIVATE Celix::log_helper Celix::etcdlib_static)
+	target_include_directories(discovery_etcd PRIVATE src)
+	target_include_directories(discovery_etcd PRIVATE
+			$<TARGET_PROPERTY:discovery_common,INCLUDE_DIRECTORIES>
+			$<TARGET_PROPERTY:civetweb,INCLUDE_DIRECTORIES>
+			${CURL_INCLUDE_DIR}
+			${JANSSON_INCLUDE_DIR}
+			${LIBXML2_INCLUDE_DIR}
+	)
+	target_link_libraries(discovery_etcd PRIVATE ${CURL_LIBRARIES} ${LIBXML2_LIBRARIES} ${JANSSON_LIBRARIES})
 
 	install_bundle(discovery_etcd)
 endif (RSA_DISCOVERY_ETCD)

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_etcd/src/discovery_impl.c
----------------------------------------------------------------------
diff --git a/remote_services/discovery_etcd/src/discovery_impl.c b/remote_services/discovery_etcd/src/discovery_impl.c
index 8087d95..500399e 100644
--- a/remote_services/discovery_etcd/src/discovery_impl.c
+++ b/remote_services/discovery_etcd/src/discovery_impl.c
@@ -50,25 +50,35 @@
 
 
 
-celix_status_t discovery_create(bundle_context_pt context, discovery_pt *discovery) {
+celix_status_t discovery_create(bundle_context_pt context, discovery_t** out) {
 	celix_status_t status = CELIX_SUCCESS;
 
-	*discovery = malloc(sizeof(struct discovery));
-	if (!*discovery) {
-		return CELIX_ENOMEM;
-	}
+	discovery_t* discovery = calloc(1, sizeof(*discovery));
+	discovery_impl_t* pImpl = calloc(1, sizeof(*pImpl));
+
+	if (discovery != NULL && pImpl != NULL) {
+		discovery->pImpl = pImpl;
+		discovery->context = context;
+		discovery->poller = NULL;
+		discovery->server = NULL;
 
-	(*discovery)->context = context;
-	(*discovery)->poller = NULL;
-	(*discovery)->server = NULL;
+		discovery->listenerReferences = hashMap_create(serviceReference_hashCode, NULL, serviceReference_equals2,
+														  NULL);
+		discovery->discoveredServices = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
 
-	(*discovery)->listenerReferences = hashMap_create(serviceReference_hashCode, NULL, serviceReference_equals2, NULL);
-	(*discovery)->discoveredServices = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
+		status = celixThreadMutex_create(&discovery->listenerReferencesMutex, NULL);
+		status = celixThreadMutex_create(&discovery->discoveredServicesMutex, NULL);
 
-	status = celixThreadMutex_create(&(*discovery)->listenerReferencesMutex, NULL);
-	status = celixThreadMutex_create(&(*discovery)->discoveredServicesMutex, NULL);
+		logHelper_create(context, &discovery->loghelper);
+	} else {
+		status = CELIX_ENOMEM;
+		free(discovery);
+		free(pImpl);
+	}
 
-	logHelper_create(context, &(*discovery)->loghelper);
+	if (status == CELIX_SUCCESS) {
+		*out = discovery;
+	}
 
 	return status;
 }
@@ -124,17 +134,17 @@ celix_status_t discovery_start(discovery_pt discovery) {
 		path = DEFAULT_SERVER_PATH;
 	}
 
-    status = endpointDiscoveryPoller_create(discovery, discovery->context, &discovery->poller);
+    status = endpointDiscoveryPoller_create(discovery, discovery->context, DEFAULT_POLL_ENDPOINTS, &discovery->poller);
     if (status != CELIX_SUCCESS) {
     	return CELIX_BUNDLE_EXCEPTION;
     }
 
-    status = endpointDiscoveryServer_create(discovery, discovery->context, &discovery->server);
+    status = endpointDiscoveryServer_create(discovery, discovery->context, DEFAULT_SERVER_PATH, DEFAULT_SERVER_PORT, DEFAULT_SERVER_IP, &discovery->server);
     if (status != CELIX_SUCCESS) {
 		return CELIX_BUNDLE_EXCEPTION;
     }
 
-    status = etcdWatcher_create(discovery, discovery->context, &discovery->watcher);
+    status = etcdWatcher_create(discovery, discovery->context, &discovery->pImpl->watcher);
     if (status != CELIX_SUCCESS) {
     	return CELIX_BUNDLE_EXCEPTION;
     }
@@ -144,7 +154,7 @@ celix_status_t discovery_start(discovery_pt discovery) {
 celix_status_t discovery_stop(discovery_pt discovery) {
 	celix_status_t status;
 
-	status = etcdWatcher_destroy(discovery->watcher);
+	status = etcdWatcher_destroy(discovery->pImpl->watcher);
 	if (status != CELIX_SUCCESS) {
 		return CELIX_BUNDLE_EXCEPTION;
 	}

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_etcd/src/discovery_impl.h
----------------------------------------------------------------------
diff --git a/remote_services/discovery_etcd/src/discovery_impl.h b/remote_services/discovery_etcd/src/discovery_impl.h
index a19b145..f28017b 100644
--- a/remote_services/discovery_etcd/src/discovery_impl.h
+++ b/remote_services/discovery_etcd/src/discovery_impl.h
@@ -47,20 +47,8 @@
 
 #define FREE_MEM(ptr) if(ptr) {free(ptr); ptr = NULL;}
 
-struct discovery {
-	bundle_context_pt context;
-
-	celix_thread_mutex_t listenerReferencesMutex;
-	celix_thread_mutex_t discoveredServicesMutex;
-
-	hash_map_pt listenerReferences; //key=serviceReference, value=nop
-	hash_map_pt discoveredServices; //key=endpointId (string), value=endpoint_description_pt
-
-	etcd_watcher_pt watcher;
-	endpoint_discovery_poller_pt poller;
-	endpoint_discovery_server_pt server;
-
-	log_helper_pt loghelper;
+struct discovery_impl {
+    etcd_watcher_t* watcher;
 };
 
 #endif /* DISCOVERY_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_etcd/src/etcd_watcher.h
----------------------------------------------------------------------
diff --git a/remote_services/discovery_etcd/src/etcd_watcher.h b/remote_services/discovery_etcd/src/etcd_watcher.h
index b4dbf40..56bae92 100644
--- a/remote_services/discovery_etcd/src/etcd_watcher.h
+++ b/remote_services/discovery_etcd/src/etcd_watcher.h
@@ -31,6 +31,7 @@
 #include "discovery.h"
 #include "endpoint_discovery_poller.h"
 
+typedef struct etcd_watcher etcd_watcher_t;
 typedef struct etcd_watcher *etcd_watcher_pt;
 
 celix_status_t etcdWatcher_create(discovery_pt discovery,  bundle_context_pt context, etcd_watcher_pt *watcher);

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_shm/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/discovery_shm/CMakeLists.txt b/remote_services/discovery_shm/CMakeLists.txt
index dff403d..61e54f7 100644
--- a/remote_services/discovery_shm/CMakeLists.txt
+++ b/remote_services/discovery_shm/CMakeLists.txt
@@ -28,13 +28,17 @@ find_package(CURL REQUIRED)
 			src/discovery_shm.c
 			src/discovery_shmWatcher.c
 			src/discovery_impl.c
+			$<TARGET_OBJECTS:discovery_common>
+			$<TARGET_OBJECTS:civetweb>
 	)
 	target_include_directories(discovery_shm PRIVATE
 			src
 			${LIBXML2_INCLUDE_DIR}
 			${CURL_INCLUDE_DIR}
+			$<TARGET_PROPERTY:discovery_common,INCLUDE_DIRECTORIES>
+			$<TARGET_PROPERTY:civetweb,INCLUDE_DIRECTORIES>
 	)
-	target_link_libraries(discovery_shm PRIVATE Celix::framework ${CURL_LIBRARIES} ${LIBXML2_LIBRARIES} discovery_common)
+	target_link_libraries(discovery_shm PRIVATE Celix::framework ${CURL_LIBRARIES} ${LIBXML2_LIBRARIES})
 
 	install_bundle(discovery_shm)
 		

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_shm/src/discovery_impl.c
----------------------------------------------------------------------
diff --git a/remote_services/discovery_shm/src/discovery_impl.c b/remote_services/discovery_shm/src/discovery_impl.c
index 2604595..fadff8c 100644
--- a/remote_services/discovery_shm/src/discovery_impl.c
+++ b/remote_services/discovery_shm/src/discovery_impl.c
@@ -48,28 +48,34 @@
 #include "endpoint_discovery_poller.h"
 #include "endpoint_discovery_server.h"
 
-
-
-celix_status_t discovery_create(bundle_context_pt context, discovery_pt *discovery) {
+celix_status_t discovery_create(bundle_context_pt context, discovery_t** out) {
 	celix_status_t status = CELIX_SUCCESS;
 
-	*discovery = calloc(1, sizeof(struct discovery));
-	if (!*discovery) {
-		status = CELIX_ENOMEM;
-	} else {
-        (*discovery)->context = context;
-        (*discovery)->poller = NULL;
-        (*discovery)->server = NULL;
+	discovery_t* discovery = calloc(1, sizeof(*discovery));
+    discovery_impl_t* pImpl = calloc(1, sizeof(*pImpl));
+	if (discovery != NULL && pImpl != NULL) {
+        discovery->pImpl = pImpl;
+        discovery->context = context;
+        discovery->poller = NULL;
+        discovery->server = NULL;
 
-        (*discovery)->listenerReferences = hashMap_create(serviceReference_hashCode, NULL, serviceReference_equals2, NULL);
-        (*discovery)->discoveredServices = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
+        discovery->listenerReferences = hashMap_create(serviceReference_hashCode, NULL, serviceReference_equals2, NULL);
+        discovery->discoveredServices = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
 
-        celixThreadMutex_create(&(*discovery)->listenerReferencesMutex, NULL);
-        celixThreadMutex_create(&(*discovery)->discoveredServicesMutex, NULL);
+        celixThreadMutex_create(&discovery->listenerReferencesMutex, NULL);
+        celixThreadMutex_create(&discovery->discoveredServicesMutex, NULL);
 
-        if (logHelper_create(context, &(*discovery)->loghelper) == CELIX_SUCCESS) {
-            logHelper_start((*discovery)->loghelper);
+        if (logHelper_create(context, &discovery->loghelper) == CELIX_SUCCESS) {
+            logHelper_start(discovery->loghelper);
         }
+    } else {
+        status = CELIX_ENOMEM;
+        free(discovery);
+        free(pImpl);
+    }
+
+    if (status == CELIX_SUCCESS) {
+        *out = discovery;
     }
 
 	return status;
@@ -113,9 +119,9 @@ celix_status_t discovery_destroy(discovery_pt discovery) {
 celix_status_t discovery_start(discovery_pt discovery) {
     celix_status_t status;
 
-    status = endpointDiscoveryPoller_create(discovery, discovery->context, &discovery->poller);
+    status = endpointDiscoveryPoller_create(discovery, discovery->context, DEFAULT_POLL_ENDPOINTS, &discovery->poller);
     if (status == CELIX_SUCCESS) {
-        status = endpointDiscoveryServer_create(discovery, discovery->context, &discovery->server);
+        status = endpointDiscoveryServer_create(discovery, discovery->context, DEFAULT_SERVER_PATH, DEFAULT_SERVER_PORT, DEFAULT_SERVER_IP, &discovery->server);
     }
 
     if (status == CELIX_SUCCESS) {

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_shm/src/discovery_impl.h
----------------------------------------------------------------------
diff --git a/remote_services/discovery_shm/src/discovery_impl.h b/remote_services/discovery_shm/src/discovery_impl.h
index c7206bd..e994b1f 100644
--- a/remote_services/discovery_shm/src/discovery_impl.h
+++ b/remote_services/discovery_shm/src/discovery_impl.h
@@ -37,30 +37,17 @@
 #include "endpoint_discovery_server.h"
 #include "discovery_shmWatcher.h"
 
-
 #define DEFAULT_SERVER_IP   "127.0.0.1"
 #define DEFAULT_SERVER_PORT "9999"
 #define DEFAULT_SERVER_PATH "/org.apache.celix.discovery.shm"
 #define DEFAULT_POLL_ENDPOINTS "http://localhost:9999/org.apache.celix.discovery.shm"
 
-#define MAX_ROOTNODE_LENGTH		 64
-#define MAX_LOCALNODE_LENGTH	256
-
-
-struct discovery {
-	bundle_context_pt context;
-
-	celix_thread_mutex_t listenerReferencesMutex;
-	celix_thread_mutex_t discoveredServicesMutex;
-
-	hash_map_pt listenerReferences; //key=serviceReference, value=nop
-	hash_map_pt discoveredServices; //key=endpointId (string), value=endpoint_description_pt
+#define MAX_ROOTNODE_LENGTH    64
+#define MAX_LOCALNODE_LENGTH   256
 
-	shm_watcher_pt watcher;
-	endpoint_discovery_poller_pt poller;
-	endpoint_discovery_server_pt server;
 
-	log_helper_pt loghelper;
+struct discovery_impl {
+    shm_watcher_t* watcher;
 };
 
 #endif /* DISCOVERY_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_shm/src/discovery_shmWatcher.c
----------------------------------------------------------------------
diff --git a/remote_services/discovery_shm/src/discovery_shmWatcher.c b/remote_services/discovery_shm/src/discovery_shmWatcher.c
index 6460de8..ef7df71 100644
--- a/remote_services/discovery_shm/src/discovery_shmWatcher.c
+++ b/remote_services/discovery_shm/src/discovery_shmWatcher.c
@@ -40,6 +40,15 @@
 
 #include "endpoint_discovery_poller.h"
 
+#define DEFAULT_SERVER_IP   "127.0.0.1"
+#define DEFAULT_SERVER_PORT "9999"
+#define DEFAULT_SERVER_PATH "/org.apache.celix.discovery.shm"
+#define DEFAULT_POLL_ENDPOINTS "http://localhost:9999/org.apache.celix.discovery.shm"
+
+#define MAX_ROOTNODE_LENGTH		 64
+#define MAX_LOCALNODE_LENGTH	256
+
+
 struct shm_watcher {
     shmData_pt shmData;
     celix_thread_t watcherThread;
@@ -82,7 +91,7 @@ static celix_status_t discoveryShmWatcher_getLocalNodePath(bundle_context_pt con
 /* retrieves all endpoints from shm and syncs them with the ones already available */
 static celix_status_t discoveryShmWatcher_syncEndpoints(discovery_pt discovery) {
     celix_status_t status = CELIX_SUCCESS;
-    shm_watcher_pt watcher = discovery->watcher;
+    shm_watcher_pt watcher = discovery->pImpl->watcher;
     char** shmKeyArr = calloc(SHM_DATA_MAX_ENTRIES, sizeof(*shmKeyArr));
     array_list_pt registeredKeyArr = NULL;
 
@@ -147,7 +156,7 @@ static celix_status_t discoveryShmWatcher_syncEndpoints(discovery_pt discovery)
 
 static void* discoveryShmWatcher_run(void* data) {
     discovery_pt discovery = (discovery_pt) data;
-    shm_watcher_pt watcher = discovery->watcher;
+    shm_watcher_pt watcher = discovery->pImpl->watcher;
     char localNodePath[MAX_LOCALNODE_LENGTH];
     char url[MAX_LOCALNODE_LENGTH];
 
@@ -194,10 +203,10 @@ celix_status_t discoveryShmWatcher_create(discovery_pt discovery) {
         }
 
         if (status == CELIX_SUCCESS) {
-            discovery->watcher = watcher;
+            discovery->pImpl->watcher = watcher;
         }
         else{
-        	discovery->watcher = NULL;
+        	discovery->pImpl->watcher = NULL;
         	free(watcher);
         }
 
@@ -216,7 +225,7 @@ celix_status_t discoveryShmWatcher_create(discovery_pt discovery) {
 
 celix_status_t discoveryShmWatcher_destroy(discovery_pt discovery) {
     celix_status_t status;
-    shm_watcher_pt watcher = discovery->watcher;
+    shm_watcher_pt watcher = discovery->pImpl->watcher;
     char localNodePath[MAX_LOCALNODE_LENGTH];
 
     celixThreadMutex_lock(&watcher->watcherLock);

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_shm/src/discovery_shmWatcher.h
----------------------------------------------------------------------
diff --git a/remote_services/discovery_shm/src/discovery_shmWatcher.h b/remote_services/discovery_shm/src/discovery_shmWatcher.h
index ff70f72..4e7e1d5 100644
--- a/remote_services/discovery_shm/src/discovery_shmWatcher.h
+++ b/remote_services/discovery_shm/src/discovery_shmWatcher.h
@@ -31,6 +31,7 @@
 #include "discovery.h"
 #include "endpoint_discovery_poller.h"
 
+typedef struct shm_watcher shm_watcher_t;
 typedef struct shm_watcher *shm_watcher_pt;
 
 celix_status_t discoveryShmWatcher_create(discovery_pt discovery);

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_common/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_common/CMakeLists.txt b/remote_services/remote_service_admin_common/CMakeLists.txt
index 1813211..a421cda 100644
--- a/remote_services/remote_service_admin_common/CMakeLists.txt
+++ b/remote_services/remote_service_admin_common/CMakeLists.txt
@@ -21,4 +21,6 @@ add_library(remote_service_admin_common STATIC
     src/import_registration_impl.c
 )
 target_include_directories(remote_service_admin_common PRIVATE src)
-target_link_libraries(remote_service_admin_common PUBLIC Celix::framework Celix::remote_service_admin_api Celix::log_helper)
\ No newline at end of file
+target_link_libraries(remote_service_admin_common PUBLIC Celix::framework Celix::remote_service_admin_api Celix::log_helper)
+
+add_library(Celix::remote_service_admin_common ALIAS remote_service_admin_common)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/CMakeLists.txt b/remote_services/remote_service_admin_dfi/CMakeLists.txt
index 4b28231..206c6dc 100644
--- a/remote_services/remote_service_admin_dfi/CMakeLists.txt
+++ b/remote_services/remote_service_admin_dfi/CMakeLists.txt
@@ -23,21 +23,31 @@ if (RSA_REMOTE_SERVICE_ADMIN_DFI)
     find_package(CURL REQUIRED)
     find_package(Jansson REQUIRED)
 
-    include_directories(
-        ${CURL_INCLUDE_DIRS}
-        ${JANSSON_INCLUDE_DIRS}
+    add_bundle(remote_service_admin_dfi
+            VERSION 0.9.0
+            SYMBOLIC_NAME "apache_celix_remote_service_admin_dfi"
+            NAME "Apache Celix Remote Service Admin Dynamic Function Interface (DFI)"
+            SOURCES
+            src/remote_service_admin_dfi.c
+            src/remote_service_admin_activator.c
+            src/export_registration_dfi.c
+            src/import_registration_dfi.c
+            src/dfi_utils.c
+            $<TARGET_OBJECTS:civetweb>
     )
+    target_include_directories(remote_service_admin_dfi PRIVATE src $<TARGET_PROPERTY:civetweb,INCLUDE_DIRECTORIES>)
+    target_link_libraries(remote_service_admin_dfi PRIVATE
+            Celix::dfi_static
+            Celix::log_helper
+            Celix::remote_service_admin_common
+            ${CURL_LIBRARIES} ${JANSSON_LIBRARIES})
 
-    if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
-        include_directories(dynamic_function_interface/memstream)
-    endif()
-
-    add_subdirectory(rsa)
+    install_bundle(remote_service_admin_dfi)
 
     if (ENABLE_TESTING)
-        find_package(CppUTest REQUIRED)
-        include_directories(${CPPUTEST_INCLUDE_DIR})
-        add_subdirectory(rsa_tst)
+        add_subdirectory(test)
     endif()
 
+    #Setup target aliases to match external usage
+    add_library(Celix::remote_service_admin_dfi ALIAS remote_service_admin_dfi)
 endif()

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/CMakeLists.txt b/remote_services/remote_service_admin_dfi/rsa/CMakeLists.txt
deleted file mode 100644
index 3efabf8..0000000
--- a/remote_services/remote_service_admin_dfi/rsa/CMakeLists.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-# 
-#   http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-add_bundle(remote_service_admin_dfi 
-    VERSION 0.9.0
-    SYMBOLIC_NAME "apache_celix_remote_service_admin_dfi"
-    NAME "Apache Celix Remote Service Admin Dynamic Function Interface (DFI)"
-    SOURCES
-        src/remote_service_admin_dfi.c
-        src/remote_service_admin_activator.c
-        src/export_registration_dfi.c
-        src/import_registration_dfi.c
-        src/dfi_utils.c
-)
-target_include_directories(remote_service_admin_dfi PRIVATE src)
-target_link_libraries(remote_service_admin_dfi PRIVATE
-        Celix::dfi Celix::log_helper remote_service_admin_common
-        ${CURL_LIBRARIES} ${JANSSON_LIBRARIES})
-
-install_bundle(remote_service_admin_dfi)

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa/src/dfi_utils.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/src/dfi_utils.c b/remote_services/remote_service_admin_dfi/rsa/src/dfi_utils.c
deleted file mode 100644
index 1b1eb36..0000000
--- a/remote_services/remote_service_admin_dfi/rsa/src/dfi_utils.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#include "dfi_utils.h"
-#include <stdlib.h>
-#include <unistd.h>
-
-static celix_status_t dfi_findFileForFramework(bundle_context_pt context, const char *fileName, FILE **out) {
-    celix_status_t  status;
-
-    char pwd[1024];
-    char path[1024];
-    const char *extPath = NULL;
-   
-    status = bundleContext_getProperty(context, "CELIX_FRAMEWORK_EXTENDER_PATH", &extPath);
-    if (status != CELIX_SUCCESS || extPath == NULL) {
-        getcwd(pwd, sizeof(pwd));
-        extPath = pwd;
-    }
-
-    snprintf(path, sizeof(path), "%s/%s", extPath, fileName);
-
-    if (status == CELIX_SUCCESS) {
-        FILE *df = fopen(path, "r");
-        if (df == NULL) {
-            status = CELIX_FILE_IO_EXCEPTION;
-        } else {
-            *out = df;
-        }
-    }
-
-    return status;
-}
-
-static celix_status_t dfi_findFileForBundle(bundle_pt bundle, const char *fileName, FILE **out) {
-    celix_status_t  status;
-
-    char *path = NULL;
-    char metaInfFileName[512];
-    snprintf(metaInfFileName, sizeof(metaInfFileName), "META-INF/descriptors/%s", fileName);
-
-    status = bundle_getEntry(bundle, fileName, &path);
-    
-    if (status != CELIX_SUCCESS || path == NULL) {
-        status = bundle_getEntry(bundle, metaInfFileName, &path);
-    }
-
-    if (status == CELIX_SUCCESS && path != NULL) {
-        FILE *df = fopen(path, "r");
-        if (df == NULL) {
-            status = CELIX_FILE_IO_EXCEPTION;
-        } else {
-            *out = df;
-        }
-
-    }
-
-    free(path);
-    return status;
-}
-
-celix_status_t dfi_findDescriptor(bundle_context_pt context, bundle_pt bundle, const char *name, FILE **out) {
-    celix_status_t  status;
-    char fileName[128];
-
-    snprintf(fileName, 128, "%s.descriptor", name);
-
-    long id;
-    status = bundle_getBundleId(bundle, &id);
-    
-    if (status == CELIX_SUCCESS) {
-        if (id == 0) {
-            //framework bundle
-            status = dfi_findFileForFramework(context, fileName, out);
-        } else {
-            //normal bundle
-            status = dfi_findFileForBundle(bundle, fileName, out);
-        }
-    }
-
-    return status;
-}

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa/src/dfi_utils.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/src/dfi_utils.h b/remote_services/remote_service_admin_dfi/rsa/src/dfi_utils.h
deleted file mode 100644
index cec8aa1..0000000
--- a/remote_services/remote_service_admin_dfi/rsa/src/dfi_utils.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-#ifndef DFI_UTILS_H_
-#define DFI_UTILS_H_
-
-#include "bundle.h"
-#include "bundle_context.h"
-#include <stdio.h>
-#include "celix_errno.h"
-
-
-celix_status_t dfi_findDescriptor(bundle_context_pt context, bundle_pt bundle, const char *name, FILE **out);
-
-#endif

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa/src/export_registration_dfi.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/src/export_registration_dfi.c b/remote_services/remote_service_admin_dfi/rsa/src/export_registration_dfi.c
deleted file mode 100644
index b83b5a8..0000000
--- a/remote_services/remote_service_admin_dfi/rsa/src/export_registration_dfi.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#include <jansson.h>
-#include <dyn_interface.h>
-#include <json_serializer.h>
-#include <remote_constants.h>
-#include <remote_service_admin.h>
-#include <service_tracker_customizer.h>
-#include <service_tracker.h>
-#include <json_rpc.h>
-#include "constants.h"
-#include "export_registration_dfi.h"
-#include "dfi_utils.h"
-
-struct export_reference {
-    endpoint_description_pt endpoint; //owner
-    service_reference_pt reference;
-};
-
-struct export_registration {
-    bundle_context_pt  context;
-    struct export_reference exportReference;
-    char *servId;
-    dyn_interface_type *intf; //owner
-    service_tracker_pt tracker;
-
-    celix_thread_mutex_t mutex;
-    void *service; //protected by mutex
-
-    //TODO add tracker and lock
-    bool closed;
-};
-
-static void exportRegistration_addServ(export_registration_pt reg, service_reference_pt ref, void *service);
-static void exportRegistration_removeServ(export_registration_pt reg, service_reference_pt ref, void *service);
-
-celix_status_t exportRegistration_create(log_helper_pt helper, service_reference_pt reference, endpoint_description_pt endpoint, bundle_context_pt context, export_registration_pt *out) {
-    celix_status_t status = CELIX_SUCCESS;
-
-    const char *servId = NULL;
-    status = serviceReference_getProperty(reference, "service.id", &servId);
-    if (status != CELIX_SUCCESS) {
-        logHelper_log(helper, OSGI_LOGSERVICE_WARNING, "Cannot find service.id for ref");
-    }
-
-    export_registration_pt reg = NULL;
-    if (status == CELIX_SUCCESS) {
-        reg = calloc(1, sizeof(*reg));
-        if (reg == NULL) {
-            status = CELIX_ENOMEM;
-        }
-    }
-
-
-    if (status == CELIX_SUCCESS) {
-        reg->context = context;
-        reg->exportReference.endpoint = endpoint;
-        reg->exportReference.reference = reference;
-        reg->closed = false;
-
-        celixThreadMutex_create(&reg->mutex, NULL);
-    }
-
-    const char *exports = NULL;
-    CELIX_DO_IF(status, serviceReference_getProperty(reference, (char *) OSGI_RSA_SERVICE_EXPORTED_INTERFACES, &exports));
-
-    bundle_pt bundle = NULL;
-    CELIX_DO_IF(status, serviceReference_getBundle(reference, &bundle));
-
-    FILE *descriptor = NULL;
-    if (status == CELIX_SUCCESS) {
-        status = dfi_findDescriptor(context, bundle, exports, &descriptor);
-    }
-
-    if (status != CELIX_SUCCESS || descriptor == NULL) {
-        status = CELIX_BUNDLE_EXCEPTION;
-        logHelper_log(helper, OSGI_LOGSERVICE_ERROR, "Cannot find/open descriptor for '%s'", exports);
-    }
-
-    if (status == CELIX_SUCCESS) {
-        int rc = dynInterface_parse(descriptor, &reg->intf);
-        fclose(descriptor);
-        if (rc != 0) {
-            status = CELIX_BUNDLE_EXCEPTION;
-            logHelper_log(helper, OSGI_LOGSERVICE_WARNING, "RSA: Error parsing service descriptor.");
-        }
-        else{
-            /* Add the interface version as a property in the properties_map */
-            char* intfVersion = NULL;
-            dynInterface_getVersionString(reg->intf, &intfVersion);
-            const char *serviceVersion = properties_get(endpoint->properties,(char*) CELIX_FRAMEWORK_SERVICE_VERSION);
-            if(serviceVersion!=NULL){
-            	if(strcmp(serviceVersion,intfVersion)!=0){
-            		logHelper_log(helper, OSGI_LOGSERVICE_WARNING, "Service version (%s) and interface version from the descriptor (%s) are not the same!",serviceVersion,intfVersion);
-            	}
-            }
-            else{
-            	properties_set(endpoint->properties, (char*) CELIX_FRAMEWORK_SERVICE_VERSION, intfVersion);
-            }
-        }
-    } 
-
-    if (status == CELIX_SUCCESS) {
-        service_tracker_customizer_pt cust = NULL;
-        status = serviceTrackerCustomizer_create(reg, NULL, (void *) exportRegistration_addServ, NULL,
-                                                 (void *) exportRegistration_removeServ, &cust);
-        if (status == CELIX_SUCCESS) {
-            char filter[32];
-            snprintf(filter, 32, "(service.id=%s)", servId);
-            status = serviceTracker_createWithFilter(reg->context, filter, cust, &reg->tracker);
-        }
-    }
-
-    if (status == CELIX_SUCCESS) {
-        *out = reg;
-    } else {
-        logHelper_log(helper, OSGI_LOGSERVICE_ERROR, "Error creating export registration");
-        exportRegistration_destroy(reg);
-    }
-
-    return status;
-}
-
-celix_status_t exportRegistration_call(export_registration_pt export, char *data, int datalength, char **responseOut, int *responseLength) {
-    int status = CELIX_SUCCESS;
-
-    //printf("calling for '%s'\n");
-
-    *responseLength = -1;
-    celixThreadMutex_lock(&export->mutex);
-    status = jsonRpc_call(export->intf, export->service, data, responseOut);
-    celixThreadMutex_unlock(&export->mutex);
-
-    return status;
-}
-
-void exportRegistration_destroy(export_registration_pt reg) {
-    if (reg != NULL) {
-        if (reg->intf != NULL) {
-            dyn_interface_type *intf = reg->intf;
-            reg->intf = NULL;
-            dynInterface_destroy(intf);
-        }
-
-        if (reg->exportReference.endpoint != NULL) {
-            endpoint_description_pt ep = reg->exportReference.endpoint;
-            reg->exportReference.endpoint = NULL;
-            endpointDescription_destroy(ep);
-        }
-        if (reg->tracker != NULL) {
-            serviceTracker_destroy(reg->tracker);
-        }
-        celixThreadMutex_destroy(&reg->mutex);
-
-        free(reg);
-    }
-}
-
-celix_status_t exportRegistration_start(export_registration_pt reg) {
-    celix_status_t status = CELIX_SUCCESS;
-
-    serviceTracker_open(reg->tracker);
-    return status;
-}
-
-
-celix_status_t exportRegistration_stop(export_registration_pt reg) {
-    celix_status_t status = CELIX_SUCCESS;
-    if (status == CELIX_SUCCESS) {
-        status = bundleContext_ungetServiceReference(reg->context, reg->exportReference.reference);
-        serviceTracker_close(reg->tracker);
-    }
-    return status;
-}
-
-static void exportRegistration_addServ(export_registration_pt reg, service_reference_pt ref, void *service) {
-    celixThreadMutex_lock(&reg->mutex);
-    reg->service = service;
-    celixThreadMutex_unlock(&reg->mutex);
-}
-
-static void exportRegistration_removeServ(export_registration_pt reg, service_reference_pt ref, void *service) {
-    celixThreadMutex_lock(&reg->mutex);
-    if (reg->service == service) {
-        reg->service = NULL;
-    }
-    celixThreadMutex_unlock(&reg->mutex);
-}
-
-
-celix_status_t exportRegistration_close(export_registration_pt reg) {
-    celix_status_t status = CELIX_SUCCESS;
-    exportRegistration_stop(reg);
-    return status;
-}
-
-
-celix_status_t exportRegistration_getException(export_registration_pt registration) {
-    celix_status_t status = CELIX_SUCCESS;
-    //TODO
-    return status;
-}
-
-celix_status_t exportRegistration_getExportReference(export_registration_pt registration, export_reference_pt *out) {
-    celix_status_t status = CELIX_SUCCESS;
-    export_reference_pt ref = calloc(1, sizeof(*ref));
-    if (ref != NULL) {
-        ref->endpoint = registration->exportReference.endpoint;
-        ref->reference = registration->exportReference.reference;
-    } else {
-        status = CELIX_ENOMEM;
-    }
-
-    if (status == CELIX_SUCCESS) {
-        *out = ref;
-    }
-
-    return status;
-}
-
-celix_status_t exportReference_getExportedEndpoint(export_reference_pt reference, endpoint_description_pt *endpoint) {
-    celix_status_t status = CELIX_SUCCESS;
-    *endpoint = reference->endpoint;
-    return status;
-}
-
-celix_status_t exportReference_getExportedService(export_reference_pt reference, service_reference_pt *ref) {
-    celix_status_t status = CELIX_SUCCESS;
-    *ref = reference->reference;
-    return status;
-}
-
-
-

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa/src/export_registration_dfi.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/src/export_registration_dfi.h b/remote_services/remote_service_admin_dfi/rsa/src/export_registration_dfi.h
deleted file mode 100644
index 93f37ba..0000000
--- a/remote_services/remote_service_admin_dfi/rsa/src/export_registration_dfi.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#ifndef CELIX_EXPORT_REGISTRATION_DFI_H
-#define CELIX_EXPORT_REGISTRATION_DFI_H
-
-
-#include "export_registration.h"
-#include "log_helper.h"
-#include "endpoint_description.h"
-
-celix_status_t exportRegistration_create(log_helper_pt helper, service_reference_pt reference, endpoint_description_pt endpoint, bundle_context_pt context, export_registration_pt *registration);
-celix_status_t exportRegistration_close(export_registration_pt registration);
-void exportRegistration_destroy(export_registration_pt registration);
-
-celix_status_t exportRegistration_start(export_registration_pt registration);
-celix_status_t exportRegistration_stop(export_registration_pt registration);
-
-celix_status_t exportRegistration_call(export_registration_pt export, char *data, int datalength, char **response, int *responseLength);
-
-
-#endif //CELIX_EXPORT_REGISTRATION_DFI_H

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa/src/import_registration_dfi.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/src/import_registration_dfi.c b/remote_services/remote_service_admin_dfi/rsa/src/import_registration_dfi.c
deleted file mode 100644
index 0b8dcf7..0000000
--- a/remote_services/remote_service_admin_dfi/rsa/src/import_registration_dfi.c
+++ /dev/null
@@ -1,402 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#include <stdlib.h>
-#include <jansson.h>
-#include <json_rpc.h>
-#include <assert.h>
-#include "version.h"
-#include "json_serializer.h"
-#include "dyn_interface.h"
-#include "import_registration.h"
-#include "import_registration_dfi.h"
-
-struct import_registration {
-    bundle_context_pt context;
-    endpoint_description_pt  endpoint; //TODO owner? -> free when destroyed
-    const char *classObject; //NOTE owned by endpoint
-    version_pt version;
-
-    celix_thread_mutex_t mutex; //protects send & sendhandle
-    send_func_type send;
-    void *sendHandle;
-
-    service_factory_pt factory;
-    service_registration_pt factoryReg;
-
-    hash_map_pt proxies; //key -> bundle, value -> service_proxy
-    celix_thread_mutex_t proxiesMutex; //protects proxies
-};
-
-struct service_proxy {
-    dyn_interface_type *intf;
-    void *service;
-    size_t count;
-};
-
-static celix_status_t importRegistration_createProxy(import_registration_pt import, bundle_pt bundle,
-                                              struct service_proxy **proxy);
-static void importRegistration_proxyFunc(void *userData, void *args[], void *returnVal);
-static void importRegistration_destroyProxy(struct service_proxy *proxy);
-static void importRegistration_clearProxies(import_registration_pt import);
-
-celix_status_t importRegistration_create(bundle_context_pt context, endpoint_description_pt endpoint, const char *classObject, const char* serviceVersion,
-                                         import_registration_pt *out) {
-    celix_status_t status = CELIX_SUCCESS;
-    import_registration_pt reg = calloc(1, sizeof(*reg));
-
-    if (reg != NULL) {
-        reg->factory = calloc(1, sizeof(*reg->factory));
-    }
-
-    if (reg != NULL && reg->factory != NULL) {
-        reg->context = context;
-        reg->endpoint = endpoint;
-        reg->classObject = classObject;
-        reg->proxies = hashMap_create(NULL, NULL, NULL, NULL);
-
-        celixThreadMutex_create(&reg->mutex, NULL);
-        celixThreadMutex_create(&reg->proxiesMutex, NULL);
-        status = version_createVersionFromString((char*)serviceVersion,&(reg->version));
-
-        reg->factory->handle = reg;
-        reg->factory->getService = (void *)importRegistration_getService;
-        reg->factory->ungetService = (void *)importRegistration_ungetService;
-    } else {
-        status = CELIX_ENOMEM;
-    }
-
-    if (status == CELIX_SUCCESS) {
-        //printf("IMPORT REGISTRATION IS %p\n", reg);
-        *out = reg;
-    }
-    else{
-    	importRegistration_destroy(reg);
-    }
-
-    return status;
-}
-
-
-celix_status_t importRegistration_setSendFn(import_registration_pt reg,
-                                            send_func_type send,
-                                            void *handle) {
-    celixThreadMutex_lock(&reg->mutex);
-    reg->send = send;
-    reg->sendHandle = handle;
-    celixThreadMutex_unlock(&reg->mutex);
-
-    return CELIX_SUCCESS;
-}
-
-static void importRegistration_clearProxies(import_registration_pt import) {
-    if (import != NULL) {
-        pthread_mutex_lock(&import->proxiesMutex);
-        if (import->proxies != NULL) {
-            hash_map_iterator_pt iter = hashMapIterator_create(import->proxies);
-            while (hashMapIterator_hasNext(iter)) {
-                hash_map_entry_pt  entry = hashMapIterator_nextEntry(iter);
-                struct service_proxy *proxy = hashMapEntry_getValue(entry);
-                importRegistration_destroyProxy(proxy);
-            }
-            hashMapIterator_destroy(iter);
-        }
-        pthread_mutex_unlock(&import->proxiesMutex);
-    }
-}
-
-void importRegistration_destroy(import_registration_pt import) {
-    if (import != NULL) {
-        if (import->proxies != NULL) {
-            hashMap_destroy(import->proxies, false, false);
-            import->proxies = NULL;
-        }
-
-        pthread_mutex_destroy(&import->mutex);
-        pthread_mutex_destroy(&import->proxiesMutex);
-
-        if (import->factory != NULL) {
-            free(import->factory);
-        }
-
-        if(import->version!=NULL){
-        	version_destroy(import->version);
-        }
-        free(import);
-    }
-}
-
-celix_status_t importRegistration_start(import_registration_pt import) {
-    celix_status_t  status = CELIX_SUCCESS;
-    if (import->factoryReg == NULL && import->factory != NULL) {
-        properties_pt props = NULL;
-        properties_copy(import->endpoint->properties, &props);
-        status = bundleContext_registerServiceFactory(import->context, (char *)import->classObject, import->factory, props, &import->factoryReg);
-    } else {
-        status = CELIX_ILLEGAL_STATE;
-    }
-    return status;
-}
-
-celix_status_t importRegistration_stop(import_registration_pt import) {
-    celix_status_t status = CELIX_SUCCESS;
-
-    if (import->factoryReg != NULL) {
-        serviceRegistration_unregister(import->factoryReg);
-        import->factoryReg = NULL;
-    }
-
-    importRegistration_clearProxies(import);
-
-    return status;
-}
-
-
-celix_status_t importRegistration_getService(import_registration_pt import, bundle_pt bundle, service_registration_pt registration, void **out) {
-    celix_status_t  status = CELIX_SUCCESS;
-
-    /*
-    module_pt module = NULL;
-    char *name = NULL;
-    bundle_getCurrentModule(bundle, &module);
-    module_getSymbolicName(module, &name);
-    printf("getting service for bundle '%s'\n", name);
-     */
-
-
-    pthread_mutex_lock(&import->proxiesMutex);
-    struct service_proxy *proxy = hashMap_get(import->proxies, bundle);
-    if (proxy == NULL) {
-        status = importRegistration_createProxy(import, bundle, &proxy);
-        if (status == CELIX_SUCCESS) {
-            hashMap_put(import->proxies, bundle, proxy);
-        }
-    }
-
-    if (status == CELIX_SUCCESS) {
-        proxy->count += 1;
-        *out = proxy->service;
-    }
-    pthread_mutex_unlock(&import->proxiesMutex);
-
-    return status;
-}
-
-static celix_status_t importRegistration_createProxy(import_registration_pt import, bundle_pt bundle, struct service_proxy **out) {
-    celix_status_t  status;
-    dyn_interface_type* intf = NULL;
-    FILE *descriptor = NULL;
-
-    status = dfi_findDescriptor(import->context, bundle, import->classObject, &descriptor);
-
-    if (status != CELIX_SUCCESS || descriptor == NULL) {
-        //TODO use log helper logHelper_log(helper, OSGI_LOGSERVICE_ERROR, "Cannot find/open descriptor for '%s'", import->classObject);
-        fprintf(stderr, "RSA_DFI: Cannot find/open descriptor for '%s'", import->classObject);
-        return CELIX_BUNDLE_EXCEPTION;
-    }
-
-    if (status == CELIX_SUCCESS) {
-        int rc = dynInterface_parse(descriptor, &intf);
-        fclose(descriptor);
-        if (rc != 0 || intf==NULL) {
-            return CELIX_BUNDLE_EXCEPTION;
-        }
-    }
-
-    /* Check if the imported service version is compatible with the one in the consumer descriptor */
-    version_pt consumerVersion = NULL;
-    bool isCompatible = false;
-    dynInterface_getVersion(intf,&consumerVersion);
-    version_isCompatible(consumerVersion,import->version,&isCompatible);
-
-    if(!isCompatible){
-    	char* cVerString = NULL;
-    	char* pVerString = NULL;
-    	version_toString(consumerVersion,&cVerString);
-    	version_toString(import->version,&pVerString);
-    	printf("Service version mismatch: consumer has %s, provider has %s. NOT creating proxy.\n",cVerString,pVerString);
-    	dynInterface_destroy(intf);
-    	free(cVerString);
-    	free(pVerString);
-    	status = CELIX_SERVICE_EXCEPTION;
-    }
-
-    struct service_proxy *proxy = NULL;
-    if (status == CELIX_SUCCESS) {
-        proxy = calloc(1, sizeof(*proxy));
-        if (proxy == NULL) {
-            status = CELIX_ENOMEM;
-        }
-    }
-
-    if (status == CELIX_SUCCESS) {
-    	proxy->intf = intf;
-        size_t count = dynInterface_nrOfMethods(proxy->intf);
-        proxy->service = calloc(1 + count, sizeof(void *));
-        if (proxy->service == NULL) {
-            status = CELIX_ENOMEM;
-        }
-    }
-
-    if (status == CELIX_SUCCESS) {
-        void **serv = proxy->service;
-        serv[0] = import;
-
-        struct methods_head *list = NULL;
-        dynInterface_methods(proxy->intf, &list);
-        struct method_entry *entry = NULL;
-        void (*fn)(void) = NULL;
-        int index = 0;
-        TAILQ_FOREACH(entry, list, entries) {
-            int rc = dynFunction_createClosure(entry->dynFunc, importRegistration_proxyFunc, entry, &fn);
-            serv[index + 1] = fn;
-            index += 1;
-
-            if (rc != 0) {
-                status = CELIX_BUNDLE_EXCEPTION;
-                break;
-            }
-        }
-    }
-
-    if (status == CELIX_SUCCESS) {
-        *out = proxy;
-    } else if (proxy != NULL) {
-        if (proxy->intf != NULL) {
-            dynInterface_destroy(proxy->intf);
-            proxy->intf = NULL;
-        }
-        free(proxy->service);
-        free(proxy);
-    }
-
-    return status;
-}
-
-static void importRegistration_proxyFunc(void *userData, void *args[], void *returnVal) {
-    int  status = CELIX_SUCCESS;
-    struct method_entry *entry = userData;
-    import_registration_pt import = *((void **)args[0]);
-
-    if (import == NULL || import->send == NULL) {
-        status = CELIX_ILLEGAL_ARGUMENT;
-    }
-
-
-    char *invokeRequest = NULL;
-    if (status == CELIX_SUCCESS) {
-        status = jsonRpc_prepareInvokeRequest(entry->dynFunc, entry->id, args, &invokeRequest);
-        //printf("Need to send following json '%s'\n", invokeRequest);
-    }
-
-
-    if (status == CELIX_SUCCESS) {
-        char *reply = NULL;
-        int rc = 0;
-        //printf("sending request\n");
-        celixThreadMutex_lock(&import->mutex);
-        if (import->send != NULL) {
-            import->send(import->sendHandle, import->endpoint, invokeRequest, &reply, &rc);
-        }
-        celixThreadMutex_unlock(&import->mutex);
-        //printf("request sended. got reply '%s' with status %i\n", reply, rc);
-
-        if (rc == 0) {
-            //fjprintf("Handling reply '%s'\n", reply);
-            status = jsonRpc_handleReply(entry->dynFunc, reply, args);
-        }
-
-        *(int *) returnVal = rc;
-
-        free(invokeRequest); //Allocated by json_dumps in jsonRpc_prepareInvokeRequest
-        free(reply); //Allocated by json_dumps in remoteServiceAdmin_send through curl call
-    }
-
-    if (status != CELIX_SUCCESS) {
-        //TODO log error
-    }
-}
-
-celix_status_t importRegistration_ungetService(import_registration_pt import, bundle_pt bundle, service_registration_pt registration, void **out) {
-    celix_status_t  status = CELIX_SUCCESS;
-
-    assert(import != NULL);
-    assert(import->proxies != NULL);
-
-    pthread_mutex_lock(&import->proxiesMutex);
-
-    struct service_proxy *proxy = hashMap_get(import->proxies, bundle);
-    if (proxy != NULL) {
-        if (*out == proxy->service) {
-            proxy->count -= 1;
-        } else {
-            status = CELIX_ILLEGAL_ARGUMENT;
-        }
-
-        if (proxy->count == 0) {
-            hashMap_remove(import->proxies, bundle);
-            importRegistration_destroyProxy(proxy);
-        }
-    }
-
-    pthread_mutex_unlock(&import->proxiesMutex);
-
-    return status;
-}
-
-static void importRegistration_destroyProxy(struct service_proxy *proxy) {
-    if (proxy != NULL) {
-        if (proxy->intf != NULL) {
-            dynInterface_destroy(proxy->intf);
-        }
-        if (proxy->service != NULL) {
-            free(proxy->service);
-        }
-        free(proxy);
-    }
-}
-
-
-celix_status_t importRegistration_close(import_registration_pt registration) {
-    celix_status_t status = CELIX_SUCCESS;
-    importRegistration_stop(registration);
-    return status;
-}
-
-celix_status_t importRegistration_getException(import_registration_pt registration) {
-    celix_status_t status = CELIX_SUCCESS;
-    //TODO
-    return status;
-}
-
-celix_status_t importRegistration_getImportReference(import_registration_pt registration, import_reference_pt *reference) {
-    celix_status_t status = CELIX_SUCCESS;
-    //TODO
-    return status;
-}
-
-celix_status_t importReference_getImportedEndpoint(import_reference_pt reference) {
-    celix_status_t status = CELIX_SUCCESS;
-    return status;
-}
-
-celix_status_t importReference_getImportedService(import_reference_pt reference) {
-    celix_status_t status = CELIX_SUCCESS;
-    return status;
-}

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa/src/import_registration_dfi.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/src/import_registration_dfi.h b/remote_services/remote_service_admin_dfi/rsa/src/import_registration_dfi.h
deleted file mode 100644
index aac4bc7..0000000
--- a/remote_services/remote_service_admin_dfi/rsa/src/import_registration_dfi.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#ifndef CELIX_IMPORT_REGISTRATION_DFI_H
-#define CELIX_IMPORT_REGISTRATION_DFI_H
-
-#include "import_registration.h"
-#include "dfi_utils.h"
-
-#include <celix_errno.h>
-
-typedef void (*send_func_type)(void *handle, endpoint_description_pt endpointDescription, char *request, char **reply, int* replyStatus);
-
-celix_status_t importRegistration_create(bundle_context_pt context, endpoint_description_pt description, const char *classObject, const char* serviceVersion,
-                                         import_registration_pt *import);
-celix_status_t importRegistration_close(import_registration_pt import);
-void importRegistration_destroy(import_registration_pt import);
-
-celix_status_t importRegistration_setSendFn(import_registration_pt reg,
-                                            send_func_type,
-                                            void *handle);
-celix_status_t importRegistration_start(import_registration_pt import);
-celix_status_t importRegistration_stop(import_registration_pt import);
-
-celix_status_t importRegistration_getService(import_registration_pt import, bundle_pt bundle, service_registration_pt registration, void **service);
-celix_status_t importRegistration_ungetService(import_registration_pt import, bundle_pt bundle, service_registration_pt registration, void **service);
-
-#endif //CELIX_IMPORT_REGISTRATION_DFI_H

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_activator.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_activator.c b/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_activator.c
deleted file mode 100644
index d4cc765..0000000
--- a/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_activator.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-/*
- * remote_service_admin_activator.c
- *
- *  \date       Sep 30, 2011
- *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright	Apache License, Version 2.0
- */
-#include <stdlib.h>
-#include <remote_service_admin.h>
-
-#include "remote_service_admin_dfi.h"
-
-#include "bundle_activator.h"
-#include "service_registration.h"
-
-#include "export_registration_dfi.h"
-#include "import_registration_dfi.h"
-
-struct activator {
-	remote_service_admin_pt admin;
-	remote_service_admin_service_pt adminService;
-	service_registration_pt registration;
-};
-
-celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) {
-	celix_status_t status = CELIX_SUCCESS;
-	struct activator *activator;
-
-	activator = calloc(1, sizeof(*activator));
-	if (!activator) {
-		status = CELIX_ENOMEM;
-	} else {
-		activator->admin = NULL;
-		activator->registration = NULL;
-
-		*userData = activator;
-	}
-
-	return status;
-}
-
-celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
-	celix_status_t status = CELIX_SUCCESS;
-	struct activator *activator = userData;
-	remote_service_admin_service_pt remoteServiceAdmin = NULL;
-
-	status = remoteServiceAdmin_create(context, &activator->admin);
-	if (status == CELIX_SUCCESS) {
-		remoteServiceAdmin = calloc(1, sizeof(*remoteServiceAdmin));
-		if (!remoteServiceAdmin) {
-			status = CELIX_ENOMEM;
-		} else {
-			remoteServiceAdmin->admin = activator->admin;
-			remoteServiceAdmin->exportService = remoteServiceAdmin_exportService;
-
-			remoteServiceAdmin->getExportedServices = remoteServiceAdmin_getExportedServices;
-			remoteServiceAdmin->getImportedEndpoints = remoteServiceAdmin_getImportedEndpoints;
-			remoteServiceAdmin->importService = remoteServiceAdmin_importService;
-
-			remoteServiceAdmin->exportReference_getExportedEndpoint = exportReference_getExportedEndpoint;
-			remoteServiceAdmin->exportReference_getExportedService = exportReference_getExportedService;
-
-			remoteServiceAdmin->exportRegistration_close = remoteServiceAdmin_removeExportedService;
-			remoteServiceAdmin->exportRegistration_getException = exportRegistration_getException;
-			remoteServiceAdmin->exportRegistration_getExportReference = exportRegistration_getExportReference;
-
-			remoteServiceAdmin->importReference_getImportedEndpoint = importReference_getImportedEndpoint;
-			remoteServiceAdmin->importReference_getImportedService = importReference_getImportedService;
-
-			remoteServiceAdmin->importRegistration_close = remoteServiceAdmin_removeImportedService;
-			remoteServiceAdmin->importRegistration_getException = importRegistration_getException;
-			remoteServiceAdmin->importRegistration_getImportReference = importRegistration_getImportReference;
-
-			status = bundleContext_registerService(context, OSGI_RSA_REMOTE_SERVICE_ADMIN, remoteServiceAdmin, NULL, &activator->registration);
-			activator->adminService = remoteServiceAdmin;
-		}
-	}
-
-	return status;
-}
-
-celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) {
-    celix_status_t status = CELIX_SUCCESS;
-    struct activator *activator = userData;
-
-    serviceRegistration_unregister(activator->registration);
-    activator->registration = NULL;
-
-    remoteServiceAdmin_stop(activator->admin);
-    remoteServiceAdmin_destroy(&activator->admin);
-
-    free(activator->adminService);
-
-    return status;
-}
-
-celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) {
-	celix_status_t status = CELIX_SUCCESS;
-	struct activator *activator = userData;
-
-	free(activator);
-
-	return status;
-}
-
-


[2/8] celix git commit: CELIX-417: Refactors CMake usage for the RSA bundles

Posted by pn...@apache.org.
http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_dfi.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_dfi.c b/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_dfi.c
deleted file mode 100644
index 9feab9f..0000000
--- a/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_dfi.c
+++ /dev/null
@@ -1,775 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-/*
- * remote_service_admin_impl.c
- *
- *  \date       May 21, 2015
- *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright	Apache License, Version 2.0
- */
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <ifaddrs.h>
-#include <string.h>
-#include <uuid/uuid.h>
-#include <curl/curl.h>
-
-#include <jansson.h>
-#include "json_serializer.h"
-#include "remote_service_admin.h"
-#include "celix_threads.h"
-#include "hash_map.h"
-#include "array_list.h"
-
-#include "import_registration_dfi.h"
-#include "export_registration_dfi.h"
-#include "remote_service_admin_dfi.h"
-#include "dyn_interface.h"
-#include "json_rpc.h"
-
-#include "remote_constants.h"
-#include "constants.h"
-#include "civetweb.h"
-
-// defines how often the webserver is restarted (with an increased port number)
-#define MAX_NUMBER_OF_RESTARTS 	5
-
-
-#define RSA_LOG_ERROR(admin, msg, ...) \
-    logHelper_log((admin)->loghelper, OSGI_LOGSERVICE_ERROR, (msg),  ##__VA_ARGS__)
-
-#define RSA_LOG_WARNING(admin, msg, ...) \
-    logHelper_log((admin)->loghelper, OSGI_LOGSERVICE_ERROR, (msg),  ##__VA_ARGS__)
-
-#define RSA_LOG_DEBUG(admin, msg, ...) \
-    logHelper_log((admin)->loghelper, OSGI_LOGSERVICE_ERROR, (msg),  ##__VA_ARGS__)
-
-struct remote_service_admin {
-    bundle_context_pt context;
-    log_helper_pt loghelper;
-
-    celix_thread_mutex_t exportedServicesLock;
-    hash_map_pt exportedServices;
-
-    celix_thread_mutex_t importedServicesLock;
-    array_list_pt importedServices;
-
-    char *port;
-    char *ip;
-
-    struct mg_context *ctx;
-};
-
-struct post {
-    const char *readptr;
-    int size;
-};
-
-struct get {
-    char *writeptr;
-    int size;
-};
-
-#define OSGI_RSA_REMOTE_PROXY_FACTORY 	"remote_proxy_factory"
-#define OSGI_RSA_REMOTE_PROXY_TIMEOUT   "remote_proxy_timeout"
-
-static const char *data_response_headers =
-        "HTTP/1.1 200 OK\r\n"
-                "Cache: no-cache\r\n"
-                "Content-Type: application/json\r\n"
-                "\r\n";
-
-static const char *no_content_response_headers =
-        "HTTP/1.1 204 OK\r\n";
-
-// TODO do we need to specify a non-Amdatu specific configuration type?!
-static const char * const CONFIGURATION_TYPE = "org.amdatu.remote.admin.http";
-static const char * const ENDPOINT_URL = "org.amdatu.remote.admin.http.url";
-
-static const char *DEFAULT_PORT = "8888";
-static const char *DEFAULT_IP = "127.0.0.1";
-
-static const unsigned int DEFAULT_TIMEOUT = 0;
-
-static int remoteServiceAdmin_callback(struct mg_connection *conn);
-static celix_status_t remoteServiceAdmin_createEndpointDescription(remote_service_admin_pt admin, service_reference_pt reference, properties_pt props, char *interface, endpoint_description_pt *description);
-static celix_status_t remoteServiceAdmin_send(void *handle, endpoint_description_pt endpointDescription, char *request, char **reply, int* replyStatus);
-static celix_status_t remoteServiceAdmin_getIpAdress(char* interface, char** ip);
-static size_t remoteServiceAdmin_readCallback(void *ptr, size_t size, size_t nmemb, void *userp);
-static size_t remoteServiceAdmin_write(void *contents, size_t size, size_t nmemb, void *userp);
-static void remoteServiceAdmin_log(remote_service_admin_pt admin, int level, const char *file, int line, const char *msg, ...);
-
-celix_status_t remoteServiceAdmin_create(bundle_context_pt context, remote_service_admin_pt *admin) {
-    celix_status_t status = CELIX_SUCCESS;
-
-    *admin = calloc(1, sizeof(**admin));
-
-    if (!*admin) {
-        status = CELIX_ENOMEM;
-    } else {
-        unsigned int port_counter = 0;
-        const char *port = NULL;
-        const char *ip = NULL;
-        char *detectedIp = NULL;
-        (*admin)->context = context;
-        (*admin)->exportedServices = hashMap_create(NULL, NULL, NULL, NULL);
-         arrayList_create(&(*admin)->importedServices);
-
-        celixThreadMutex_create(&(*admin)->exportedServicesLock, NULL);
-        celixThreadMutex_create(&(*admin)->importedServicesLock, NULL);
-
-        if (logHelper_create(context, &(*admin)->loghelper) == CELIX_SUCCESS) {
-            logHelper_start((*admin)->loghelper);
-            dynCommon_logSetup((void *)remoteServiceAdmin_log, *admin, 1);
-            dynType_logSetup((void *)remoteServiceAdmin_log, *admin, 1);
-            dynFunction_logSetup((void *)remoteServiceAdmin_log, *admin, 1);
-            dynInterface_logSetup((void *)remoteServiceAdmin_log, *admin, 1);
-            jsonSerializer_logSetup((void *)remoteServiceAdmin_log, *admin, 1);
-            jsonRpc_logSetup((void *)remoteServiceAdmin_log, *admin, 1);
-        }
-
-        bundleContext_getProperty(context, "RSA_PORT", &port);
-        if (port == NULL) {
-            port = (char *)DEFAULT_PORT;
-        }
-
-        bundleContext_getProperty(context, "RSA_IP", &ip);
-        if (ip == NULL) {
-            const char *interface = NULL;
-
-            bundleContext_getProperty(context, "RSA_INTERFACE", &interface);
-            if ((interface != NULL) && (remoteServiceAdmin_getIpAdress((char*)interface, &detectedIp) != CELIX_SUCCESS)) {
-                logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "RSA: Could not retrieve IP adress for interface %s", interface);
-            }
-
-            if (ip == NULL) {
-                remoteServiceAdmin_getIpAdress(NULL, &detectedIp);
-            }
-
-            ip = detectedIp;
-        }
-
-        if (ip != NULL) {
-            logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Using %s for service annunciation", ip);
-            (*admin)->ip = strdup(ip);
-        }
-        else {
-            logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "RSA: No IP address for service annunciation set. Using %s", DEFAULT_IP);
-            (*admin)->ip = strdup((char*) DEFAULT_IP);
-        }
-
-        if (detectedIp != NULL) {
-            free(detectedIp);
-        }
-
-        // Prepare callbacks structure. We have only one callback, the rest are NULL.
-        struct mg_callbacks callbacks;
-        memset(&callbacks, 0, sizeof(callbacks));
-        callbacks.begin_request = remoteServiceAdmin_callback;
-
-        char newPort[10];
-
-        do {
-
-            const char *options[] = { "listening_ports", port, "num_threads", "5", NULL};
-
-            (*admin)->ctx = mg_start(&callbacks, (*admin), options);
-
-            if ((*admin)->ctx != NULL) {
-                logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Start webserver: %s", port);
-                (*admin)->port = strdup(port);
-
-            }
-            else {
-            	errno = 0;
-                char* endptr = (char*)port;
-                int currentPort = strtol(port, &endptr, 10);
-
-                if (*endptr || errno != 0) {
-                    currentPort = strtol(DEFAULT_PORT, NULL, 10);
-                }
-
-                port_counter++;
-                snprintf(&newPort[0], 6,  "%d", (currentPort+1));
-
-                logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_ERROR, "Error while starting rsa server on port %s - retrying on port %s...", port, newPort);
-                port = newPort;
-            }
-        } while(((*admin)->ctx == NULL) && (port_counter < MAX_NUMBER_OF_RESTARTS));
-
-    }
-
-    return status;
-}
-
-
-celix_status_t remoteServiceAdmin_destroy(remote_service_admin_pt *admin)
-{
-    celix_status_t status = CELIX_SUCCESS;
-
-    free((*admin)->ip);
-    free((*admin)->port);
-    free(*admin);
-
-    //TODO destroy exports/imports
-
-    *admin = NULL;
-
-    return status;
-}
-
-
-celix_status_t remoteServiceAdmin_stop(remote_service_admin_pt admin) {
-    celix_status_t status = CELIX_SUCCESS;
-
-    celixThreadMutex_lock(&admin->exportedServicesLock);
-
-    hash_map_iterator_pt iter = hashMapIterator_create(admin->exportedServices);
-    while (hashMapIterator_hasNext(iter)) {
-        array_list_pt exports = hashMapIterator_nextValue(iter);
-        int i;
-        for (i = 0; i < arrayList_size(exports); i++) {
-            export_registration_pt export = arrayList_get(exports, i);
-            if (export != NULL) {
-                exportRegistration_stop(export);
-                exportRegistration_destroy(export);
-            }
-        }
-        arrayList_destroy(exports);
-    }
-    hashMapIterator_destroy(iter);
-    celixThreadMutex_unlock(&admin->exportedServicesLock);
-
-    celixThreadMutex_lock(&admin->importedServicesLock);
-    int i;
-    int size = arrayList_size(admin->importedServices);
-    for (i = 0; i < size ; i += 1) {
-        import_registration_pt import = arrayList_get(admin->importedServices, i);
-        if (import != NULL) {
-            importRegistration_stop(import);
-            importRegistration_destroy(import);
-        }
-    }
-    celixThreadMutex_unlock(&admin->importedServicesLock);
-
-    if (admin->ctx != NULL) {
-        logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Stopping webserver...");
-        mg_stop(admin->ctx);
-        admin->ctx = NULL;
-    }
-
-    hashMap_destroy(admin->exportedServices, false, false);
-    arrayList_destroy(admin->importedServices);
-
-    logHelper_stop(admin->loghelper);
-    logHelper_destroy(&admin->loghelper);
-
-    return status;
-}
-
-/**
- * Request: http://host:port/services/{service}/{request}
- */
-//void *remoteServiceAdmin_callback(enum mg_event event, struct mg_connection *conn, const struct mg_request_info *request_info) {
-
-celix_status_t importRegistration_getFactory(import_registration_pt import, service_factory_pt *factory);
-
-static int remoteServiceAdmin_callback(struct mg_connection *conn) {
-    int result = 1; // zero means: let civetweb handle it further, any non-zero value means it is handled by us...
-
-    const struct mg_request_info *request_info = mg_get_request_info(conn);
-    if (request_info->uri != NULL) {
-        remote_service_admin_pt rsa = request_info->user_data;
-
-
-        if (strncmp(request_info->uri, "/service/", 9) == 0 && strcmp("POST", request_info->request_method) == 0) {
-
-            // uri = /services/myservice/call
-            const char *uri = request_info->uri;
-            // rest = myservice/call
-
-            const char *rest = uri+9;
-            char *interfaceStart = strchr(rest, '/');
-            int pos = interfaceStart - rest;
-            char service[pos+1];
-            strncpy(service, rest, pos);
-            service[pos] = '\0';
-            unsigned long serviceId = strtoul(service,NULL,10);
-
-            celixThreadMutex_lock(&rsa->exportedServicesLock);
-
-            //find endpoint
-            export_registration_pt export = NULL;
-            hash_map_iterator_pt iter = hashMapIterator_create(rsa->exportedServices);
-            while (hashMapIterator_hasNext(iter)) {
-                hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
-                array_list_pt exports = hashMapEntry_getValue(entry);
-                int expIt = 0;
-                for (expIt = 0; expIt < arrayList_size(exports); expIt++) {
-                    export_registration_pt check = arrayList_get(exports, expIt);
-                    export_reference_pt  ref = NULL;
-                    exportRegistration_getExportReference(check, &ref);
-                    endpoint_description_pt  checkEndpoint = NULL;
-                    exportReference_getExportedEndpoint(ref, &checkEndpoint);
-                    if (serviceId == checkEndpoint->serviceId) {
-                        export = check;
-                        free(ref);
-                        break;
-                    }
-                    free(ref);
-                }
-            }
-            hashMapIterator_destroy(iter);
-
-            if (export != NULL) {
-
-                uint64_t datalength = request_info->content_length;
-                char* data = malloc(datalength + 1);
-                mg_read(conn, data, datalength);
-                data[datalength] = '\0';
-
-                char *response = NULL;
-                int responceLength = 0;
-                int rc = exportRegistration_call(export, data, -1, &response, &responceLength);
-                if (rc != CELIX_SUCCESS) {
-                    RSA_LOG_ERROR(rsa, "Error trying to invoke remove service, got error %i\n", rc);
-                }
-
-                if (rc == CELIX_SUCCESS && response != NULL) {
-                    mg_write(conn, data_response_headers, strlen(data_response_headers));
-                    mg_write(conn, response, strlen(response));
-                    free(response);
-                } else {
-                    mg_write(conn, no_content_response_headers, strlen(no_content_response_headers));
-                }
-                result = 1;
-
-                free(data);
-            } else {
-                result = 0;
-                RSA_LOG_WARNING(rsa, "NO export registration found for service id %lu", serviceId);
-            }
-
-            celixThreadMutex_unlock(&rsa->exportedServicesLock);
-
-        }
-    }
-
-    return result;
-}
-
-celix_status_t remoteServiceAdmin_exportService(remote_service_admin_pt admin, char *serviceId, properties_pt properties, array_list_pt *registrations) {
-    celix_status_t status;
-
-    arrayList_create(registrations);
-    array_list_pt references = NULL;
-    service_reference_pt reference = NULL;
-    char filter [256];
-
-    snprintf(filter, 256, "(%s=%s)", (char *)OSGI_FRAMEWORK_SERVICE_ID, serviceId);
-
-    status = bundleContext_getServiceReferences(admin->context, NULL, filter, &references);
-
-    logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "RSA: exportService called for serviceId %s", serviceId);
-
-    int i;
-    int size = arrayList_size(references);
-    for (i = 0; i < size; i += 1) {
-        if (i == 0) {
-            reference = arrayList_get(references, i);
-        } else {
-            bundleContext_ungetServiceReference(admin->context, arrayList_get(references, i));
-        }
-    }
-    arrayList_destroy(references);
-
-    if (reference == NULL) {
-        logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "ERROR: expected a reference for service id %s.", serviceId);
-        status = CELIX_ILLEGAL_STATE;
-    }
-
-    const char *exports = NULL;
-    const char *provided = NULL;
-    if (status == CELIX_SUCCESS) {
-        serviceReference_getProperty(reference, (char *) OSGI_RSA_SERVICE_EXPORTED_INTERFACES, &exports);
-        serviceReference_getProperty(reference, (char *) OSGI_FRAMEWORK_OBJECTCLASS, &provided);
-
-        if (exports == NULL || provided == NULL || strcmp(exports, provided) != 0) {
-            logHelper_log(admin->loghelper, OSGI_LOGSERVICE_WARNING, "RSA: No Services to export.");
-            status = CELIX_ILLEGAL_STATE;
-        } else {
-            logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Export service (%s)", provided);
-        }
-    }
-
-    if (status == CELIX_SUCCESS) {
-        const char *interface = provided;
-        endpoint_description_pt endpoint = NULL;
-        export_registration_pt registration = NULL;
-
-        remoteServiceAdmin_createEndpointDescription(admin, reference, properties, (char*)interface, &endpoint);
-        //TODO precheck if descriptor exists
-        status = exportRegistration_create(admin->loghelper, reference, endpoint, admin->context, &registration);
-        if (status == CELIX_SUCCESS) {
-            status = exportRegistration_start(registration);
-            if (status == CELIX_SUCCESS) {
-                arrayList_add(*registrations, registration);
-            }
-        }
-    }
-
-
-    if (status == CELIX_SUCCESS) {
-        celixThreadMutex_lock(&admin->exportedServicesLock);
-        hashMap_put(admin->exportedServices, reference, *registrations);
-        celixThreadMutex_unlock(&admin->exportedServicesLock);
-    }
-    else{
-    	arrayList_destroy(*registrations);
-    	*registrations = NULL;
-    }
-
-    return status;
-}
-
-celix_status_t remoteServiceAdmin_removeExportedService(remote_service_admin_pt admin, export_registration_pt registration) {
-    celix_status_t status;
-
-    logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA_DFI: Removing exported service");
-
-    export_reference_pt  ref = NULL;
-    status = exportRegistration_getExportReference(registration, &ref);
-
-    if (status == CELIX_SUCCESS && ref != NULL) {
-    	service_reference_pt servRef;
-        celixThreadMutex_lock(&admin->exportedServicesLock);
-    	exportReference_getExportedService(ref, &servRef);
-
-    	array_list_pt exports = (array_list_pt)hashMap_remove(admin->exportedServices, servRef);
-    	if(exports!=NULL){
-    		arrayList_destroy(exports);
-    	}
-
-        exportRegistration_close(registration);
-        exportRegistration_destroy(registration);
-
-        celixThreadMutex_unlock(&admin->exportedServicesLock);
-
-        free(ref);
-
-    } else {
-    	logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "Cannot find reference for registration");
-    }
-
-    return status;
-}
-
-static celix_status_t remoteServiceAdmin_createEndpointDescription(remote_service_admin_pt admin, service_reference_pt reference, properties_pt props, char *interface, endpoint_description_pt *endpoint) {
-
-    celix_status_t status = CELIX_SUCCESS;
-    properties_pt endpointProperties = properties_create();
-
-
-    unsigned int size = 0;
-    char **keys;
-
-    serviceReference_getPropertyKeys(reference, &keys, &size);
-    for (int i = 0; i < size; i++) {
-        char *key = keys[i];
-        const char *value = NULL;
-
-        if (serviceReference_getProperty(reference, key, &value) == CELIX_SUCCESS
-            && strcmp(key, (char*) OSGI_RSA_SERVICE_EXPORTED_INTERFACES) != 0
-            && strcmp(key, (char*) OSGI_FRAMEWORK_OBJECTCLASS) != 0) {
-            properties_set(endpointProperties, key, value);
-        }
-    }
-
-    hash_map_entry_pt entry = hashMap_getEntry(endpointProperties, (void *) OSGI_FRAMEWORK_SERVICE_ID);
-
-    char* key = hashMapEntry_getKey(entry);
-    char *serviceId = (char *) hashMap_remove(endpointProperties, (void *) OSGI_FRAMEWORK_SERVICE_ID);
-    const char *uuid = NULL;
-
-    char buf[512];
-    snprintf(buf, 512,  "/service/%s/%s", serviceId, interface);
-
-    char url[1024];
-    snprintf(url, 1024, "http://%s:%s%s", admin->ip, admin->port, buf);
-
-    uuid_t endpoint_uid;
-    uuid_generate(endpoint_uid);
-    char endpoint_uuid[37];
-    uuid_unparse_lower(endpoint_uid, endpoint_uuid);
-
-    bundleContext_getProperty(admin->context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &uuid);
-    properties_set(endpointProperties, (char*) OSGI_RSA_ENDPOINT_FRAMEWORK_UUID, uuid);
-    properties_set(endpointProperties, (char*) OSGI_FRAMEWORK_OBJECTCLASS, interface);
-    properties_set(endpointProperties, (char*) OSGI_RSA_ENDPOINT_SERVICE_ID, serviceId);
-    properties_set(endpointProperties, (char*) OSGI_RSA_ENDPOINT_ID, endpoint_uuid);
-    properties_set(endpointProperties, (char*) OSGI_RSA_SERVICE_IMPORTED, "true");
-    properties_set(endpointProperties, (char*) OSGI_RSA_SERVICE_IMPORTED_CONFIGS, (char*) CONFIGURATION_TYPE);
-    properties_set(endpointProperties, (char*) ENDPOINT_URL, url);
-
-    if (props != NULL) {
-        hash_map_iterator_pt propIter = hashMapIterator_create(props);
-        while (hashMapIterator_hasNext(propIter)) {
-    	    hash_map_entry_pt entry = hashMapIterator_nextEntry(propIter);
-    	    properties_set(endpointProperties, (char*)hashMapEntry_getKey(entry), (char*)hashMapEntry_getValue(entry));
-        }
-        hashMapIterator_destroy(propIter);
-    }
-
-    *endpoint = calloc(1, sizeof(**endpoint));
-    if (!*endpoint) {
-        status = CELIX_ENOMEM;
-    } else {
-        (*endpoint)->id = (char*)properties_get(endpointProperties, (char*) OSGI_RSA_ENDPOINT_ID);
-        const char *serviceId = NULL;
-        serviceReference_getProperty(reference, (char*) OSGI_FRAMEWORK_SERVICE_ID, &serviceId);
-        (*endpoint)->serviceId = strtoull(serviceId, NULL, 0);
-        (*endpoint)->frameworkUUID = (char*) properties_get(endpointProperties, (char*) OSGI_RSA_ENDPOINT_FRAMEWORK_UUID);
-        (*endpoint)->service = strndup(interface, 1024*10);
-        (*endpoint)->properties = endpointProperties;
-    }
-
-    free(key);
-    free(serviceId);
-    free(keys);
-
-    return status;
-}
-
-static celix_status_t remoteServiceAdmin_getIpAdress(char* interface, char** ip) {
-    celix_status_t status = CELIX_BUNDLE_EXCEPTION;
-
-    struct ifaddrs *ifaddr, *ifa;
-    char host[NI_MAXHOST];
-
-    if (getifaddrs(&ifaddr) != -1)
-    {
-        for (ifa = ifaddr; ifa != NULL && status != CELIX_SUCCESS; ifa = ifa->ifa_next)
-        {
-            if (ifa->ifa_addr == NULL)
-                continue;
-
-            if ((getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0) && (ifa->ifa_addr->sa_family == AF_INET)) {
-                if (interface == NULL) {
-                    *ip = strdup(host);
-                    status = CELIX_SUCCESS;
-                }
-                else if (strcmp(ifa->ifa_name, interface) == 0) {
-                    *ip = strdup(host);
-                    status = CELIX_SUCCESS;
-                }
-            }
-        }
-
-        freeifaddrs(ifaddr);
-    }
-
-    return status;
-}
-
-
-celix_status_t remoteServiceAdmin_destroyEndpointDescription(endpoint_description_pt *description)
-{
-    celix_status_t status = CELIX_SUCCESS;
-
-    properties_destroy((*description)->properties);
-    free((*description)->service);
-    free(*description);
-
-    return status;
-}
-
-
-celix_status_t remoteServiceAdmin_getExportedServices(remote_service_admin_pt admin, array_list_pt *services) {
-    celix_status_t status = CELIX_SUCCESS;
-    return status;
-}
-
-celix_status_t remoteServiceAdmin_getImportedEndpoints(remote_service_admin_pt admin, array_list_pt *services) {
-    celix_status_t status = CELIX_SUCCESS;
-    return status;
-}
-
-celix_status_t remoteServiceAdmin_importService(remote_service_admin_pt admin, endpoint_description_pt endpointDescription, import_registration_pt *out) {
-    celix_status_t status = CELIX_SUCCESS;
-    import_registration_pt import = NULL;
-
-    const char *objectClass = properties_get(endpointDescription->properties, "objectClass");
-    const char *serviceVersion = properties_get(endpointDescription->properties, (char*) CELIX_FRAMEWORK_SERVICE_VERSION);
-
-    logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Import service %s", endpointDescription->service);
-    logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "Registering service factory (proxy) for service '%s'\n", objectClass);
-
-    if (objectClass != NULL) {
-        status = importRegistration_create(admin->context, endpointDescription, objectClass, serviceVersion, &import);
-    }
-    if (status == CELIX_SUCCESS && import != NULL) {
-        importRegistration_setSendFn(import, (send_func_type) remoteServiceAdmin_send, admin);
-    }
-
-    if (status == CELIX_SUCCESS && import != NULL) {
-        status = importRegistration_start(import);
-    }
-
-    celixThreadMutex_lock(&admin->importedServicesLock);
-    arrayList_add(admin->importedServices, import);
-    celixThreadMutex_unlock(&admin->importedServicesLock);
-
-    if (status == CELIX_SUCCESS) {
-        *out = import;
-    }
-
-    return status;
-}
-
-
-celix_status_t remoteServiceAdmin_removeImportedService(remote_service_admin_pt admin, import_registration_pt registration) {
-    celix_status_t status = CELIX_SUCCESS;
-    logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA_DFI: Removing imported service");
-
-    celixThreadMutex_lock(&admin->importedServicesLock);
-    int i;
-    int size = arrayList_size(admin->importedServices);
-    import_registration_pt  current  = NULL;
-    for (i = 0; i < size; i += 1) {
-        current = arrayList_get(admin->importedServices, i);
-        if (current == registration) {
-            arrayList_remove(admin->importedServices, i);
-            importRegistration_close(current);
-            importRegistration_destroy(current);
-            break;
-        }
-    }
-    celixThreadMutex_unlock(&admin->importedServicesLock);
-
-    return status;
-}
-
-
-static celix_status_t remoteServiceAdmin_send(void *handle, endpoint_description_pt endpointDescription, char *request, char **reply, int* replyStatus) {
-    remote_service_admin_pt  rsa = handle;
-    struct post post;
-    post.readptr = request;
-    post.size = strlen(request);
-
-    struct get get;
-    get.size = 0;
-    get.writeptr = malloc(1);
-
-    char *serviceUrl = (char*)properties_get(endpointDescription->properties, (char*) ENDPOINT_URL);
-    char url[256];
-    snprintf(url, 256, "%s", serviceUrl);
-
-    // assume the default timeout
-    int timeout = DEFAULT_TIMEOUT;
-
-    const char *timeoutStr = NULL;
-    // Check if the endpoint has a timeout, if so, use it.
-    timeoutStr = (char*) properties_get(endpointDescription->properties, (char*) OSGI_RSA_REMOTE_PROXY_TIMEOUT);
-    if (timeoutStr == NULL) {
-        // If not, get the global variable and use that one.
-        bundleContext_getProperty(rsa->context, (char*) OSGI_RSA_REMOTE_PROXY_TIMEOUT, &timeoutStr);
-    }
-
-    // Update timeout if a property is used to set it.
-    if (timeoutStr != NULL) {
-        timeout = atoi(timeoutStr);
-    }
-
-    celix_status_t status = CELIX_SUCCESS;
-    CURL *curl;
-    CURLcode res;
-
-    curl = curl_easy_init();
-    if(!curl) {
-        status = CELIX_ILLEGAL_STATE;
-    } else {
-        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
-        curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
-        curl_easy_setopt(curl, CURLOPT_URL, url);
-        curl_easy_setopt(curl, CURLOPT_POST, 1L);
-        curl_easy_setopt(curl, CURLOPT_READFUNCTION, remoteServiceAdmin_readCallback);
-        curl_easy_setopt(curl, CURLOPT_READDATA, &post);
-        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, remoteServiceAdmin_write);
-        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&get);
-        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (curl_off_t)post.size);
-        logHelper_log(rsa->loghelper, OSGI_LOGSERVICE_DEBUG, "RSA: Performing curl post\n");
-        res = curl_easy_perform(curl);
-
-        *reply = get.writeptr;
-        *replyStatus = res;
-
-        curl_easy_cleanup(curl);
-    }
-
-    return status;
-}
-
-static size_t remoteServiceAdmin_readCallback(void *ptr, size_t size, size_t nmemb, void *userp) {
-    struct post *post = userp;
-
-    if (post->size) {
-        *(char *) ptr = post->readptr[0];
-        post->readptr++;
-        post->size--;
-        return 1;
-    }
-
-    return 0;
-}
-
-static size_t remoteServiceAdmin_write(void *contents, size_t size, size_t nmemb, void *userp) {
-    size_t realsize = size * nmemb;
-    struct get *mem = (struct get *)userp;
-
-    mem->writeptr = realloc(mem->writeptr, mem->size + realsize + 1);
-    if (mem->writeptr == NULL) {
-        /* out of memory! */
-        printf("not enough memory (realloc returned NULL)");
-        exit(EXIT_FAILURE);
-    }
-
-    memcpy(&(mem->writeptr[mem->size]), contents, realsize);
-    mem->size += realsize;
-    mem->writeptr[mem->size] = 0;
-
-    return realsize;
-}
-
-
-static void remoteServiceAdmin_log(remote_service_admin_pt admin, int level, const char *file, int line, const char *msg, ...) {
-    va_list ap;
-    va_start(ap, msg);
-    int levels[5] = {0, OSGI_LOGSERVICE_ERROR, OSGI_LOGSERVICE_WARNING, OSGI_LOGSERVICE_INFO, OSGI_LOGSERVICE_DEBUG};
-
-    char buf1[256];
-    snprintf(buf1, 256, "FILE:%s, LINE:%i, MSG:", file, line);
-
-    char buf2[256];
-    vsnprintf(buf2, 256, msg, ap);
-    logHelper_log(admin->loghelper, levels[level], "%s%s", buf1, buf2);
-    va_end(ap);
-}

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_dfi.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_dfi.h b/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_dfi.h
deleted file mode 100644
index 8b282f1..0000000
--- a/remote_services/remote_service_admin_dfi/rsa/src/remote_service_admin_dfi.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-/*
- * remote_service_admin_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 "bundle_context.h"
-#include "endpoint_description.h"
-
-//typedef struct remote_service_admin *remote_service_admin_pt;
-
-celix_status_t remoteServiceAdmin_create(bundle_context_pt context, remote_service_admin_pt *admin);
-celix_status_t remoteServiceAdmin_destroy(remote_service_admin_pt *admin);
-
-celix_status_t remoteServiceAdmin_stop(remote_service_admin_pt admin);
-
-celix_status_t remoteServiceAdmin_exportService(remote_service_admin_pt admin, char *serviceId, properties_pt properties, array_list_pt *registrations);
-celix_status_t remoteServiceAdmin_removeExportedService(remote_service_admin_pt admin, export_registration_pt registration);
-celix_status_t remoteServiceAdmin_getExportedServices(remote_service_admin_pt admin, array_list_pt *services);
-celix_status_t remoteServiceAdmin_getImportedEndpoints(remote_service_admin_pt admin, array_list_pt *services);
-celix_status_t remoteServiceAdmin_importService(remote_service_admin_pt admin, endpoint_description_pt endpoint, import_registration_pt *registration);
-celix_status_t remoteServiceAdmin_removeImportedService(remote_service_admin_pt admin, import_registration_pt registration);
-
-
-celix_status_t exportReference_getExportedEndpoint(export_reference_pt reference, endpoint_description_pt *endpoint);
-celix_status_t exportReference_getExportedService(export_reference_pt reference, service_reference_pt *service);
-
-celix_status_t importReference_getImportedEndpoint(import_reference_pt reference);
-celix_status_t importReference_getImportedService(import_reference_pt reference);
-
-celix_status_t remoteServiceAdmin_destroyEndpointDescription(endpoint_description_pt *description);
-
-#endif /* REMOTE_SERVICE_ADMIN_HTTP_IMPL_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa_tst/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa_tst/CMakeLists.txt b/remote_services/remote_service_admin_dfi/rsa_tst/CMakeLists.txt
deleted file mode 100644
index b3b272e..0000000
--- a/remote_services/remote_service_admin_dfi/rsa_tst/CMakeLists.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-include_directories(
-    ${PROJECT_SOURCE_DIR}/remote_services/remote_service_admin/public/include
-    ${PROJECT_SOURCE_DIR}/remote_services/examples/calculator_service/public/include
-    bundle
-)
-
-add_subdirectory(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" "${PROJECT_BINARY_DIR}/dfi")
-
-add_executable(test_rsa_dfi
-    run_tests.cpp
-    rsa_tests.cpp
-    rsa_client_server_tests.cpp
-)
-target_link_libraries(test_rsa_dfi PRIVATE Celix::framework ${CURL_LIBRARIES} ${CPPUTEST_LIBRARY} remote_service_admin_common)
-
-get_property(rsa_bundle_file TARGET remote_service_admin_dfi PROPERTY BUNDLE_FILE)
-get_property(calc_bundle_file TARGET calculator PROPERTY BUNDLE_FILE)
-get_property(calculator_shell_bundle_file TARGET calculator_shell PROPERTY BUNDLE_FILE)
-get_property(discovery_configured_bundle_file TARGET discovery_configured PROPERTY BUNDLE_FILE)
-get_property(topology_manager_bundle_file TARGET topology_manager PROPERTY BUNDLE_FILE)
-get_property(tst_bundle_file TARGET rsa_dfi_tst_bundle PROPERTY BUNDLE_FILE)
-
-configure_file(config.properties.in config.properties)
-configure_file(client.properties.in client.properties)
-configure_file(server.properties.in server.properties)
-
-add_dependencies(test_rsa_dfi remote_service_admin_dfi calculator)
-
-add_test(NAME run_test_rsa_dfi COMMAND test_rsa_dfi)
-SETUP_TARGET_FOR_COVERAGE(test_rsa_dfi_cov test_rsa_dfi ${CMAKE_BINARY_DIR}/coverage/test_rsa_dfi/test_rsa_dfi)
-

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa_tst/bundle/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa_tst/bundle/CMakeLists.txt b/remote_services/remote_service_admin_dfi/rsa_tst/bundle/CMakeLists.txt
deleted file mode 100644
index 65b18e8..0000000
--- a/remote_services/remote_service_admin_dfi/rsa_tst/bundle/CMakeLists.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-add_bundle(rsa_dfi_tst_bundle
-    VERSION 0.0.1
-    SOURCES
-        tst_activator.c
-)
-
-bundle_files(rsa_dfi_tst_bundle
-    ${PROJECT_SOURCE_DIR}/remote_services/examples/calculator_api/include/org.apache.celix.calc.api.Calculator2.descriptor
-    DESTINATION .
-)
-target_include_directories(rsa_dfi_tst_bundle PRIVATE calculator)
-target_link_libraries(rsa_dfi_tst_bundle PRIVATE ${CPPUTEST_LIBRARY} calculator_api)

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa_tst/bundle/tst_activator.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa_tst/bundle/tst_activator.c b/remote_services/remote_service_admin_dfi/rsa_tst/bundle/tst_activator.c
deleted file mode 100644
index f5838f8..0000000
--- a/remote_services/remote_service_admin_dfi/rsa_tst/bundle/tst_activator.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <service_tracker_customizer.h>
-#include <service_tracker.h>
-
-#include "bundle_activator.h"
-#include "bundle_context.h"
-#include "service_registration.h"
-#include "service_reference.h"
-#include "celix_errno.h"
-
-#include "tst_service.h"
-#include "calculator_service.h"
-
-
-struct activator {
-	bundle_context_pt context;
-	struct tst_service serv;
-	service_registration_pt  reg;
-
-	service_tracker_customizer_pt cust;
-	service_tracker_pt tracker;
-	calculator_service_pt calc;
-};
-
-static celix_status_t addCalc(void * handle, service_reference_pt reference, void * service);
-static celix_status_t removeCalc(void * handle, service_reference_pt reference, void * service);
-static int test(void *handle);
-
-celix_status_t bundleActivator_create(bundle_context_pt context, void **out) {
-	celix_status_t status = CELIX_SUCCESS;
-	struct activator *act = calloc(1, sizeof(*act));
-	if (act != NULL) {
-		act->context = context;
-		act->serv.handle = act;
-		act->serv.test = test;
-
-		status = serviceTrackerCustomizer_create(act, NULL, addCalc, NULL, removeCalc, &act->cust);
-		status = CELIX_DO_IF(status, serviceTracker_create(context, CALCULATOR2_SERVICE, act->cust, &act->tracker));
-
-	} else {
-		status = CELIX_ENOMEM;
-	}
-
-	if (status == CELIX_SUCCESS) {
-		*out = act;
-	} else if (act != NULL) {
-		if (act->cust != NULL) {
-			free(act->cust);
-			act->cust = NULL;
-		}
-		if (act->tracker != NULL) {
-			serviceTracker_destroy(act->tracker);
-			act->tracker = NULL;
-		}
-		free(act);
-	}
-
-	return CELIX_SUCCESS;
-}
-
-static celix_status_t addCalc(void * handle, service_reference_pt reference, void * service) {
-	celix_status_t status = CELIX_SUCCESS;
-	struct activator * act = handle;
-	act->calc = service;
-	return status;
-}
-
-static celix_status_t removeCalc(void * handle, service_reference_pt reference, void * service) {
-	celix_status_t status = CELIX_SUCCESS;
-	struct activator * act = handle;
-	if (act->calc == service) {
-		act->calc = NULL;
-	}
-	return status;
-
-}
-
-celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
-    celix_status_t status = CELIX_SUCCESS;
-	struct activator * act = userData;
-
-	act->reg = NULL;
-	status = bundleContext_registerService(context, (char *)TST_SERVICE_NAME, &act->serv, NULL, &act->reg);
-
-	status = CELIX_DO_IF(status, serviceTracker_open(act->tracker));
-
-
-	return status;
-}
-
-
-celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) {
-    celix_status_t status = CELIX_SUCCESS;
-	struct activator * act = userData;
-
-	status = serviceRegistration_unregister(act->reg);
-	status = CELIX_DO_IF(status, serviceTracker_close(act->tracker));
-
-	return status;
-}
-
-celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) {
-	struct activator *act = userData;
-	if (act != NULL) {
-		if (act->tracker != NULL) {
-			serviceTracker_destroy(act->tracker);
-			act->tracker = NULL;
-		}
-		free(act);
-	}
-	return CELIX_SUCCESS;
-}
-
-static int test(void *handle) {
-	int status = 0;
-	struct activator *act = handle;
-
-	double result = -1.0;
-
-    int rc = 1;
-    if (act->calc != NULL) {
-         rc = act->calc->sqrt(act->calc->calculator, 4, &result);
-        printf("calc result is %f\n", result);
-    } else {
-        printf("calc not ready\n");
-    }
-
-	if (rc != 0 || result != 2.0) {
-		status = 1;
-	}
-	return status;
-}

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa_tst/bundle/tst_service.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa_tst/bundle/tst_service.h b/remote_services/remote_service_admin_dfi/rsa_tst/bundle/tst_service.h
deleted file mode 100644
index c8ca2e7..0000000
--- a/remote_services/remote_service_admin_dfi/rsa_tst/bundle/tst_service.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#ifndef CELIX_TST_SERVICE_H
-#define CELIX_TST_SERVICE_H
-
-#define TST_SERVICE_NAME "tst_service"
-
-struct tst_service {
-    void *handle;
-    int (*test)(void *handle);
-};
-
-typedef struct tst_service *tst_service_pt;
-
-#endif //CELIX_TST_SERVICE_H

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa_tst/client.properties.in
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa_tst/client.properties.in b/remote_services/remote_service_admin_dfi/rsa_tst/client.properties.in
deleted file mode 100644
index a9a06fb..0000000
--- a/remote_services/remote_service_admin_dfi/rsa_tst/client.properties.in
+++ /dev/null
@@ -1,8 +0,0 @@
-cosgi.auto.start.1=@rsa_bundle_file@ @calculator_shell_bundle_file@ @discovery_configured_bundle_file@ @topology_manager_bundle_file@ @tst_bundle_file@
-LOGHELPER_ENABLE_STDOUT_FALLBACK=true
-RSA_PORT=50881
-DISCOVERY_CFG_SERVER_PORT=50991
-DISCOVERY_CFG_POLL_ENDPOINTS=http://127.0.0.1:50992/org.apache.celix.discovery.configured
-org.osgi.framework.storage.clean=onFirstInit
-org.osgi.framework.storage=.cacheClient
-DISCOVERY_CFG_POLL_INTERVAL=1
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa_tst/config.properties.in
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa_tst/config.properties.in b/remote_services/remote_service_admin_dfi/rsa_tst/config.properties.in
deleted file mode 100644
index 5776ad8..0000000
--- a/remote_services/remote_service_admin_dfi/rsa_tst/config.properties.in
+++ /dev/null
@@ -1,20 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-cosgi.auto.start.1=@rsa_bundle_file@ @calc_bundle_file@
-LOGHELPER_ENABLE_STDOUT_FALLBACK=true
-org.osgi.framework.storage.clean=onFirstInit
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa_tst/rsa_client_server_tests.cpp
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa_tst/rsa_client_server_tests.cpp b/remote_services/remote_service_admin_dfi/rsa_tst/rsa_client_server_tests.cpp
deleted file mode 100644
index d091746..0000000
--- a/remote_services/remote_service_admin_dfi/rsa_tst/rsa_client_server_tests.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#include <CppUTest/TestHarness.h>
-#include <remote_constants.h>
-#include <constants.h>
-#include <tst_service.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"
-
-    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 rc;
-        service_reference_pt ref = NULL;
-        tst_service_pt tst = NULL;
-        int retries = 4;
-
-        while (ref == NULL && retries > 0) {
-            printf("Waiting for service .. %d\n", retries);
-            rc = bundleContext_getServiceReference(clientContext, (char *) TST_SERVICE_NAME, &ref);
-            usleep(1000000);
-            --retries;
-        }
-
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-        CHECK(ref != NULL);
-
-        rc = bundleContext_getService(clientContext, ref, (void **)&tst);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-        CHECK(tst != NULL);
-
-        rc = tst->test(tst->handle);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        bool result;
-        bundleContext_ungetService(clientContext, ref, &result);
-        bundleContext_ungetServiceReference(clientContext, ref);
-    }
-
-}
-
-
-TEST_GROUP(RsaDfiClientServerTests) {
-    void setup() {
-        setupFm();
-    }
-
-    void teardown() {
-        teardownFm();
-    }
-};
-
-TEST(RsaDfiClientServerTests, Test1) {
-    test1();
-}

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa_tst/rsa_tests.cpp
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa_tst/rsa_tests.cpp b/remote_services/remote_service_admin_dfi/rsa_tst/rsa_tests.cpp
deleted file mode 100644
index 8b7988d..0000000
--- a/remote_services/remote_service_admin_dfi/rsa_tst/rsa_tests.cpp
+++ /dev/null
@@ -1,234 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#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 "celix_launcher.h"
-#include "framework.h"
-#include "remote_service_admin.h"
-#include "calculator_service.h"
-
-
-    static framework_pt framework = NULL;
-    static bundle_context_pt context = NULL;
-
-    static service_reference_pt rsaRef = NULL;
-    static remote_service_admin_service_pt rsa = NULL;
-
-    static service_reference_pt calcRef = NULL;
-    static calculator_service_pt calc = NULL;
-
-    static void setupFm(void) {
-        int rc = 0;
-
-        rc = celixLauncher_launch("config.properties", &framework);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        bundle_pt bundle = NULL;
-        rc = framework_getFrameworkBundle(framework, &bundle);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        rc = bundle_getContext(bundle, &context);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        rc = bundleContext_getServiceReference(context, (char *)OSGI_RSA_REMOTE_SERVICE_ADMIN, &rsaRef);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-        CHECK(rsaRef != NULL);
-
-        rc = bundleContext_getService(context, rsaRef, (void **)&rsa);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        rc = bundleContext_getServiceReference(context, (char *)CALCULATOR2_SERVICE, &calcRef);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-        CHECK(calcRef != NULL);
-
-        rc = bundleContext_getService(context, calcRef, (void **)&calc);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-    }
-
-    static void teardownFm(void) {
-        int rc = 0;
-        rc = bundleContext_ungetService(context, rsaRef, NULL);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        rc = bundleContext_ungetServiceReference(context, rsaRef);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        rc = bundleContext_ungetService(context, calcRef, NULL);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        rc = bundleContext_ungetServiceReference(context, calcRef);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        celixLauncher_stop(framework);
-        celixLauncher_waitForShutdown(framework);
-        celixLauncher_destroy(framework);
-
-        rsaRef = NULL;
-        rsa = NULL;
-        calcRef = NULL;
-        calc = NULL;
-        context = NULL;
-        framework = NULL;
-    }
-
-    static void testServices(void) {
-        int rc = 0;
-        array_list_pt exported = NULL;
-        array_list_pt imported = NULL;
-        arrayList_create(&exported);
-        arrayList_create(&imported);
-
-        rc = rsa->getExportedServices(rsa->admin, &exported);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-        CHECK_EQUAL(0, arrayList_size(exported));
-
-        rc = rsa->getImportedEndpoints(rsa->admin, &imported);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-        CHECK_EQUAL(0, arrayList_size(imported));
-
-        double result = 0;
-        rc = calc->add(calc->calculator, 2.0, 5.0, &result);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-        CHECK_EQUAL(7.0, result);
-
-        arrayList_destroy(imported);
-        arrayList_destroy(exported);
-    }
-
-    static void testExportService(void) {
-        int rc = 0;
-        const char *calcId = NULL;
-        array_list_pt regs = NULL;
-
-        rc = serviceReference_getProperty(calcRef, (char *)"service.id", &calcId);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        rc = rsa->exportService(rsa->admin, (char*)calcId, NULL, &regs);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        CHECK_EQUAL(1, arrayList_size(regs));
-
-        rc = rsa->exportRegistration_close(rsa->admin,(export_registration_pt)(arrayList_get(regs,0)));
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-    }
-
-    static void testImportService(void) {
-        int rc = 0;
-        import_registration_pt reg = NULL;
-        endpoint_description_pt endpoint = NULL;
-
-        properties_pt props = properties_create();
-        properties_set(props, (char *)OSGI_RSA_ENDPOINT_SERVICE_ID, (char *)"42");
-        properties_set(props, (char *)OSGI_RSA_ENDPOINT_FRAMEWORK_UUID, (char *)"eec5404d-51d0-47ef-8d86-c825a8beda42");
-        properties_set(props, (char *)OSGI_RSA_ENDPOINT_ID, (char *)"eec5404d-51d0-47ef-8d86-c825a8beda42-42");
-        properties_set(props, (char *)OSGI_FRAMEWORK_OBJECTCLASS,(char *)"org.apache.celix.Example");
-        properties_set(props, (char *)"service.version",(char *)"1.0.0"); //TODO find out standard in osgi spec
-
-        rc = endpointDescription_create(props, &endpoint);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        rc = rsa->importService(rsa->admin, endpoint, &reg);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-        CHECK(reg != NULL);
-
-        service_reference_pt ref = NULL;
-        rc = bundleContext_getServiceReference(context, (char *)"org.apache.celix.Example", &ref);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-        CHECK(ref != NULL);
-
-        rc = bundleContext_ungetServiceReference(context, ref);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        rc = endpointDescription_destroy(endpoint);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        /* Cannot test. uses requesting bundles descriptor
-        void *service = NULL;
-        rc = bundleContext_getService(context, ref, &service);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-        CHECK(service != NULL);
-         */
-    }
-
-    static void testBundles(void) {
-        array_list_pt bundles = NULL;
-
-        int rc = bundleContext_getBundles(context, &bundles);
-        CHECK_EQUAL(0, rc);
-        CHECK_EQUAL(3, arrayList_size(bundles)); //framework, rsa_dfi & calc
-
-        /*
-        int size = arrayList_size(bundles);
-        int i;
-        for (i = 0; i < size; i += 1) {
-            bundle_pt bundle = NULL;
-            module_pt module = NULL;
-            char *name = NULL;
-
-            bundle = (bundle_pt) arrayList_get(bundles, i);
-            bundle_getCurrentModule(bundle, &module);
-            module_getSymbolicName(module, &name);
-            printf("got bundle with symbolic name '%s'", name);
-        }*/
-
-        arrayList_destroy(bundles);
-    }
-
-}
-
-
-TEST_GROUP(RsaDfiTests) {
-    void setup() {
-        setupFm();
-    }
-
-    void teardown() {
-        teardownFm();
-    }
-};
-
-TEST(RsaDfiTests, InfoTest) {
-    testServices();
-}
-
-TEST(RsaDfiTests, ExportService) {
-    testExportService();
-}
-
-TEST(RsaDfiTests, ImportService) {
-    testImportService();
-}
-
-TEST(RsaDfiTests, TestBundles) {
-    testBundles();
-}

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/rsa_tst/run_tests.cpp
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa_tst/run_tests.cpp b/remote_services/remote_service_admin_dfi/rsa_tst/run_tests.cpp
deleted file mode 100644
index b5fd502..0000000
--- a/remote_services/remote_service_admin_dfi/rsa_tst/run_tests.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#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/27a2aa75/remote_services/remote_service_admin_dfi/rsa_tst/server.properties.in
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/rsa_tst/server.properties.in b/remote_services/remote_service_admin_dfi/rsa_tst/server.properties.in
deleted file mode 100644
index 707c7e6..0000000
--- a/remote_services/remote_service_admin_dfi/rsa_tst/server.properties.in
+++ /dev/null
@@ -1,23 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-cosgi.auto.start.1=@rsa_bundle_file@ @calc_bundle_file@ @discovery_configured_bundle_file@ @topology_manager_bundle_file@
-LOGHELPER_ENABLE_STDOUT_FALLBACK=true
-RSA_PORT=50882
-DISCOVERY_CFG_SERVER_PORT=50992
-org.osgi.framework.storage.clean=onFirstInit
-org.osgi.framework.storage=.cacheServer
-DISCOVERY_CFG_POLL_INTERVAL=1
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/src/dfi_utils.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/src/dfi_utils.c b/remote_services/remote_service_admin_dfi/src/dfi_utils.c
new file mode 100644
index 0000000..631152d
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/src/dfi_utils.c
@@ -0,0 +1,108 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "dfi_utils.h"
+#include <stdlib.h>
+#include <unistd.h>
+
+static celix_status_t dfi_findFileForFramework(bundle_context_pt context, const char *fileName, FILE **out) {
+    celix_status_t  status;
+
+    char pwd[1024];
+    char path[1024];
+    const char *extPath = NULL;
+   
+    status = bundleContext_getProperty(context, "CELIX_FRAMEWORK_EXTENDER_PATH", &extPath);
+    if (status != CELIX_SUCCESS || extPath == NULL) {
+        getcwd(pwd, sizeof(pwd));
+        extPath = pwd;
+    }
+
+    snprintf(path, sizeof(path), "%s/%s", extPath, fileName);
+
+    if (status == CELIX_SUCCESS) {
+        FILE *df = fopen(path, "r");
+        if (df == NULL) {
+            status = CELIX_FILE_IO_EXCEPTION;
+        } else {
+            *out = df;
+        }
+    }
+
+    return status;
+}
+
+static celix_status_t dfi_findFileForBundle(bundle_pt bundle, const char *fileName, FILE **out) {
+    celix_status_t  status;
+
+    //Checking if descriptor is in root dir of bundle
+    char *path = NULL;
+    status = bundle_getEntry(bundle, fileName, &path);
+
+    char metaInfFileName[512];
+    if (status != CELIX_SUCCESS || path == NULL) {
+        free(path);
+        //Checking if descriptor is in META-INF/descriptors
+        snprintf(metaInfFileName, sizeof(metaInfFileName), "META-INF/descriptors/%s", fileName);
+        status = bundle_getEntry(bundle, metaInfFileName, &path);
+    }
+
+    if (status != CELIX_SUCCESS || path == NULL) {
+        free(path);
+        //Checking if descriptor is in META-INF/descriptors/services
+        snprintf(metaInfFileName, sizeof(metaInfFileName), "META-INF/descriptors/services/%s", fileName);
+        status = bundle_getEntry(bundle, metaInfFileName, &path);
+    }
+
+
+    if (status == CELIX_SUCCESS && path != NULL) {
+        FILE *df = fopen(path, "r");
+        if (df == NULL) {
+            status = CELIX_FILE_IO_EXCEPTION;
+        } else {
+            *out = df;
+        }
+
+    }
+
+    free(path);
+    return status;
+}
+
+celix_status_t dfi_findDescriptor(bundle_context_pt context, bundle_pt bundle, const char *name, FILE **out) {
+    celix_status_t  status;
+    char fileName[128];
+
+    snprintf(fileName, 128, "%s.descriptor", name);
+
+    long id;
+    status = bundle_getBundleId(bundle, &id);
+    
+    if (status == CELIX_SUCCESS) {
+        if (id == 0) {
+            //framework bundle
+            status = dfi_findFileForFramework(context, fileName, out);
+        } else {
+            //normal bundle
+            status = dfi_findFileForBundle(bundle, fileName, out);
+        }
+    }
+
+    return status;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/src/dfi_utils.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/src/dfi_utils.h b/remote_services/remote_service_admin_dfi/src/dfi_utils.h
new file mode 100644
index 0000000..cec8aa1
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/src/dfi_utils.h
@@ -0,0 +1,30 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+#ifndef DFI_UTILS_H_
+#define DFI_UTILS_H_
+
+#include "bundle.h"
+#include "bundle_context.h"
+#include <stdio.h>
+#include "celix_errno.h"
+
+
+celix_status_t dfi_findDescriptor(bundle_context_pt context, bundle_pt bundle, const char *name, FILE **out);
+
+#endif

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/src/export_registration_dfi.c
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/src/export_registration_dfi.c b/remote_services/remote_service_admin_dfi/src/export_registration_dfi.c
new file mode 100644
index 0000000..b83b5a8
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/src/export_registration_dfi.c
@@ -0,0 +1,251 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <jansson.h>
+#include <dyn_interface.h>
+#include <json_serializer.h>
+#include <remote_constants.h>
+#include <remote_service_admin.h>
+#include <service_tracker_customizer.h>
+#include <service_tracker.h>
+#include <json_rpc.h>
+#include "constants.h"
+#include "export_registration_dfi.h"
+#include "dfi_utils.h"
+
+struct export_reference {
+    endpoint_description_pt endpoint; //owner
+    service_reference_pt reference;
+};
+
+struct export_registration {
+    bundle_context_pt  context;
+    struct export_reference exportReference;
+    char *servId;
+    dyn_interface_type *intf; //owner
+    service_tracker_pt tracker;
+
+    celix_thread_mutex_t mutex;
+    void *service; //protected by mutex
+
+    //TODO add tracker and lock
+    bool closed;
+};
+
+static void exportRegistration_addServ(export_registration_pt reg, service_reference_pt ref, void *service);
+static void exportRegistration_removeServ(export_registration_pt reg, service_reference_pt ref, void *service);
+
+celix_status_t exportRegistration_create(log_helper_pt helper, service_reference_pt reference, endpoint_description_pt endpoint, bundle_context_pt context, export_registration_pt *out) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    const char *servId = NULL;
+    status = serviceReference_getProperty(reference, "service.id", &servId);
+    if (status != CELIX_SUCCESS) {
+        logHelper_log(helper, OSGI_LOGSERVICE_WARNING, "Cannot find service.id for ref");
+    }
+
+    export_registration_pt reg = NULL;
+    if (status == CELIX_SUCCESS) {
+        reg = calloc(1, sizeof(*reg));
+        if (reg == NULL) {
+            status = CELIX_ENOMEM;
+        }
+    }
+
+
+    if (status == CELIX_SUCCESS) {
+        reg->context = context;
+        reg->exportReference.endpoint = endpoint;
+        reg->exportReference.reference = reference;
+        reg->closed = false;
+
+        celixThreadMutex_create(&reg->mutex, NULL);
+    }
+
+    const char *exports = NULL;
+    CELIX_DO_IF(status, serviceReference_getProperty(reference, (char *) OSGI_RSA_SERVICE_EXPORTED_INTERFACES, &exports));
+
+    bundle_pt bundle = NULL;
+    CELIX_DO_IF(status, serviceReference_getBundle(reference, &bundle));
+
+    FILE *descriptor = NULL;
+    if (status == CELIX_SUCCESS) {
+        status = dfi_findDescriptor(context, bundle, exports, &descriptor);
+    }
+
+    if (status != CELIX_SUCCESS || descriptor == NULL) {
+        status = CELIX_BUNDLE_EXCEPTION;
+        logHelper_log(helper, OSGI_LOGSERVICE_ERROR, "Cannot find/open descriptor for '%s'", exports);
+    }
+
+    if (status == CELIX_SUCCESS) {
+        int rc = dynInterface_parse(descriptor, &reg->intf);
+        fclose(descriptor);
+        if (rc != 0) {
+            status = CELIX_BUNDLE_EXCEPTION;
+            logHelper_log(helper, OSGI_LOGSERVICE_WARNING, "RSA: Error parsing service descriptor.");
+        }
+        else{
+            /* Add the interface version as a property in the properties_map */
+            char* intfVersion = NULL;
+            dynInterface_getVersionString(reg->intf, &intfVersion);
+            const char *serviceVersion = properties_get(endpoint->properties,(char*) CELIX_FRAMEWORK_SERVICE_VERSION);
+            if(serviceVersion!=NULL){
+            	if(strcmp(serviceVersion,intfVersion)!=0){
+            		logHelper_log(helper, OSGI_LOGSERVICE_WARNING, "Service version (%s) and interface version from the descriptor (%s) are not the same!",serviceVersion,intfVersion);
+            	}
+            }
+            else{
+            	properties_set(endpoint->properties, (char*) CELIX_FRAMEWORK_SERVICE_VERSION, intfVersion);
+            }
+        }
+    } 
+
+    if (status == CELIX_SUCCESS) {
+        service_tracker_customizer_pt cust = NULL;
+        status = serviceTrackerCustomizer_create(reg, NULL, (void *) exportRegistration_addServ, NULL,
+                                                 (void *) exportRegistration_removeServ, &cust);
+        if (status == CELIX_SUCCESS) {
+            char filter[32];
+            snprintf(filter, 32, "(service.id=%s)", servId);
+            status = serviceTracker_createWithFilter(reg->context, filter, cust, &reg->tracker);
+        }
+    }
+
+    if (status == CELIX_SUCCESS) {
+        *out = reg;
+    } else {
+        logHelper_log(helper, OSGI_LOGSERVICE_ERROR, "Error creating export registration");
+        exportRegistration_destroy(reg);
+    }
+
+    return status;
+}
+
+celix_status_t exportRegistration_call(export_registration_pt export, char *data, int datalength, char **responseOut, int *responseLength) {
+    int status = CELIX_SUCCESS;
+
+    //printf("calling for '%s'\n");
+
+    *responseLength = -1;
+    celixThreadMutex_lock(&export->mutex);
+    status = jsonRpc_call(export->intf, export->service, data, responseOut);
+    celixThreadMutex_unlock(&export->mutex);
+
+    return status;
+}
+
+void exportRegistration_destroy(export_registration_pt reg) {
+    if (reg != NULL) {
+        if (reg->intf != NULL) {
+            dyn_interface_type *intf = reg->intf;
+            reg->intf = NULL;
+            dynInterface_destroy(intf);
+        }
+
+        if (reg->exportReference.endpoint != NULL) {
+            endpoint_description_pt ep = reg->exportReference.endpoint;
+            reg->exportReference.endpoint = NULL;
+            endpointDescription_destroy(ep);
+        }
+        if (reg->tracker != NULL) {
+            serviceTracker_destroy(reg->tracker);
+        }
+        celixThreadMutex_destroy(&reg->mutex);
+
+        free(reg);
+    }
+}
+
+celix_status_t exportRegistration_start(export_registration_pt reg) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    serviceTracker_open(reg->tracker);
+    return status;
+}
+
+
+celix_status_t exportRegistration_stop(export_registration_pt reg) {
+    celix_status_t status = CELIX_SUCCESS;
+    if (status == CELIX_SUCCESS) {
+        status = bundleContext_ungetServiceReference(reg->context, reg->exportReference.reference);
+        serviceTracker_close(reg->tracker);
+    }
+    return status;
+}
+
+static void exportRegistration_addServ(export_registration_pt reg, service_reference_pt ref, void *service) {
+    celixThreadMutex_lock(&reg->mutex);
+    reg->service = service;
+    celixThreadMutex_unlock(&reg->mutex);
+}
+
+static void exportRegistration_removeServ(export_registration_pt reg, service_reference_pt ref, void *service) {
+    celixThreadMutex_lock(&reg->mutex);
+    if (reg->service == service) {
+        reg->service = NULL;
+    }
+    celixThreadMutex_unlock(&reg->mutex);
+}
+
+
+celix_status_t exportRegistration_close(export_registration_pt reg) {
+    celix_status_t status = CELIX_SUCCESS;
+    exportRegistration_stop(reg);
+    return status;
+}
+
+
+celix_status_t exportRegistration_getException(export_registration_pt registration) {
+    celix_status_t status = CELIX_SUCCESS;
+    //TODO
+    return status;
+}
+
+celix_status_t exportRegistration_getExportReference(export_registration_pt registration, export_reference_pt *out) {
+    celix_status_t status = CELIX_SUCCESS;
+    export_reference_pt ref = calloc(1, sizeof(*ref));
+    if (ref != NULL) {
+        ref->endpoint = registration->exportReference.endpoint;
+        ref->reference = registration->exportReference.reference;
+    } else {
+        status = CELIX_ENOMEM;
+    }
+
+    if (status == CELIX_SUCCESS) {
+        *out = ref;
+    }
+
+    return status;
+}
+
+celix_status_t exportReference_getExportedEndpoint(export_reference_pt reference, endpoint_description_pt *endpoint) {
+    celix_status_t status = CELIX_SUCCESS;
+    *endpoint = reference->endpoint;
+    return status;
+}
+
+celix_status_t exportReference_getExportedService(export_reference_pt reference, service_reference_pt *ref) {
+    celix_status_t status = CELIX_SUCCESS;
+    *ref = reference->reference;
+    return status;
+}
+
+
+

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/src/export_registration_dfi.h
----------------------------------------------------------------------
diff --git a/remote_services/remote_service_admin_dfi/src/export_registration_dfi.h b/remote_services/remote_service_admin_dfi/src/export_registration_dfi.h
new file mode 100644
index 0000000..93f37ba
--- /dev/null
+++ b/remote_services/remote_service_admin_dfi/src/export_registration_dfi.h
@@ -0,0 +1,38 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CELIX_EXPORT_REGISTRATION_DFI_H
+#define CELIX_EXPORT_REGISTRATION_DFI_H
+
+
+#include "export_registration.h"
+#include "log_helper.h"
+#include "endpoint_description.h"
+
+celix_status_t exportRegistration_create(log_helper_pt helper, service_reference_pt reference, endpoint_description_pt endpoint, bundle_context_pt context, export_registration_pt *registration);
+celix_status_t exportRegistration_close(export_registration_pt registration);
+void exportRegistration_destroy(export_registration_pt registration);
+
+celix_status_t exportRegistration_start(export_registration_pt registration);
+celix_status_t exportRegistration_stop(export_registration_pt registration);
+
+celix_status_t exportRegistration_call(export_registration_pt export, char *data, int datalength, char **response, int *responseLength);
+
+
+#endif //CELIX_EXPORT_REGISTRATION_DFI_H


[4/8] celix git commit: CELIX-417: Refactors CMake usage for the RSA bundles

Posted by pn...@apache.org.
http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_common/src/civetweb.c
----------------------------------------------------------------------
diff --git a/remote_services/discovery_common/src/civetweb.c b/remote_services/discovery_common/src/civetweb.c
deleted file mode 100644
index a6093b7..0000000
--- a/remote_services/discovery_common/src/civetweb.c
+++ /dev/null
@@ -1,7907 +0,0 @@
-	/* Copyright (c) 2013-2015 the Civetweb developers
- * Copyright (c) 2004-2013 Sergey Lyubka
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#if defined(_WIN32)
-#if !defined(_CRT_SECURE_NO_WARNINGS)
-#define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005 */
-#endif
-#else
-#ifdef __linux__
-#define _XOPEN_SOURCE 600     /* For flockfile() on Linux */
-#endif
-#ifndef _LARGEFILE_SOURCE
-#define _LARGEFILE_SOURCE     /* For fseeko(), ftello() */
-#endif
-#ifndef _FILE_OFFSET_BITS
-#define _FILE_OFFSET_BITS 64  /* Use 64-bit file offsets by default */
-#endif
-#ifndef __STDC_FORMAT_MACROS
-#define __STDC_FORMAT_MACROS  /* <inttypes.h> wants this for C++ */
-#endif
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS   /* C++ wants that for INT64_MAX */
-#endif
-#endif
-
-#if defined (_MSC_VER)
-/* 'type cast' : conversion from 'int' to 'HANDLE' of greater size */
-#pragma warning (disable : 4306 )
-/* conditional expression is constant: introduced by FD_SET(..) */
-#pragma warning (disable : 4127)
-/* non-constant aggregate initializer: issued due to missing C99 support */
-#pragma warning (disable : 4204)
-#endif
-
-/* Disable WIN32_LEAN_AND_MEAN.
-   This makes windows.h always include winsock2.h */
-#if defined(WIN32_LEAN_AND_MEAN)
-#undef WIN32_LEAN_AND_MEAN
-#endif
-
-#if defined USE_IPV6 && defined(_WIN32)
-#include <ws2tcpip.h>
-#endif
-
-#if defined(__SYMBIAN32__)
-#define NO_SSL /* SSL is not supported */
-#define NO_CGI /* CGI is not supported */
-#define PATH_MAX FILENAME_MAX
-#endif /* __SYMBIAN32__ */
-
-#ifndef IGNORE_UNUSED_RESULT
-#define IGNORE_UNUSED_RESULT(a) (void)((a) && 1)
-#endif
-
-#ifndef _WIN32_WCE /* Some ANSI #includes are not available on Windows CE */
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <signal.h>
-#include <fcntl.h>
-#endif /* !_WIN32_WCE */
-
-#include <time.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <string.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stddef.h>
-#include <stdio.h>
-
-#ifndef MAX_WORKER_THREADS
-#define MAX_WORKER_THREADS (1024*64)
-#endif
-
-#if defined(_WIN32) && !defined(__SYMBIAN32__) /* Windows specific */
-#if defined(_MSC_VER) && _MSC_VER <= 1400
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0400 /* To make it link in VS2005 */
-#endif
-#include <windows.h>
-typedef const char * SOCK_OPT_TYPE;
-
-#ifndef PATH_MAX
-#define PATH_MAX MAX_PATH
-#endif
-
-#ifndef _IN_PORT_T
-#ifndef in_port_t
-#define in_port_t u_short
-#endif
-#endif
-
-#ifndef _WIN32_WCE
-#include <process.h>
-#include <direct.h>
-#include <io.h>
-#else /* _WIN32_WCE */
-#define NO_CGI /* WinCE has no pipes */
-
-typedef long off_t;
-
-#define errno   GetLastError()
-#define strerror(x)  _ultoa(x, (char *) _alloca(sizeof(x) *3 ), 10)
-#endif /* _WIN32_WCE */
-
-#define MAKEUQUAD(lo, hi) ((uint64_t)(((uint32_t)(lo)) | \
-      ((uint64_t)((uint32_t)(hi))) << 32))
-#define RATE_DIFF 10000000 /* 100 nsecs */
-#define EPOCH_DIFF MAKEUQUAD(0xd53e8000, 0x019db1de)
-#define SYS2UNIX_TIME(lo, hi) \
-  (time_t) ((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF)
-
-/* Visual Studio 6 does not know __func__ or __FUNCTION__
-   The rest of MS compilers use __FUNCTION__, not C99 __func__
-   Also use _strtoui64 on modern M$ compilers */
-#if defined(_MSC_VER) && _MSC_VER < 1300
-#define STRX(x) #x
-#define STR(x) STRX(x)
-#define __func__ __FILE__ ":" STR(__LINE__)
-#define strtoull(x, y, z) (unsigned __int64) _atoi64(x)
-#define strtoll(x, y, z) _atoi64(x)
-#else
-#define __func__  __FUNCTION__
-#define strtoull(x, y, z) _strtoui64(x, y, z)
-#define strtoll(x, y, z) _strtoi64(x, y, z)
-#endif /* _MSC_VER */
-
-#define ERRNO   GetLastError()
-#define NO_SOCKLEN_T
-#define SSL_LIB   "ssleay32.dll"
-#define CRYPTO_LIB  "libeay32.dll"
-#define O_NONBLOCK  0
-#define W_OK (2) /* http://msdn.microsoft.com/en-us/library/1w06ktdy.aspx */
-#if !defined(EWOULDBLOCK)
-#define EWOULDBLOCK  WSAEWOULDBLOCK
-#endif /* !EWOULDBLOCK */
-#define _POSIX_
-#define INT64_FMT  "I64d"
-
-#define WINCDECL __cdecl
-#define SHUT_WR 1
-#define snprintf _snprintf
-#define vsnprintf _vsnprintf
-#define access _access
-#define mg_sleep(x) Sleep(x)
-
-#define pipe(x) _pipe(x, MG_BUF_LEN, _O_BINARY)
-#ifndef popen
-#define popen(x, y) _popen(x, y)
-#endif
-#ifndef pclose
-#define pclose(x) _pclose(x)
-#endif
-#define close(x) _close(x)
-#define dlsym(x,y) GetProcAddress((HINSTANCE) (x), (y))
-#define RTLD_LAZY  0
-#define fseeko(x, y, z) _lseeki64(_fileno(x), (y), (z))
-#define fdopen(x, y) _fdopen((x), (y))
-#define write(x, y, z) _write((x), (y), (unsigned) z)
-#define read(x, y, z) _read((x), (y), (unsigned) z)
-#define flockfile(x) EnterCriticalSection(&global_log_file_lock)
-#define funlockfile(x) LeaveCriticalSection(&global_log_file_lock)
-#define sleep(x) Sleep((x) * 1000)
-#define rmdir(x) _rmdir(x)
-
-#if defined(USE_LUA) && defined(USE_WEBSOCKET)
-#define USE_TIMERS
-#endif
-
-#if !defined(va_copy)
-#define va_copy(x, y) x = y
-#endif /* !va_copy MINGW #defines va_copy */
-
-#if !defined(fileno)
-#define fileno(x) _fileno(x)
-#endif /* !fileno MINGW #defines fileno */
-
-typedef HANDLE pthread_mutex_t;
-typedef DWORD pthread_key_t;
-typedef HANDLE pthread_t;
-typedef struct {
-    CRITICAL_SECTION threadIdSec;
-    int waitingthreadcount;        /* The number of threads queued. */
-    pthread_t *waitingthreadhdls;  /* The thread handles. */
-} pthread_cond_t;
-
-#ifndef __clockid_t_defined
-typedef DWORD clockid_t;
-#endif
-#ifndef CLOCK_MONOTONIC
-#define CLOCK_MONOTONIC (1)
-#endif
-#ifndef CLOCK_REALTIME
-#define CLOCK_REALTIME  (2)
-#endif
-
-#ifndef _TIMESPEC_DEFINED
-struct timespec {
-    time_t   tv_sec;        /* seconds */
-    long     tv_nsec;       /* nanoseconds */
-};
-#endif
-
-#define pid_t HANDLE /* MINGW typedefs pid_t to int. Using #define here. */
-
-static int pthread_mutex_lock(pthread_mutex_t *);
-static int pthread_mutex_unlock(pthread_mutex_t *);
-static void to_unicode(const char *path, wchar_t *wbuf, size_t wbuf_len);
-struct file;
-static char *mg_fgets(char *buf, size_t size, struct file *filep, char **p);
-
-#if defined(HAVE_STDINT)
-#include <stdint.h>
-#else
-typedef unsigned int  uint32_t;
-typedef unsigned short  uint16_t;
-typedef unsigned __int64 uint64_t;
-typedef __int64   int64_t;
-#define INT64_MAX  9223372036854775807
-#endif /* HAVE_STDINT */
-
-/* POSIX dirent interface */
-struct dirent {
-    char d_name[PATH_MAX];
-};
-
-typedef struct DIR {
-    HANDLE   handle;
-    WIN32_FIND_DATAW info;
-    struct dirent  result;
-} DIR;
-
-#if !defined(USE_IPV6) && defined(_WIN32)
-#ifndef HAVE_POLL
-struct pollfd {
-    SOCKET fd;
-    short events;
-    short revents;
-};
-#define POLLIN 1
-#endif
-#endif
-
-/* Mark required libraries */
-#ifdef _MSC_VER
-#pragma comment(lib, "Ws2_32.lib")
-#endif
-
-#else    /* UNIX  specific */
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <sys/poll.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/time.h>
-#include <sys/utsname.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <netdb.h>
-typedef const void * SOCK_OPT_TYPE;
-
-//#if defined(ANDROID)
-typedef unsigned short int in_port_t;
-//#endif
-
-#include <pwd.h>
-#include <unistd.h>
-#include <dirent.h>
-#if !defined(NO_SSL_DL) && !defined(NO_SSL)
-#include <dlfcn.h>
-#endif
-#include <pthread.h>
-#if defined(__MACH__)
-#define SSL_LIB   "libssl.dylib"
-#define CRYPTO_LIB  "libcrypto.dylib"
-#else
-#if !defined(SSL_LIB)
-#define SSL_LIB   "libssl.so"
-#endif
-#if !defined(CRYPTO_LIB)
-#define CRYPTO_LIB  "libcrypto.so"
-#endif
-#endif
-#ifndef O_BINARY
-#define O_BINARY  0
-#endif /* O_BINARY */
-#define closesocket(a) close(a)
-#define mg_mkdir(x, y) mkdir(x, y)
-#define mg_remove(x) remove(x)
-#define mg_sleep(x) usleep((x) * 1000)
-#define ERRNO errno
-#define INVALID_SOCKET (-1)
-#define INT64_FMT PRId64
-typedef int SOCKET;
-#define WINCDECL
-
-#endif /* End of Windows and UNIX specific includes */
-
-#ifdef _WIN32
-static CRITICAL_SECTION global_log_file_lock;
-static DWORD pthread_self(void)
-{
-    return GetCurrentThreadId();
-}
-
-int pthread_key_create(pthread_key_t *key, void (*_must_be_zero)(void*) /* destructor function not supported for windows */)
-{
-    assert(_must_be_zero == NULL);
-    if ((key!=0) && (_must_be_zero == NULL)) {
-        *key = TlsAlloc();
-        return (*key != TLS_OUT_OF_INDEXES) ? 0 : -1;
-    }
-    return -2;
-}
-
-int pthread_key_delete(pthread_key_t key)
-{
-    return TlsFree(key) ? 0 : 1;
-}
-
-int pthread_setspecific(pthread_key_t key, void * value)
-{
-    return TlsSetValue(key, value) ? 0 : 1;
-}
-
-void *pthread_getspecific(pthread_key_t key)
-{
-    return TlsGetValue(key);
-}
-#endif /* _WIN32 */
-
-
-#include "civetweb.h"
-
-#define PASSWORDS_FILE_NAME ".htpasswd"
-#define CGI_ENVIRONMENT_SIZE 4096
-#define MAX_CGI_ENVIR_VARS 64
-#define MG_BUF_LEN 8192
-#ifndef MAX_REQUEST_SIZE
-#define MAX_REQUEST_SIZE 16384
-#endif
-#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
-
-#if !defined(DEBUG_TRACE)
-#if defined(CWDEBUG)
-
-static void DEBUG_TRACE_FUNC(const char *func, unsigned line, PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(3, 4);
-
-static void DEBUG_TRACE_FUNC(const char *func, unsigned line, const char *fmt, ...) {
-
-  va_list args;
-  flockfile(stdout);
- printf("*** %lu.%p.%s.%u: ",
-         (unsigned long) time(NULL), (void *) pthread_self(),
-         func, line);
-  va_start(args, fmt);
-  vprintf(fmt, args);
-  va_end(args);
-  putchar('\n');
-  fflush(stdout);
-  funlockfile(stdout);
-}
-
-#define DEBUG_TRACE(fmt, ...) DEBUG_TRACE_FUNC(__func__, __LINE__, fmt, __VA_ARGS__)
-
-#else
-#define DEBUG_TRACE(fmt, ...)
-#endif /* CWDEBUG */
-#endif /* DEBUG_TRACE */
-
-#if defined(MEMORY_DEBUGGING)
-static unsigned long blockCount = 0;
-static unsigned long totalMemUsed = 0;
-
-static void * mg_malloc_ex(size_t size, const char * file, unsigned line) {
-
-    void * data = malloc(size + sizeof(size_t));
-    void * memory = 0;
-    char mallocStr[256];
-
-    if (data) {
-        *(size_t*)data = size;
-        totalMemUsed += size;
-        blockCount++;
-        memory = (void *)(((char*)data)+sizeof(size_t));
-    }
-
-    sprintf(mallocStr, "MEM: %p %5lu alloc   %7lu %4lu --- %s:%u\n", memory, (unsigned long)size, totalMemUsed, blockCount, file, line);
-#if defined(_WIN32)
-    OutputDebugStringA(mallocStr);
-#else
-    DEBUG_TRACE("%s", mallocStr);
-#endif
-
-    return memory;
-}
-
-static void * mg_calloc_ex(size_t count, size_t size, const char * file, unsigned line) {
-
-    void * data = mg_malloc_ex(size*count, file, line);
-    if (data) memset(data, 0, size);
-
-    return data;
-}
-
-static void mg_free_ex(void * memory, const char * file, unsigned line) {
-
-    char mallocStr[256];
-    void * data = (void *)(((char*)memory)-sizeof(size_t));
-    size_t size;
-
-    if (memory) {
-        size = *(size_t*)data;
-        totalMemUsed -= size;
-        blockCount--;
-        sprintf(mallocStr, "MEM: %p %5lu free    %7lu %4lu --- %s:%u\n", memory, (unsigned long)size, totalMemUsed, blockCount, file, line);
-#if defined(_WIN32)
-        OutputDebugStringA(mallocStr);
-#else
-        DEBUG_TRACE("%s", mallocStr);
-#endif
-
-        free(data);
-    }
-}
-
-static void * mg_realloc_ex(void * memory, size_t newsize, const char * file, unsigned line) {
-
-    char mallocStr[256];
-    void * data;
-    void * _realloc;
-    size_t oldsize;
-
-    if (newsize) {
-        if (memory) {
-            data = (void *)(((char*)memory)-sizeof(size_t));
-            oldsize = *(size_t*)data;
-            _realloc = realloc(data, newsize+sizeof(size_t));
-            if (_realloc) {
-                data = _realloc;
-                totalMemUsed -= oldsize;
-                sprintf(mallocStr, "MEM: %p %5lu r-free  %7lu %4lu --- %s:%u\n", memory, (unsigned long)oldsize, totalMemUsed, blockCount, file, line);
-#if defined(_WIN32)
-                OutputDebugStringA(mallocStr);
-#else
-                DEBUG_TRACE("%s", mallocStr);
-#endif
-                totalMemUsed += newsize;
-                sprintf(mallocStr, "MEM: %p %5lu r-alloc %7lu %4lu --- %s:%u\n", memory, (unsigned long)newsize, totalMemUsed, blockCount, file, line);
-#if defined(_WIN32)
-                OutputDebugStringA(mallocStr);
-#else
-                DEBUG_TRACE("%s", mallocStr);
-#endif
-                *(size_t*)data = newsize;
-                data = (void *)(((char*)data)+sizeof(size_t));
-            } else {
-#if defined(_WIN32)
-                OutputDebugStringA("MEM: realloc failed\n");
-#else
-                DEBUG_TRACE("%s", "MEM: realloc failed\n");
-#endif
-                return _realloc;
-            }
-        } else {
-            data = mg_malloc_ex(newsize, file, line);
-        }
-    } else {
-        data = 0;
-        mg_free_ex(memory, file, line);
-    }
-
-    return data;
-}
-
-#define mg_malloc(a)      mg_malloc_ex(a, __FILE__, __LINE__)
-#define mg_calloc(a,b)    mg_calloc_ex(a, b, __FILE__, __LINE__)
-#define mg_realloc(a, b)  mg_realloc_ex(a, b, __FILE__, __LINE__)
-#define mg_free(a)        mg_free_ex(a, __FILE__, __LINE__)
-
-#else
-static __inline void * mg_malloc(size_t a)             {return malloc(a);}
-static __inline void * mg_calloc(size_t a, size_t b)   {return calloc(a, b);}
-static __inline void * mg_realloc(void * a, size_t b)  {return realloc(a, b);}
-static __inline void   mg_free(void * a)               {free(a);}
-#endif
-
-/* This following lines are just meant as a reminder to use the mg-functions for memory management */
-#ifdef malloc
-    #undef malloc
-#endif
-#ifdef calloc
-    #undef calloc
-#endif
-#ifdef realloc
-    #undef realloc
-#endif
-#ifdef free
-    #undef free
-#endif
-#define malloc  DO_NOT_USE_THIS_FUNCTION__USE_mg_malloc
-#define calloc  DO_NOT_USE_THIS_FUNCTION__USE_mg_calloc
-#define realloc DO_NOT_USE_THIS_FUNCTION__USE_mg_realloc
-#define free    DO_NOT_USE_THIS_FUNCTION__USE_mg_free
-
-
-#define MD5_STATIC static
-#include "md5.inl"
-
-/* Darwin prior to 7.0 and Win32 do not have socklen_t */
-#ifdef NO_SOCKLEN_T
-typedef int socklen_t;
-#endif /* NO_SOCKLEN_T */
-#define _DARWIN_UNLIMITED_SELECT
-
-#define IP_ADDR_STR_LEN 50  /* IPv6 hex string is 46 chars */
-
-#if !defined(MSG_NOSIGNAL)
-#define MSG_NOSIGNAL 0
-#endif
-
-#if !defined(SOMAXCONN)
-#define SOMAXCONN 100
-#endif
-
-#if !defined(PATH_MAX)
-#define PATH_MAX 4096
-#endif
-
-/* Size of the accepted socket queue */
-#if !defined(MGSQLEN)
-#define MGSQLEN 20
-#endif
-
-#if defined(NO_SSL_DL)
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#else
-/* SSL loaded dynamically from DLL.
-   I put the prototypes here to be independent from OpenSSL source
-   installation. */
-
-typedef struct ssl_st SSL;
-typedef struct ssl_method_st SSL_METHOD;
-typedef struct ssl_ctx_st SSL_CTX;
-
-struct ssl_func {
-    const char *name;   /* SSL function name */
-    void  (*ptr)(void); /* Function pointer */
-};
-
-#define SSL_free (* (void (*)(SSL *)) ssl_sw[0].ptr)
-#define SSL_accept (* (int (*)(SSL *)) ssl_sw[1].ptr)
-#define SSL_connect (* (int (*)(SSL *)) ssl_sw[2].ptr)
-#define SSL_read (* (int (*)(SSL *, void *, int)) ssl_sw[3].ptr)
-#define SSL_write (* (int (*)(SSL *, const void *,int)) ssl_sw[4].ptr)
-#define SSL_get_error (* (int (*)(SSL *, int)) ssl_sw[5].ptr)
-#define SSL_set_fd (* (int (*)(SSL *, SOCKET)) ssl_sw[6].ptr)
-#define SSL_new (* (SSL * (*)(SSL_CTX *)) ssl_sw[7].ptr)
-#define SSL_CTX_new (* (SSL_CTX * (*)(SSL_METHOD *)) ssl_sw[8].ptr)
-#define SSLv23_server_method (* (SSL_METHOD * (*)(void)) ssl_sw[9].ptr)
-#define SSL_library_init (* (int (*)(void)) ssl_sw[10].ptr)
-#define SSL_CTX_use_PrivateKey_file (* (int (*)(SSL_CTX *, \
-        const char *, int)) ssl_sw[11].ptr)
-#define SSL_CTX_use_certificate_file (* (int (*)(SSL_CTX *, \
-        const char *, int)) ssl_sw[12].ptr)
-#define SSL_CTX_set_default_passwd_cb \
-  (* (void (*)(SSL_CTX *, mg_callback_t)) ssl_sw[13].ptr)
-#define SSL_CTX_free (* (void (*)(SSL_CTX *)) ssl_sw[14].ptr)
-#define SSL_load_error_strings (* (void (*)(void)) ssl_sw[15].ptr)
-#define SSL_CTX_use_certificate_chain_file \
-  (* (int (*)(SSL_CTX *, const char *)) ssl_sw[16].ptr)
-#define SSLv23_client_method (* (SSL_METHOD * (*)(void)) ssl_sw[17].ptr)
-#define SSL_pending (* (int (*)(SSL *)) ssl_sw[18].ptr)
-#define SSL_CTX_set_verify (* (void (*)(SSL_CTX *, int, int)) ssl_sw[19].ptr)
-#define SSL_shutdown (* (int (*)(SSL *)) ssl_sw[20].ptr)
-
-#define CRYPTO_num_locks (* (int (*)(void)) crypto_sw[0].ptr)
-#define CRYPTO_set_locking_callback \
-  (* (void (*)(void (*)(int, int, const char *, int))) crypto_sw[1].ptr)
-#define CRYPTO_set_id_callback \
-  (* (void (*)(unsigned long (*)(void))) crypto_sw[2].ptr)
-#define ERR_get_error (* (unsigned long (*)(void)) crypto_sw[3].ptr)
-#define ERR_error_string (* (char * (*)(unsigned long,char *)) crypto_sw[4].ptr)
-
-/* set_ssl_option() function updates this array.
-   It loads SSL library dynamically and changes NULLs to the actual addresses
-   of respective functions. The macros above (like SSL_connect()) are really
-   just calling these functions indirectly via the pointer. */
-static struct ssl_func ssl_sw[] = {
-    {"SSL_free",   NULL},
-    {"SSL_accept",   NULL},
-    {"SSL_connect",   NULL},
-    {"SSL_read",   NULL},
-    {"SSL_write",   NULL},
-    {"SSL_get_error",  NULL},
-    {"SSL_set_fd",   NULL},
-    {"SSL_new",   NULL},
-    {"SSL_CTX_new",   NULL},
-    {"SSLv23_server_method", NULL},
-    {"SSL_library_init",  NULL},
-    {"SSL_CTX_use_PrivateKey_file", NULL},
-    {"SSL_CTX_use_certificate_file",NULL},
-    {"SSL_CTX_set_default_passwd_cb",NULL},
-    {"SSL_CTX_free",  NULL},
-    {"SSL_load_error_strings", NULL},
-    {"SSL_CTX_use_certificate_chain_file", NULL},
-    {"SSLv23_client_method", NULL},
-    {"SSL_pending", NULL},
-    {"SSL_CTX_set_verify", NULL},
-    {"SSL_shutdown",   NULL},
-    {NULL,    NULL}
-};
-
-/* Similar array as ssl_sw. These functions could be located in different
-   lib. */
-#if !defined(NO_SSL)
-static struct ssl_func crypto_sw[] = {
-    {"CRYPTO_num_locks",  NULL},
-    {"CRYPTO_set_locking_callback", NULL},
-    {"CRYPTO_set_id_callback", NULL},
-    {"ERR_get_error",  NULL},
-    {"ERR_error_string", NULL},
-    {NULL,    NULL}
-};
-#endif /* NO_SSL */
-#endif /* NO_SSL_DL */
-
-static const char *month_names[] = {
-    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
-/* Unified socket address. For IPv6 support, add IPv6 address structure
-   in the union u. */
-union usa {
-    struct sockaddr sa;
-    struct sockaddr_in sin;
-#if defined(USE_IPV6)
-    struct sockaddr_in6 sin6;
-#endif
-};
-
-/* Describes a string (chunk of memory). */
-struct vec {
-    const char *ptr;
-    size_t len;
-};
-
-struct file {
-    int is_directory;
-    time_t modification_time;
-    int64_t size;
-    FILE *fp;
-    const char *membuf;   /* Non-NULL if file data is in memory */
-    /* set to 1 if the content is gzipped
-       in which case we need a content-encoding: gzip header */
-    int gzipped;
-};
-#define STRUCT_FILE_INITIALIZER {0, 0, 0, NULL, NULL, 0}
-
-/* Describes listening socket, or socket which was accept()-ed by the master
-   thread and queued for future handling by the worker thread. */
-struct socket {
-    SOCKET sock;          /* Listening socket */
-    union usa lsa;        /* Local socket address */
-    union usa rsa;        /* Remote socket address */
-    unsigned is_ssl:1;    /* Is port SSL-ed */
-    unsigned ssl_redir:1; /* Is port supposed to redirect everything to SSL
-                             port */
-};
-
-/* NOTE(lsm): this enum shoulds be in sync with the config_options below. */
-enum {
-    CGI_EXTENSIONS, CGI_ENVIRONMENT, PUT_DELETE_PASSWORDS_FILE, CGI_INTERPRETER,
-    PROTECT_URI, AUTHENTICATION_DOMAIN, SSI_EXTENSIONS, THROTTLE,
-    ACCESS_LOG_FILE, ENABLE_DIRECTORY_LISTING, ERROR_LOG_FILE,
-    GLOBAL_PASSWORDS_FILE, INDEX_FILES, ENABLE_KEEP_ALIVE, ACCESS_CONTROL_LIST,
-    EXTRA_MIME_TYPES, LISTENING_PORTS, DOCUMENT_ROOT, SSL_CERTIFICATE,
-    NUM_THREADS, RUN_AS_USER, REWRITE, HIDE_FILES, REQUEST_TIMEOUT,
-    DECODE_URL,
-
-#if defined(USE_LUA)
-    LUA_PRELOAD_FILE, LUA_SCRIPT_EXTENSIONS, LUA_SERVER_PAGE_EXTENSIONS,
-#endif
-#if defined(USE_WEBSOCKET)
-    WEBSOCKET_ROOT,
-#endif
-#if defined(USE_LUA) && defined(USE_WEBSOCKET)
-    LUA_WEBSOCKET_EXTENSIONS,
-#endif
-    ACCESS_CONTROL_ALLOW_ORIGIN, ERROR_PAGES,
-
-    NUM_OPTIONS
-};
-
-/* Config option name, config types, default value */
-static struct mg_option config_options[] = {
-    {"cgi_pattern",                 CONFIG_TYPE_EXT_PATTERN,   "**.cgi$|**.pl$|**.php$"},
-    {"cgi_environment",             CONFIG_TYPE_STRING,        NULL},
-    {"put_delete_auth_file",        CONFIG_TYPE_FILE,          NULL},
-    {"cgi_interpreter",             CONFIG_TYPE_FILE,          NULL},
-    {"protect_uri",                 CONFIG_TYPE_STRING,        NULL},
-    {"authentication_domain",       CONFIG_TYPE_STRING,        "mydomain.com"},
-    {"ssi_pattern",                 CONFIG_TYPE_EXT_PATTERN,   "**.shtml$|**.shtm$"},
-    {"throttle",                    CONFIG_TYPE_STRING,        NULL},
-    {"access_log_file",             CONFIG_TYPE_FILE,          NULL},
-    {"enable_directory_listing",    CONFIG_TYPE_BOOLEAN,       "yes"},
-    {"error_log_file",              CONFIG_TYPE_FILE,          NULL},
-    {"global_auth_file",            CONFIG_TYPE_FILE,          NULL},
-    {"index_files",                 CONFIG_TYPE_STRING,
-#ifdef USE_LUA
-    "index.xhtml,index.html,index.htm,index.lp,index.lsp,index.lua,index.cgi,index.shtml,index.php"},
-#else
-    "index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php"},
-#endif
-    {"enable_keep_alive",           CONFIG_TYPE_BOOLEAN,       "no"},
-    {"access_control_list",         CONFIG_TYPE_STRING,        NULL},
-    {"extra_mime_types",            CONFIG_TYPE_STRING,        NULL},
-    {"listening_ports",             CONFIG_TYPE_STRING,        "8080"},
-    {"document_root",               CONFIG_TYPE_DIRECTORY,     NULL},
-    {"ssl_certificate",             CONFIG_TYPE_FILE,          NULL},
-    {"num_threads",                 CONFIG_TYPE_NUMBER,        "50"},
-    {"run_as_user",                 CONFIG_TYPE_STRING,        NULL},
-    {"url_rewrite_patterns",        CONFIG_TYPE_STRING,        NULL},
-    {"hide_files_patterns",         CONFIG_TYPE_EXT_PATTERN,   NULL},
-    {"request_timeout_ms",          CONFIG_TYPE_NUMBER,        "30000"},
-    {"decode_url",                  CONFIG_TYPE_BOOLEAN,       "yes"},
-
-#if defined(USE_LUA)
-    {"lua_preload_file",            CONFIG_TYPE_FILE,          NULL},
-    {"lua_script_pattern",          CONFIG_TYPE_EXT_PATTERN,   "**.lua$"},
-    {"lua_server_page_pattern",     CONFIG_TYPE_EXT_PATTERN,   "**.lp$|**.lsp$"},
-#endif
-#if defined(USE_WEBSOCKET)
-    {"websocket_root",              CONFIG_TYPE_DIRECTORY,     NULL},
-#endif
-#if defined(USE_LUA) && defined(USE_WEBSOCKET)
-    {"lua_websocket_pattern",       CONFIG_TYPE_EXT_PATTERN,   "**.lua$"},
-#endif
-    {"access_control_allow_origin", CONFIG_TYPE_STRING,        "*"},
-    {"error_pages",                 CONFIG_TYPE_DIRECTORY,     NULL},
-
-    {NULL, CONFIG_TYPE_UNKNOWN, NULL}
-};
-
-struct mg_request_handler_info {
-    char *uri;
-    size_t uri_len;
-    mg_request_handler handler;
-
-    void *cbdata;
-    struct mg_request_handler_info *next;
-};
-
-struct mg_context {
-    volatile int stop_flag;         /* Should we stop event loop */
-    SSL_CTX *ssl_ctx;               /* SSL context */
-    char *config[NUM_OPTIONS];      /* Civetweb configuration parameters */
-    struct mg_callbacks callbacks;  /* User-defined callback function */
-    void *user_data;                /* User-defined data */
-    int context_type;               /* 1 = server context, 2 = client context */
-
-    struct socket *listening_sockets;
-    in_port_t *listening_ports;
-    int num_listening_sockets;
-
-    volatile int num_threads;       /* Number of threads */
-    pthread_mutex_t thread_mutex;   /* Protects (max|num)_threads */
-    pthread_cond_t thread_cond;     /* Condvar for tracking workers terminations */
-
-    struct socket queue[MGSQLEN];   /* Accepted sockets */
-    volatile int sq_head;           /* Head of the socket queue */
-    volatile int sq_tail;           /* Tail of the socket queue */
-    pthread_cond_t sq_full;         /* Signaled when socket is produced */
-    pthread_cond_t sq_empty;        /* Signaled when socket is consumed */
-    pthread_t masterthreadid;       /* The master thread ID */
-    int workerthreadcount;          /* The amount of worker threads. */
-    pthread_t *workerthreadids;     /* The worker thread IDs */
-
-    unsigned long start_time;       /* Server start time, used for authentication */
-    pthread_mutex_t nonce_mutex;    /* Protects nonce_count */
-    unsigned long nonce_count;      /* Used nonces, used for authentication */
-
-    char *systemName;               /* What operating system is running */
-
-    /* linked list of uri handlers */
-    struct mg_request_handler_info *request_handlers;
-
-#if defined(USE_LUA) && defined(USE_WEBSOCKET)
-    /* linked list of shared lua websockets */
-    struct mg_shared_lua_websocket_list *shared_lua_websockets;
-#endif
-
-#ifdef USE_TIMERS
-    struct ttimers * timers;
-#endif
-};
-
-struct mg_connection {
-    struct mg_request_info request_info;
-    struct mg_context *ctx;
-    SSL *ssl;                       /* SSL descriptor */
-    SSL_CTX *client_ssl_ctx;        /* SSL context for client connections */
-    struct socket client;           /* Connected client */
-    time_t birth_time;              /* Time when request was received */
-    int64_t num_bytes_sent;         /* Total bytes sent to client */
-    int64_t content_len;            /* Content-Length header value */
-    int64_t consumed_content;       /* How many bytes of content have been read */
-    char *buf;                      /* Buffer for received data */
-    char *path_info;                /* PATH_INFO part of the URL */
-    int must_close;                 /* 1 if connection must be closed */
-    int in_error_handler;           /* 1 if in handler for user defined error pages */
-    int buf_size;                   /* Buffer size */
-    int request_len;                /* Size of the request + headers in a buffer */
-    int data_len;                   /* Total size of data in a buffer */
-    int status_code;                /* HTTP reply status code, e.g. 200 */
-    int throttle;                   /* Throttling, bytes/sec. <= 0 means no throttle */
-    time_t last_throttle_time;      /* Last time throttled data was sent */
-    int64_t last_throttle_bytes;    /* Bytes sent this second */
-    pthread_mutex_t mutex;          /* Used by mg_lock_connection/mg_unlock_connection to ensure atomic transmissions for websockets */
-#if defined(USE_LUA) && defined(USE_WEBSOCKET)
-    void * lua_websocket_state;     /* Lua_State for a websocket connection */
-#endif
-};
-
-static pthread_key_t sTlsKey;  /* Thread local storage index */
-static int sTlsInit = 0;
-
-struct mg_workerTLS {
-    int is_master;
-#if defined(_WIN32) && !defined(__SYMBIAN32__)
-    HANDLE pthread_cond_helper_mutex;
-#endif
-};
-
-/* Directory entry */
-struct de {
-    struct mg_connection *conn;
-    char *file_name;
-    struct file file;
-};
-
-#if defined(USE_WEBSOCKET)
-static int is_websocket_protocol(const struct mg_connection *conn);
-#else
-#define is_websocket_protocol(conn) (0)
-#endif
-
-int mg_atomic_inc(volatile int * addr)
-{
-    int ret;
-#if defined(_WIN32) && !defined(__SYMBIAN32__)
-    ret = InterlockedIncrement((volatile unsigned int *) addr);
-#elif defined(__GNUC__)
-    ret = __sync_add_and_fetch(addr, 1);
-#else
-    ret = (++(*addr));
-#endif
-    return ret;
-}
-
-int mg_atomic_dec(volatile int * addr)
-{
-    int ret;
-#if defined(_WIN32) && !defined(__SYMBIAN32__)
-    ret = InterlockedDecrement((volatile unsigned int *) addr);
-#elif defined(__GNUC__)
-    ret = __sync_sub_and_fetch(addr, 1);
-#else
-    ret = (--(*addr));
-#endif
-    return ret;
-}
-
-#if !defined(NO_THREAD_NAME)
-#if defined(_WIN32) && defined(_MSC_VER)
-/* Set the thread name for debugging purposes in Visual Studio
-   http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
-*/
-#pragma pack(push,8)
-typedef struct tagTHREADNAME_INFO
-{
-   DWORD dwType;     /* Must be 0x1000. */
-   LPCSTR szName;    /* Pointer to name (in user addr space). */
-   DWORD dwThreadID; /* Thread ID (-1=caller thread). */
-   DWORD dwFlags;    /* Reserved for future use, must be zero. */
-} THREADNAME_INFO;
-#pragma pack(pop)
-#elif defined(__linux__)
-#include <sys/prctl.h>
-#endif
-
-void mg_set_thread_name(const char* name)
-{
-    char threadName[16]; /* Max. thread length in Linux/OSX/.. */
-
-    if (snprintf(threadName, sizeof(threadName), "civetweb-%s", name)<0) return;
-    threadName[sizeof(threadName)-1] = 0;
-
-#if defined(_WIN32)
-#if defined(_MSC_VER)
-    /* Windows and Visual Studio Compiler */
-    __try
-    {
-        THREADNAME_INFO info;
-        info.dwType     = 0x1000;
-        info.szName     = threadName;
-        info.dwThreadID = -1;
-        info.dwFlags    = 0;
-
-        RaiseException(0x406D1388, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
-    }
-    __except(EXCEPTION_EXECUTE_HANDLER)
-    {
-    }
-#elif defined(__MINGW32__)
-   /* No option known to set thread name for MinGW */
-#endif
-#elif defined(__linux__)
-   /* Linux */
-   (void)prctl(PR_SET_NAME,threadName,0,0,0);
-#elif defined(__APPLE__) || defined(__MACH__)
-   /* OS X (TODO: test) */
-   (void)pthread_setname_np(threadName);
-#elif defined(BSD) || defined(__FreeBSD__) || defined(__OpenBSD__)
-   /* BSD (TODO: test) */
-   pthread_set_name_np(pthread_self(), threadName);
-#else
-   /* POSIX */
-   (void)pthread_setname_np(pthread_self(), threadName);
-#endif
-}
-#else /* !defined(NO_THREAD_NAME) */
-void mg_set_thread_name(const char* threadName) {}
-#endif
-
-#if defined(MG_LEGACY_INTERFACE)
-const char **mg_get_valid_option_names(void)
-{
-    static const char * data[2 * sizeof(config_options) / sizeof(config_options[0])] = {0};
-    int i;
-
-    for (i=0; config_options[i].name != NULL; i++) {
-        data[i * 2] = config_options[i].name;
-        data[i * 2 + 1] = config_options[i].default_value;
-    }
-
-    return data;
-}
-#endif
-
-const struct mg_option *mg_get_valid_options(void)
-{
-    return config_options;
-}
-
-
-static int is_file_in_memory(struct mg_connection *conn, const char *path,
-                             struct file *filep)
-{
-    size_t size = 0;
-    if ((filep->membuf = conn->ctx->callbacks.open_file == NULL ? NULL :
-                         conn->ctx->callbacks.open_file(conn, path, &size)) != NULL) {
-        /* NOTE: override filep->size only on success. Otherwise, it might
-           break constructs like if (!mg_stat() || !mg_fopen()) ... */
-        filep->size = size;
-    }
-    return filep->membuf != NULL;
-}
-
-static int is_file_opened(const struct file *filep)
-{
-    return filep->membuf != NULL || filep->fp != NULL;
-}
-
-static int mg_fopen(struct mg_connection *conn, const char *path,
-                    const char *mode, struct file *filep)
-{
-    if (!is_file_in_memory(conn, path, filep)) {
-#ifdef _WIN32
-        wchar_t wbuf[PATH_MAX], wmode[20];
-        to_unicode(path, wbuf, ARRAY_SIZE(wbuf));
-        MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, ARRAY_SIZE(wmode));
-        filep->fp = _wfopen(wbuf, wmode);
-#else
-        filep->fp = fopen(path, mode);
-#endif
-    }
-
-    return is_file_opened(filep);
-}
-
-static void mg_fclose(struct file *filep)
-{
-    if (filep != NULL && filep->fp != NULL) {
-        fclose(filep->fp);
-    }
-}
-
-static void mg_strlcpy(register char *dst, register const char *src, size_t n)
-{
-    for (; *src != '\0' && n > 1; n--) {
-        *dst++ = *src++;
-    }
-    *dst = '\0';
-}
-
-static int lowercase(const char *s)
-{
-    return tolower(* (const unsigned char *) s);
-}
-
-int mg_strncasecmp(const char *s1, const char *s2, size_t len)
-{
-    int diff = 0;
-
-    if (len > 0)
-        do {
-            diff = lowercase(s1++) - lowercase(s2++);
-        } while (diff == 0 && s1[-1] != '\0' && --len > 0);
-
-    return diff;
-}
-
-static int mg_strcasecmp(const char *s1, const char *s2)
-{
-    int diff;
-
-    do {
-        diff = lowercase(s1++) - lowercase(s2++);
-    } while (diff == 0 && s1[-1] != '\0');
-
-    return diff;
-}
-
-static char * mg_strndup(const char *ptr, size_t len)
-{
-    char *p;
-
-    if ((p = (char *) mg_malloc(len + 1)) != NULL) {
-        mg_strlcpy(p, ptr, len + 1);
-    }
-
-    return p;
-}
-
-static char * mg_strdup(const char *str)
-{
-    return mg_strndup(str, strlen(str));
-}
-
-static const char *mg_strcasestr(const char *big_str, const char *small_str)
-{
-    int i, big_len = (int)strlen(big_str), small_len = (int)strlen(small_str);
-
-    for (i = 0; i <= big_len - small_len; i++) {
-        if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) {
-            return big_str + i;
-        }
-    }
-
-    return NULL;
-}
-
-/* Like snprintf(), but never returns negative value, or a value
-   that is larger than a supplied buffer.
-   Thanks to Adam Zeldis to pointing snprintf()-caused vulnerability
-   in his audit report. */
-static int mg_vsnprintf(struct mg_connection *conn, char *buf, size_t buflen,
-                        const char *fmt, va_list ap)
-{
-    int n;
-
-    if (buflen == 0)
-        return 0;
-
-    n = vsnprintf(buf, buflen, fmt, ap);
-
-    if (n < 0) {
-        mg_cry(conn, "vsnprintf error");
-        n = 0;
-    } else if (n >= (int) buflen) {
-        mg_cry(conn, "truncating vsnprintf buffer: [%.*s]",
-               n > 200 ? 200 : n, buf);
-        n = (int) buflen - 1;
-    }
-    buf[n] = '\0';
-
-    return n;
-}
-
-static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen,
-                       PRINTF_FORMAT_STRING(const char *fmt), ...)
-PRINTF_ARGS(4, 5);
-
-static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen,
-                       const char *fmt, ...)
-{
-    va_list ap;
-    int n;
-
-    va_start(ap, fmt);
-    n = mg_vsnprintf(conn, buf, buflen, fmt, ap);
-    va_end(ap);
-
-    return n;
-}
-
-static int get_option_index(const char *name)
-{
-    int i;
-
-    for (i = 0; config_options[i].name != NULL; i++) {
-        if (strcmp(config_options[i].name, name) == 0) {
-            return i;
-        }
-    }
-    return -1;
-}
-
-const char *mg_get_option(const struct mg_context *ctx, const char *name)
-{
-    int i;
-    if ((i = get_option_index(name)) == -1) {
-        return NULL;
-    } else if (ctx->config[i] == NULL) {
-        return "";
-    } else {
-        return ctx->config[i];
-    }
-}
-
-struct mg_context *mg_get_context(struct mg_connection * conn)
-{
-    return (conn == NULL) ? (struct mg_context *)NULL : (conn->ctx);
-}
-
-void *mg_get_user_data(struct mg_context *ctx)
-{
-    return (ctx == NULL) ? NULL : ctx->user_data;
-}
-
-size_t mg_get_ports(const struct mg_context *ctx, size_t size, int* ports, int* ssl)
-{
-    size_t i;
-    for (i = 0; i < size && i < (size_t)ctx->num_listening_sockets; i++)
-    {
-        ssl[i] = ctx->listening_sockets[i].is_ssl;
-        ports[i] = ctx->listening_ports[i];
-    }
-    return i;
-}
-
-static void sockaddr_to_string(char *buf, size_t len,
-                               const union usa *usa)
-{
-    buf[0] = '\0';
-#if defined(USE_IPV6)
-    inet_ntop(usa->sa.sa_family, usa->sa.sa_family == AF_INET ?
-              (void *) &usa->sin.sin_addr :
-              (void *) &usa->sin6.sin6_addr, buf, len);
-#elif defined(_WIN32)
-    /* Only Windows Vista (and newer) have inet_ntop() */
-    mg_strlcpy(buf, inet_ntoa(usa->sin.sin_addr), len);
-#else
-    inet_ntop(usa->sa.sa_family, (void *) &usa->sin.sin_addr, buf, len);
-#endif
-}
-
-/* Convert time_t to a string. According to RFC2616, Sec 14.18, this must be included in all responses other than 100, 101, 5xx. */
-static void gmt_time_string(char *buf, size_t buf_len, time_t *t)
-{
-    struct tm *tm;
-
-    tm = gmtime(t);
-    if (tm != NULL) {
-        strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", tm);
-    } else {
-        mg_strlcpy(buf, "Thu, 01 Jan 1970 00:00:00 GMT", buf_len);
-        buf[buf_len - 1] = '\0';
-    }
-}
-
-/* Print error message to the opened error log stream. */
-void mg_cry(struct mg_connection *conn, const char *fmt, ...)
-{
-    char buf[MG_BUF_LEN], src_addr[IP_ADDR_STR_LEN];
-    va_list ap;
-    FILE *fp;
-    time_t timestamp;
-
-    va_start(ap, fmt);
-    IGNORE_UNUSED_RESULT(vsnprintf(buf, sizeof(buf), fmt, ap));
-    va_end(ap);
-
-    /* Do not lock when getting the callback value, here and below.
-       I suppose this is fine, since function cannot disappear in the
-       same way string option can. */
-    if (conn->ctx->callbacks.log_message == NULL ||
-        conn->ctx->callbacks.log_message(conn, buf) == 0) {
-        fp = conn->ctx->config[ERROR_LOG_FILE] == NULL ? NULL :
-             fopen(conn->ctx->config[ERROR_LOG_FILE], "a+");
-
-        if (fp != NULL) {
-            flockfile(fp);
-            timestamp = time(NULL);
-
-            sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
-            fprintf(fp, "[%010lu] [error] [client %s] ", (unsigned long) timestamp,
-                    src_addr);
-
-            if (conn->request_info.request_method != NULL) {
-                fprintf(fp, "%s %s: ", conn->request_info.request_method,
-                        conn->request_info.uri);
-            }
-
-            fprintf(fp, "%s", buf);
-            fputc('\n', fp);
-            funlockfile(fp);
-            fclose(fp);
-        }
-    }
-}
-
-/* Return fake connection structure. Used for logging, if connection
-   is not applicable at the moment of logging. */
-static struct mg_connection *fc(struct mg_context *ctx)
-{
-    static struct mg_connection fake_connection;
-    fake_connection.ctx = ctx;
-    return &fake_connection;
-}
-
-const char *mg_version(void)
-{
-    return CIVETWEB_VERSION;
-}
-
-struct mg_request_info *mg_get_request_info(struct mg_connection *conn)
-{
-    return &conn->request_info;
-}
-
-/* Skip the characters until one of the delimiters characters found.
-   0-terminate resulting word. Skip the delimiter and following whitespaces.
-   Advance pointer to buffer to the next word. Return found 0-terminated word.
-   Delimiters can be quoted with quotechar. */
-static char *skip_quoted(char **buf, const char *delimiters,
-                         const char *whitespace, char quotechar)
-{
-    char *p, *begin_word, *end_word, *end_whitespace;
-
-    begin_word = *buf;
-    end_word = begin_word + strcspn(begin_word, delimiters);
-
-    /* Check for quotechar */
-    if (end_word > begin_word) {
-        p = end_word - 1;
-        while (*p == quotechar) {
-            /* TODO (bel): it seems this code is never reached, so quotechar is actually
-               not needed - check if this code may be droped */
-
-            /* If there is anything beyond end_word, copy it */
-            if (*end_word == '\0') {
-                *p = '\0';
-                break;
-            } else {
-                size_t end_off = strcspn(end_word + 1, delimiters);
-                memmove (p, end_word, end_off + 1);
-                p += end_off; /* p must correspond to end_word - 1 */
-                end_word += end_off + 1;
-            }
-        }
-        for (p++; p < end_word; p++) {
-            *p = '\0';
-        }
-    }
-
-    if (*end_word == '\0') {
-        *buf = end_word;
-    } else {
-        end_whitespace = end_word + 1 + strspn(end_word + 1, whitespace);
-
-        for (p = end_word; p < end_whitespace; p++) {
-            *p = '\0';
-        }
-
-        *buf = end_whitespace;
-    }
-
-    return begin_word;
-}
-
-/* Simplified version of skip_quoted without quote char
-   and whitespace == delimiters */
-static char *skip(char **buf, const char *delimiters)
-{
-    return skip_quoted(buf, delimiters, delimiters, 0);
-}
-
-
-/* Return HTTP header value, or NULL if not found. */
-static const char *get_header(const struct mg_request_info *ri,
-                              const char *name)
-{
-    int i;
-
-    for (i = 0; i < ri->num_headers; i++)
-        if (!mg_strcasecmp(name, ri->http_headers[i].name))
-            return ri->http_headers[i].value;
-
-    return NULL;
-}
-
-const char *mg_get_header(const struct mg_connection *conn, const char *name)
-{
-    return get_header(&conn->request_info, name);
-}
-
-/* A helper function for traversing a comma separated list of values.
-   It returns a list pointer shifted to the next value, or NULL if the end
-   of the list found.
-   Value is stored in val vector. If value has form "x=y", then eq_val
-   vector is initialized to point to the "y" part, and val vector length
-   is adjusted to point only to "x". */
-static const char *next_option(const char *list, struct vec *val,
-                               struct vec *eq_val)
-{
-    if (list == NULL || *list == '\0') {
-        /* End of the list */
-        list = NULL;
-    } else {
-        val->ptr = list;
-        if ((list = strchr(val->ptr, ',')) != NULL) {
-            /* Comma found. Store length and shift the list ptr */
-            val->len = list - val->ptr;
-            list++;
-        } else {
-            /* This value is the last one */
-            list = val->ptr + strlen(val->ptr);
-            val->len = list - val->ptr;
-        }
-
-        if (eq_val != NULL) {
-            /* Value has form "x=y", adjust pointers and lengths
-               so that val points to "x", and eq_val points to "y". */
-            eq_val->len = 0;
-            eq_val->ptr = (const char *) memchr(val->ptr, '=', val->len);
-            if (eq_val->ptr != NULL) {
-                eq_val->ptr++;  /* Skip over '=' character */
-                eq_val->len = val->ptr + val->len - eq_val->ptr;
-                val->len = (eq_val->ptr - val->ptr) - 1;
-            }
-        }
-    }
-
-    return list;
-}
-
-/* Perform case-insensitive match of string against pattern */
-static int match_prefix(const char *pattern, int pattern_len, const char *str)
-{
-    const char *or_str;
-    int i, j, len, res;
-
-    if ((or_str = (const char *) memchr(pattern, '|', pattern_len)) != NULL) {
-        res = match_prefix(pattern, (int)(or_str - pattern), str);
-        return res > 0 ? res :
-               match_prefix(or_str + 1, (int)((pattern + pattern_len) - (or_str + 1)), str);
-    }
-
-    i = j = 0;
-    for (; i < pattern_len; i++, j++) {
-        if (pattern[i] == '?' && str[j] != '\0') {
-            continue;
-        } else if (pattern[i] == '$') {
-            return str[j] == '\0' ? j : -1;
-        } else if (pattern[i] == '*') {
-            i++;
-            if (pattern[i] == '*') {
-                i++;
-                len = (int) strlen(str + j);
-            } else {
-                len = (int) strcspn(str + j, "/");
-            }
-            if (i == pattern_len) {
-                return j + len;
-            }
-            do {
-                res = match_prefix(pattern + i, pattern_len - i, str + j + len);
-            } while (res == -1 && len-- > 0);
-            return res == -1 ? -1 : j + res + len;
-        } else if (lowercase(&pattern[i]) != lowercase(&str[j])) {
-            return -1;
-        }
-    }
-    return j;
-}
-
-/* HTTP 1.1 assumes keep alive if "Connection:" header is not set
-   This function must tolerate situations when connection info is not
-   set up, for example if request parsing failed. */
-static int should_keep_alive(const struct mg_connection *conn)
-{
-    const char *http_version = conn->request_info.http_version;
-    const char *header = mg_get_header(conn, "Connection");
-    if (conn->must_close ||
-        conn->status_code == 401 ||
-        mg_strcasecmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes") != 0 ||
-        (header != NULL && mg_strcasecmp(header, "keep-alive") != 0) ||
-        (header == NULL && http_version && 0!=strcmp(http_version, "1.1"))) {
-        return 0;
-    }
-    return 1;
-}
-
-static int should_decode_url(const struct mg_connection *conn)
-{
-    return (mg_strcasecmp(conn->ctx->config[DECODE_URL], "yes") == 0);
-}
-
-static const char *suggest_connection_header(const struct mg_connection *conn)
-{
-    return should_keep_alive(conn) ? "keep-alive" : "close";
-}
-
-static void handle_file_based_request(struct mg_connection *conn, const char *path, struct file *filep);
-static int mg_stat(struct mg_connection *conn, const char *path, struct file *filep);
-
-static const char *mg_get_response_code_text(int response_code, struct mg_connection *conn)
-{
-    switch (response_code)
-    {
-    /* RFC2616 Section 10.1 - Informational 1xx */
-    case 100: return "Continue"; /* RFC2616 Section 10.1.1 */
-    case 101: return "Switching Protocols"; /* RFC2616 Section 10.1.2 */
-    case 102: return "Processing"; /* RFC2518 Section 10.1 */
-
-    /* RFC2616 Section 10.2 - Successful 2xx */
-    case 200: return "OK"; /* RFC2616 Section 10.2.1 */
-    case 201: return "Created"; /* RFC2616 Section 10.2.2 */
-    case 202: return "Accepted"; /* RFC2616 Section 10.2.3 */
-    case 203: return "Non-Authoritative Information"; /* RFC2616 Section 10.2.4 */
-    case 204: return "No Content"; /* RFC2616 Section 10.2.5 */
-    case 205: return "Reset Content"; /* RFC2616 Section 10.2.6 */
-    case 206: return "Partial Content"; /* RFC2616 Section 10.2.7 */
-    case 207: return "Multi-Status"; /* RFC2518 Section 10.2, RFC4918 Section 11.1 */
-
-    /* RFC2616 Section 10.3 - Redirection 3xx */
-    case 300: return "Multiple Choices"; /* RFC2616 Section 10.3.1 */
-    case 301: return "Moved Permanently"; /* RFC2616 Section 10.3.2 */
-    case 302: return "Found"; /* RFC2616 Section 10.3.3 */
-    case 303: return "See Other"; /* RFC2616 Section 10.3.4 */
-    case 304: return "Not Modified"; /* RFC2616 Section 10.3.5 */
-    case 305: return "Use Proxy"; /* RFC2616 Section 10.3.6 */
-    case 307: return "Temporary Redirect"; /* RFC2616 Section 10.3.8 */
-
-    /* RFC2616 Section 10.4 - Client Error 4xx */
-    case 400: return "Bad Request"; /* RFC2616 Section 10.4.1 */
-    case 401: return "Unauthorized"; /* RFC2616 Section 10.4.2 */
-    case 402: return "Payment Required"; /* RFC2616 Section 10.4.3 */
-    case 403: return "Forbidden"; /* RFC2616 Section 10.4.4 */
-    case 404: return "Not Found"; /* RFC2616 Section 10.4.5 */
-    case 405: return "Method Not Allowed"; /* RFC2616 Section 10.4.6 */
-    case 406: return "Not Acceptable"; /* RFC2616 Section 10.4.7 */
-    case 407: return "Proxy Authentication Required"; /* RFC2616 Section 10.4.8 */
-    case 408: return "Request Time-out"; /* RFC2616 Section 10.4.9 */
-    case 409: return "Conflict"; /* RFC2616 Section 10.4.10 */
-    case 410: return "Gone"; /* RFC2616 Section 10.4.11 */
-    case 411: return "Length Required"; /* RFC2616 Section 10.4.12 */
-    case 412: return "Precondition Failed"; /* RFC2616 Section 10.4.13 */
-    case 413: return "Request Entity Too Large"; /* RFC2616 Section 10.4.14 */
-    case 414: return "Request-URI Too Large"; /* RFC2616 Section 10.4.15 */
-    case 415: return "Unsupported Media Type"; /* RFC2616 Section 10.4.16 */
-    case 416: return "Requested range not satisfiable"; /* RFC2616 Section 10.4.17 */
-    case 417: return "Expectation Failed"; /* RFC2616 Section 10.4.18 */
-    case 422: return "Unproccessable entity"; /* RFC2518 Section 10.3, RFC4918 Section 11.2 */
-    case 423: return "Locked"; /* RFC2518 Section 10.4, RFC4918 Section 11.3 */
-    case 424: return "Failed Dependency"; /* RFC2518 Section 10.5, RFC4918 Section 11.4 */
-    case 428: return "Precondition Required"; /* RFC 6585, Section 3 */
-    case 429: return "Too Many Requests"; /* RFC 6585, Section 4 */
-    case 431: return "Request Header Fields Too Large"; /* RFC 6585, Section 5 */
-
-    /* RFC2616 Section 10.5 - Server Error 5xx */
-    case 500: return "Internal Server Error"; /* RFC2616 Section 10.5.1 */
-    case 501: return "Not Implemented"; /* RFC2616 Section 10.5.2 */
-    case 502: return "Bad Gateway"; /* RFC2616 Section 10.5.3 */
-    case 503: return "Service Unavailable"; /* RFC2616 Section 10.5.4 */
-    case 504: return "Gateway Time-out"; /* RFC2616 Section 10.5.5 */
-    case 505: return "HTTP Version not supported"; /* RFC2616 Section 10.5.6 */
-    case 507: return "Insufficient Storage"; /* RFC2518 Section 10.6, , RFC4918 Section 11.5 */
-    case 511: return "Network Authentication Required"; /* RFC 6585, Section 6 */
-
-    /* Other RFCs */
-    case 426: return "Upgrade Required"; /* RFC 2817 */
-
-    /* Return codes from non normative RFCs: */
-    /* Informative and experimental RFCs, "de facto" standards due to common use, ... */
-    case 208: return "Already Reported"; /* RFC5842 Section 7.1 */
-    case 226: return "IM used"; /* RFC3229 Section 10.4.1 */
-    case 308: return "Permanent Redirect"; /* RFC7238 Section 3 */
-    case 418: return "I am a teapot"; /* RFC2324 Section 2.3.2 */
-    case 419: return "Authentication Timeout"; /* common use */
-    case 451: return "Unavailable For Legal Reasons"; /* draft-tbray-http-legally-restricted-status-05, Section 3 */
-    case 506: return "Variant Also Negotiates"; /* RFC 2295, Section 8.1 */
-    case 508: return "Loop Detected"; /* RFC5842 Section 7.1 */
-    case 510: return "Not Extended"; /* RFC 2774, Section 7 */
-
-    default:
-        /* This error code is unknown. This should not happen. */
-        if (conn) {
-            mg_cry(conn, "Unknown HTTP response code: %u", response_code);
-        }
-
-        /* Return at least a category according to RFC 2616 Section 10. */
-        if (response_code>=100 && response_code<200) {
-            /* Unknown informational status code */
-            return "Information";
-        }
-        if (response_code>=200 && response_code<300) {
-            /* Unknown success code */
-            return "Success";
-        }
-        if (response_code>=300 && response_code<400) {
-            /* Unknown redirection code */
-            return "Redirection";
-        }
-        if (response_code>=400 && response_code<500) {
-            /* Unknown request error code */
-            return "Client Error";
-        }
-        if (response_code>=500 && response_code<600) {
-            /* Unknown server error code */
-            return "Server Error";
-        }
-
-        /* Response code not even within reasonable range */
-        return "";
-    }
-}
-
-
-static void send_http_error(struct mg_connection *, int, const char *,
-                            PRINTF_FORMAT_STRING(const char *fmt), ...)
-PRINTF_ARGS(4, 5);
-
-
-static void send_http_error(struct mg_connection *conn, int status,
-                            const char *reason, const char *fmt, ...)
-{
-    char buf[MG_BUF_LEN];
-    va_list ap;
-    int len = 0, i, page_handler_found, scope;
-    char date[64];
-    time_t curtime = time(NULL);
-    const char *error_handler = NULL;
-    struct file error_page_file = STRUCT_FILE_INITIALIZER;
-    const char *error_page_file_ext, *tstr;
-
-    if (!reason) {
-        reason = mg_get_response_code_text(status, conn);
-    }
-
-    conn->status_code = status;
-    if (conn->in_error_handler ||
-        conn->ctx->callbacks.http_error == NULL ||
-        conn->ctx->callbacks.http_error(conn, status)) {
-
-        if (!conn->in_error_handler) {
-            /* Send user defined error pages, if defined */
-            error_handler = conn->ctx->config[ERROR_PAGES];
-            error_page_file_ext = conn->ctx->config[INDEX_FILES];
-            page_handler_found = 0;
-            if (error_handler != NULL) {
-                for (scope=1; (scope<=3) && !page_handler_found; scope++) {
-                    switch (scope) {
-                    case 1:
-                        len = mg_snprintf(conn, buf, sizeof(buf)-32, "%serror%03u.", error_handler, status);
-                        break;
-                    case 2:
-                        len = mg_snprintf(conn, buf, sizeof(buf)-32, "%serror%01uxx.", error_handler, status/100);
-                        break;
-                    default:
-                        len = mg_snprintf(conn, buf, sizeof(buf)-32, "%serror.", error_handler);
-                        break;
-                    }
-                    tstr = strchr(error_page_file_ext, '.');
-                    while (tstr) {
-                        for (i=1; i<32 && tstr[i]!=0 && tstr[i]!=','; i++) buf[len+i-1]=tstr[i];
-                        buf[len+i-1]=0;
-                        if (mg_stat(conn, buf, &error_page_file)) {
-                            page_handler_found = 1;
-                            break;
-                        }
-                        tstr = strchr(tstr+i, '.');
-                    }
-                }
-            }
-
-            if (page_handler_found) {
-                conn->in_error_handler = 1;
-                handle_file_based_request(conn, buf, &error_page_file);
-                conn->in_error_handler = 0;
-                return;
-            }
-        }
-
-        buf[0] = '\0';
-        gmt_time_string(date, sizeof(date), &curtime);
-
-        /* Errors 1xx, 204 and 304 MUST NOT send a body */
-        if (status > 199 && status != 204 && status != 304) {
-            len = mg_snprintf(conn, buf, sizeof(buf)-1, "Error %d: %s", status, reason);
-            buf[len] = '\n';
-            len++;
-            buf[len] = 0;
-
-            va_start(ap, fmt);
-            len += mg_vsnprintf(conn, buf + len, sizeof(buf) - len, fmt, ap);
-            va_end(ap);
-        }
-        DEBUG_TRACE("[%s]", buf);
-
-        mg_printf(conn, "HTTP/1.1 %d %s\r\n"
-                        "Content-Length: %d\r\n"
-                        "Date: %s\r\n"
-                        "Connection: %s\r\n\r\n",
-                        status, reason, len, date,
-                        suggest_connection_header(conn));
-        conn->num_bytes_sent += mg_printf(conn, "%s", buf);
-    }
-}
-
-#if defined(_WIN32) && !defined(__SYMBIAN32__)
-static int pthread_mutex_init(pthread_mutex_t *mutex, void *unused)
-{
-    (void) unused;
-    *mutex = CreateMutex(NULL, FALSE, NULL);
-    return *mutex == NULL ? -1 : 0;
-}
-
-static int pthread_mutex_destroy(pthread_mutex_t *mutex)
-{
-    return CloseHandle(*mutex) == 0 ? -1 : 0;
-}
-
-static int pthread_mutex_lock(pthread_mutex_t *mutex)
-{
-    return WaitForSingleObject(*mutex, INFINITE) == WAIT_OBJECT_0 ? 0 : -1;
-}
-
-static int pthread_mutex_trylock(pthread_mutex_t *mutex)
-{
-    switch (WaitForSingleObject(*mutex, 0)) {
-        case WAIT_OBJECT_0:
-            return 0;
-        case WAIT_TIMEOUT:
-            return -2; /* EBUSY */
-    }
-    return -1;
-}
-
-static int pthread_mutex_unlock(pthread_mutex_t *mutex)
-{
-    return ReleaseMutex(*mutex) == 0 ? -1 : 0;
-}
-
-#ifndef WIN_PTHREADS_TIME_H
-static int clock_gettime(clockid_t clk_id, struct timespec *tp)
-{
-    FILETIME ft;
-    ULARGE_INTEGER li;
-    BOOL ok = FALSE;
-    double d;
-    static double perfcnt_per_sec = 0.0;
-
-    if (tp) {
-        if (clk_id == CLOCK_REALTIME) {
-            GetSystemTimeAsFileTime(&ft);
-            li.LowPart = ft.dwLowDateTime;
-            li.HighPart = ft.dwHighDateTime;
-            li.QuadPart -= 116444736000000000; /* 1.1.1970 in filedate */
-            tp->tv_sec = (time_t)(li.QuadPart / 10000000);
-            tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
-            ok = TRUE;
-        } else if (clk_id == CLOCK_MONOTONIC) {
-            if (perfcnt_per_sec == 0.0) {
-                QueryPerformanceFrequency((LARGE_INTEGER *) &li);
-                perfcnt_per_sec = 1.0 / li.QuadPart;
-            }
-            if (perfcnt_per_sec != 0.0) {
-                QueryPerformanceCounter((LARGE_INTEGER *) &li);
-                d = li.QuadPart * perfcnt_per_sec;
-                tp->tv_sec = (time_t)d;
-                d -= tp->tv_sec;
-                tp->tv_nsec = (long)(d*1.0E9);
-                ok = TRUE;
-            }
-        }
-    }
-
-    return ok ? 0 : -1;
-}
-#endif
-
-static int pthread_cond_init(pthread_cond_t *cv, const void *unused)
-{
-    (void) unused;
-    InitializeCriticalSection(&cv->threadIdSec);
-    cv->waitingthreadcount = 0;
-    cv->waitingthreadhdls = (pthread_t *) mg_calloc(MAX_WORKER_THREADS, sizeof(pthread_t));
-    return (cv->waitingthreadhdls!=NULL) ? 0 : -1;
-}
-
-static int pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mutex, const struct timespec * abstime)
-{
-    struct mg_workerTLS * tls = (struct mg_workerTLS *)TlsGetValue(sTlsKey);
-    int ok;
-    struct timespec tsnow;
-    int64_t nsnow, nswaitabs, nswaitrel;
-    DWORD mswaitrel;
-
-    EnterCriticalSection(&cv->threadIdSec);
-    assert(cv->waitingthreadcount < MAX_WORKER_THREADS);
-    cv->waitingthreadhdls[cv->waitingthreadcount] = tls->pthread_cond_helper_mutex;
-    cv->waitingthreadcount++;
-    LeaveCriticalSection(&cv->threadIdSec);
-
-    if (abstime) {
-        clock_gettime(CLOCK_REALTIME, &tsnow);
-        nsnow = (((uint64_t)tsnow.tv_sec)*1000000000) + tsnow.tv_nsec;
-        nswaitabs = (((uint64_t)abstime->tv_sec)*1000000000) + abstime->tv_nsec;
-        nswaitrel = nswaitabs - nsnow;
-        if (nswaitrel<0) nswaitrel=0;
-        mswaitrel = (DWORD)(nswaitrel / 1000000);
-    } else {
-        mswaitrel = INFINITE;
-    }
-
-    pthread_mutex_unlock(mutex);
-    ok = (WAIT_OBJECT_0 == WaitForSingleObject(tls->pthread_cond_helper_mutex, mswaitrel));
-    pthread_mutex_lock(mutex);
-
-    return ok ? 0 : -1;
-}
-
-static int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex)
-{
-    return pthread_cond_timedwait(cv, mutex, NULL);
-}
-
-static int pthread_cond_signal(pthread_cond_t *cv)
-{
-    int i;
-    HANDLE wkup = NULL;
-    BOOL ok = FALSE;
-
-    EnterCriticalSection(&cv->threadIdSec);
-    if (cv->waitingthreadcount) {
-        wkup = cv->waitingthreadhdls[0];
-        ok = SetEvent(wkup);
-
-        for (i=1; i<cv->waitingthreadcount; i++) {
-            cv->waitingthreadhdls[i-1] = cv->waitingthreadhdls[i];
-        }
-        cv->waitingthreadcount--;
-
-        assert(ok);
-    }
-    LeaveCriticalSection(&cv->threadIdSec);
-
-    return ok ? 0 : 1;
-}
-
-static int pthread_cond_broadcast(pthread_cond_t *cv)
-{
-    EnterCriticalSection(&cv->threadIdSec);
-    while (cv->waitingthreadcount) {
-        pthread_cond_signal(cv);
-    }
-    LeaveCriticalSection(&cv->threadIdSec);
-
-    return 0;
-}
-
-static int pthread_cond_destroy(pthread_cond_t *cv)
-{
-    EnterCriticalSection(&cv->threadIdSec);
-    assert(cv->waitingthreadcount==0);
-    mg_free(cv->waitingthreadhdls);
-    cv->waitingthreadhdls = 0;
-    LeaveCriticalSection(&cv->threadIdSec);
-    DeleteCriticalSection(&cv->threadIdSec);
-
-    return 0;
-}
-
-/* For Windows, change all slashes to backslashes in path names. */
-static void change_slashes_to_backslashes(char *path)
-{
-    int i;
-
-    for (i = 0; path[i] != '\0'; i++) {
-        if (path[i] == '/')
-            path[i] = '\\';
-        /* i > 0 check is to preserve UNC paths, like \\server\file.txt */
-        if (path[i] == '\\' && i > 0)
-            while (path[i + 1] == '\\' || path[i + 1] == '/')
-                (void) memmove(path + i + 1,
-                               path + i + 2, strlen(path + i + 1));
-    }
-}
-
-/* Encode 'path' which is assumed UTF-8 string, into UNICODE string.
-   wbuf and wbuf_len is a target buffer and its length. */
-static void to_unicode(const char *path, wchar_t *wbuf, size_t wbuf_len)
-{
-    char buf[PATH_MAX], buf2[PATH_MAX];
-
-    mg_strlcpy(buf, path, sizeof(buf));
-    change_slashes_to_backslashes(buf);
-
-    /* Convert to Unicode and back. If doubly-converted string does not
-       match the original, something is fishy, reject. */
-    memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
-    MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len);
-    WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2),
-                        NULL, NULL);
-    if (strcmp(buf, buf2) != 0) {
-        wbuf[0] = L'\0';
-    }
-}
-
-#if defined(_WIN32_WCE)
-static time_t time(time_t *ptime)
-{
-    time_t t;
-    SYSTEMTIME st;
-    FILETIME ft;
-
-    GetSystemTime(&st);
-    SystemTimeToFileTime(&st, &ft);
-    t = SYS2UNIX_TIME(ft.dwLowDateTime, ft.dwHighDateTime);
-
-    if (ptime != NULL) {
-        *ptime = t;
-    }
-
-    return t;
-}
-
-static struct tm *localtime(const time_t *ptime, struct tm *ptm)
-{
-    int64_t t = ((int64_t) *ptime) * RATE_DIFF + EPOCH_DIFF;
-    FILETIME ft, lft;
-    SYSTEMTIME st;
-    TIME_ZONE_INFORMATION tzinfo;
-
-    if (ptm == NULL) {
-        return NULL;
-    }
-
-    * (int64_t *) &ft = t;
-    FileTimeToLocalFileTime(&ft, &lft);
-    FileTimeToSystemTime(&lft, &st);
-    ptm->tm_year = st.wYear - 1900;
-    ptm->tm_mon = st.wMonth - 1;
-    ptm->tm_wday = st.wDayOfWeek;
-    ptm->tm_mday = st.wDay;
-    ptm->tm_hour = st.wHour;
-    ptm->tm_min = st.wMinute;
-    ptm->tm_sec = st.wSecond;
-    ptm->tm_yday = 0; /* hope nobody uses this */
-    ptm->tm_isdst =
-        GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT ? 1 : 0;
-
-    return ptm;
-}
-
-static struct tm *gmtime(const time_t *ptime, struct tm *ptm)
-{
-    /* FIXME(lsm): fix this. */
-    return localtime(ptime, ptm);
-}
-
-static size_t strftime(char *dst, size_t dst_size, const char *fmt,
-                       const struct tm *tm)
-{
-    (void) snprintf(dst, dst_size, "implement strftime() for WinCE");
-    return 0;
-}
-#endif
-
-/* Windows happily opens files with some garbage at the end of file name.
-   For example, fopen("a.cgi    ", "r") on Windows successfully opens
-   "a.cgi", despite one would expect an error back.
-   This function returns non-0 if path ends with some garbage. */
-static int path_cannot_disclose_cgi(const char *path)
-{
-    static const char *allowed_last_characters = "_-";
-    int last = path[strlen(path) - 1];
-    return isalnum(last) || strchr(allowed_last_characters, last) != NULL;
-}
-
-static int mg_stat(struct mg_connection *conn, const char *path, struct file *filep)
-{
-    wchar_t wbuf[PATH_MAX];
-    WIN32_FILE_ATTRIBUTE_DATA info;
-
-    if (!is_file_in_memory(conn, path, filep)) {
-        to_unicode(path, wbuf, ARRAY_SIZE(wbuf));
-        if (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0) {
-            filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh);
-            filep->modification_time = SYS2UNIX_TIME(
-                                           info.ftLastWriteTime.dwLowDateTime,
-                                           info.ftLastWriteTime.dwHighDateTime);
-            filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
-            /* If file name is fishy, reset the file structure and return
-               error.
-               Note it is important to reset, not just return the error, cause
-               functions like is_file_opened() check the struct. */
-            if (!filep->is_directory && !path_cannot_disclose_cgi(path)) {
-                memset(filep, 0, sizeof(*filep));
-            }
-        }
-    }
-
-    return filep->membuf != NULL || filep->modification_time != 0;
-}
-
-static int mg_remove(const char *path)
-{
-    wchar_t wbuf[PATH_MAX];
-    to_unicode(path, wbuf, ARRAY_SIZE(wbuf));
-    return DeleteFileW(wbuf) ? 0 : -1;
-}
-
-static int mg_mkdir(const char *path, int mode)
-{
-    char buf[PATH_MAX];
-    wchar_t wbuf[PATH_MAX];
-
-    (void) mode;
-    mg_strlcpy(buf, path, sizeof(buf));
-    change_slashes_to_backslashes(buf);
-
-    (void) MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, ARRAY_SIZE(wbuf));
-
-    return CreateDirectoryW(wbuf, NULL) ? 0 : -1;
-}
-
-/* Implementation of POSIX opendir/closedir/readdir for Windows. */
-static DIR * opendir(const char *name)
-{
-    DIR *dir = NULL;
-    wchar_t wpath[PATH_MAX];
-    DWORD attrs;
-
-    if (name == NULL) {
-        SetLastError(ERROR_BAD_ARGUMENTS);
-    } else if ((dir = (DIR *) mg_malloc(sizeof(*dir))) == NULL) {
-        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-    } else {
-        to_unicode(name, wpath, ARRAY_SIZE(wpath));
-        attrs = GetFileAttributesW(wpath);
-        if (attrs != 0xFFFFFFFF &&
-            ((attrs & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)) {
-            (void) wcscat(wpath, L"\\*");
-            dir->handle = FindFirstFileW(wpath, &dir->info);
-            dir->result.d_name[0] = '\0';
-        } else {
-            mg_free(dir);
-            dir = NULL;
-        }
-    }
-
-    return dir;
-}
-
-static int closedir(DIR *dir)
-{
-    int result = 0;
-
-    if (dir != NULL) {
-        if (dir->handle != INVALID_HANDLE_VALUE)
-            result = FindClose(dir->handle) ? 0 : -1;
-
-        mg_free(dir);
-    } else {
-        result = -1;
-        SetLastError(ERROR_BAD_ARGUMENTS);
-    }
-
-    return result;
-}
-
-static struct dirent *readdir(DIR *dir)
-{
-    struct dirent *result = 0;
-
-    if (dir) {
-        if (dir->handle != INVALID_HANDLE_VALUE) {
-            result = &dir->result;
-            (void) WideCharToMultiByte(CP_UTF8, 0,
-                                       dir->info.cFileName, -1, result->d_name,
-                                       sizeof(result->d_name), NULL, NULL);
-
-            if (!FindNextFileW(dir->handle, &dir->info)) {
-                (void) FindClose(dir->handle);
-                dir->handle = INVALID_HANDLE_VALUE;
-            }
-
-        } else {
-            SetLastError(ERROR_FILE_NOT_FOUND);
-        }
-    } else {
-        SetLastError(ERROR_BAD_ARGUMENTS);
-    }
-
-    return result;
-}
-
-#ifndef HAVE_POLL
-static int poll(struct pollfd *pfd, int n, int milliseconds)
-{
-    struct timeval tv;
-    fd_set set;
-    int i, result;
-    SOCKET maxfd = 0;
-
-    tv.tv_sec = milliseconds / 1000;
-    tv.tv_usec = (milliseconds % 1000) * 1000;
-    FD_ZERO(&set);
-
-    for (i = 0; i < n; i++) {
-        FD_SET((SOCKET) pfd[i].fd, &set);
-        pfd[i].revents = 0;
-
-        if (pfd[i].fd > maxfd) {
-            maxfd = pfd[i].fd;
-        }
-    }
-
-    if ((result = select((int)maxfd + 1, &set, NULL, NULL, &tv)) > 0) {
-        for (i = 0; i < n; i++) {
-            if (FD_ISSET(pfd[i].fd, &set)) {
-                pfd[i].revents = POLLIN;
-            }
-        }
-    }
-
-    return result;
-}
-#endif /* HAVE_POLL */
-
-static void set_close_on_exec(SOCKET sock, struct mg_connection *conn /* may be null */)
-{
-    (void) conn; /* Unused. */
-    (void) SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0);
-}
-
-int mg_start_thread(mg_thread_func_t f, void *p)
-{
-#if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
-    /* Compile-time option to control stack size, e.g. -DUSE_STACK_SIZE=16384 */
-    return ((_beginthread((void (__cdecl *)(void *)) f, USE_STACK_SIZE, p) == ((uintptr_t)(-1L))) ? -1 : 0);
-#else
-    return ((_beginthread((void (__cdecl *)(void *)) f, 0, p) == ((uintptr_t)(-1L))) ? -1 : 0);
-#endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
-}
-
-/* Start a thread storing the thread context. */
-
-static int mg_start_thread_with_id(unsigned (__stdcall *f)(void *), void *p,
-                                   pthread_t *threadidptr)
-{
-    uintptr_t uip;
-    HANDLE threadhandle;
-    int result = -1;
-
-    uip = _beginthreadex(NULL, 0, (unsigned (__stdcall *)(void *)) f, p, 0,
-                         NULL);
-    threadhandle = (HANDLE) uip;
-    if ((uip != (uintptr_t)(-1L)) && (threadidptr != NULL)) {
-        *threadidptr = threadhandle;
-        result = 0;
-    }
-
-    return result;
-}
-
-/* Wait for a thread to finish. */
-
-static int mg_join_thread(pthread_t threadid)
-{
-    int result;
-    DWORD dwevent;
-
-    result = -1;
-    dwevent = WaitForSingleObject(threadid, INFINITE);
-    if (dwevent == WAIT_FAILED) {
-        int err;
-
-        err = GetLastError();
-        DEBUG_TRACE("WaitForSingleObject() failed, error %d", err);
-    } else {
-        if (dwevent == WAIT_OBJECT_0) {
-            CloseHandle(threadid);
-            result = 0;
-        }
-    }
-
-    return result;
-}
-
-static HANDLE dlopen(const char *dll_name, int flags)
-{
-    wchar_t wbuf[PATH_MAX];
-    (void) flags;
-    to_unicode(dll_name, wbuf, ARRAY_SIZE(wbuf));
-    return LoadLibraryW(wbuf);
-}
-
-static int dlclose(void *handle)
-{
-    int result;
-
-    if (FreeLibrary((HMODULE) handle) != 0) {
-        result = 0;
-    } else {
-        result = -1;
-    }
-
-    return result;
-}
-
-#if !defined(NO_CGI)
-#define SIGKILL 0
-static int kill(pid_t pid, int sig_num)
-{
-    (void) TerminateProcess(pid, sig_num);
-    (void) CloseHandle(pid);
-    return 0;
-}
-
-static void trim_trailing_whitespaces(char *s)
-{
-    char *e = s + strlen(s) - 1;
-    while (e > s && isspace(* (unsigned char *) e)) {
-        *e-- = '\0';
-    }
-}
-
-static pid_t spawn_process(struct mg_connection *conn, const char *prog,
-                           char *envblk, char *envp[], int fdin,
-                           int fdout, const char *dir)
-{
-    HANDLE me;
-    char *p, *interp, full_interp[PATH_MAX], full_dir[PATH_MAX],
-         cmdline[PATH_MAX], buf[PATH_MAX];
-    struct file file = STRUCT_FILE_INITIALIZER;
-    STARTUPINFOA si;
-    PROCESS_INFORMATION pi = { 0 };
-
-    (void) envp;
-
-    memset(&si, 0, sizeof(si));
-    si.cb = sizeof(si);
-
-    /* TODO(lsm): redirect CGI errors to the error log file */
-    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
-    si.wShowWindow = SW_HIDE;
-
-    me = GetCurrentProcess();
-    DuplicateHandle(me, (HANDLE) _get_osfhandle(fdin), me,
-                    &si.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS);
-    DuplicateHandle(me, (HANDLE) _get_osfhandle(fdout), me,
-                    &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS);
-
-    /* If CGI file is a script, try to read the interpreter line */
-    interp = conn->ctx->config[CGI_INTERPRETER];
-    if (interp == NULL) {
-        buf[0] = buf[1] = '\0';
-
-        /* Read the first line of the script into the buffer */
-        snprintf(cmdline, sizeof(cmdline), "%s%c%s", dir, '/', prog);
-        if (mg_fopen(conn, cmdline, "r", &file)) {
-            p = (char *) file.membuf;
-            mg_fgets(buf, sizeof(buf), &file, &p);
-            mg_fclose(&file);
-            buf[sizeof(buf) - 1] = '\0';
-        }
-
-        if (buf[0] == '#' && buf[1] == '!') {
-            trim_trailing_whitespaces(buf + 2);
-        } else {
-            buf[2] = '\0';
-        }
-        interp = buf + 2;
-    }
-
-    if (interp[0] != '\0') {
-        GetFullPathNameA(interp, sizeof(full_interp), full_interp, NULL);
-        interp = full_interp;
-    }
-    GetFullPathNameA(dir, sizeof(full_dir), full_dir, NULL);
-
-    mg_snprintf(conn, cmdline, sizeof(cmdline), "%s%s\"%s\\%s\"",
-                interp, interp[0] == '\0' ? "" : " ", full_dir, prog);
-
-    DEBUG_TRACE("Running [%s]", cmdline);
-    if (CreateProcessA(NULL, cmdline, NULL, NULL, TRUE,
-                       CREATE_NEW_PROCESS_GROUP, envblk, NULL, &si, &pi) == 0) {
-        mg_cry(conn, "%s: CreateProcess(%s): %ld",
-               __func__, cmdline, ERRNO);
-        pi.hProcess = (pid_t) -1;
-    }
-
-    (void) CloseHandle(si.hStdOutput);
-    (void) CloseHandle(si.hStdInput);
-    if (pi.hThread != NULL)
-        (void) CloseHandle(pi.hThread);
-
-    return (pid_t) pi.hProcess;
-}
-#endif /* !NO_CGI */
-
-static int set_non_blocking_mode(SOCKET sock)
-{
-    unsigned long on = 1;
-    return ioctlsocket(sock, FIONBIO, &on);
-}
-
-#else
-static int mg_stat(struct mg_connection *conn, const char *path,
-                   struct file *filep)
-{
-    struct stat st;
-
-    if (!is_file_in_memory(conn, path, filep) && !stat(path, &st)) {
-        filep->size = st.st_size;
-        filep->modification_time = st.st_mtime;
-        filep->is_directory = S_ISDIR(st.st_mode);
-    } else {
-        filep->modification_time = (time_t) 0;
-    }
-
-    return filep->membuf != NULL || filep->modification_time != (time_t) 0;
-}
-
-static void set_close_on_exec(int fd, struct mg_connection *conn /* may be null */)
-{
-    if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
-        if (conn) {
-            mg_cry(conn, "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s", __func__, strerror(ERRNO));
-        }
-    }
-}
-
-int mg_start_thread(mg_thread_func_t func, void *param)
-{
-    pthread_t thread_id;
-    pthread_attr_t attr;
-    int result;
-
-    (void) pthread_attr_init(&attr);
-    (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
-#if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
-    /* Compile-time option to control stack size,
-       e.g. -DUSE_STACK_SIZE=16384 */
-    (void) pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
-#endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
-
-    result = pthread_create(&thread_id, &attr, func, param);
-    pthread_attr_destroy(&attr);
-
-    return result;
-}
-
-/* Start a thread storing the thread context. */
-
-static int mg_start_thread_with_id(mg_thread_func_t func, void *param, pthread_t *threadidptr)
-{
-    pthread_t thread_id;
-    pthread_attr_t attr;
-    int result;
-
-    (void) pthread_attr_init(&attr);
-
-#if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
-    /* Compile-time option to control stack size,
-       e.g. -DUSE_STACK_SIZE=16384 */
-    (void) pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
-#endif /* defined(USE_STACK_SIZE) && USE_STACK_SIZE > 1 */
-
-    result = pthread_create(&thread_id, &attr, func, param);
-    pthread_attr_destroy(&attr);
-    if ((result == 0) && (threadidptr != NULL)) {
-        *threadidptr = thread_id;
-    }
-    return result;
-}
-
-/* Wait for a thread to finish. */
-
-static int mg_join_thread(pthread_t threadid)
-{
-    int result;
-
-    result = pthread_join(threadid, NULL);
-    return result;
-}
-
-#ifndef NO_CGI
-static pid_t spawn_process(struct mg_connection *conn, const char *prog,
-                           char *envblk, char *envp[], int fdin,
-                           int fdout, const char *dir)
-{
-    pid_t pid;
-    const char *interp;
-
-    (void) envblk;
-
-    if ((pid = fork()) == -1) {
-        /* Parent */
-        send_http_error(conn, 500, NULL,
-            "Error: Creating CGI process\nfork(): %s", strerror(ERRNO));
-    } else if (pid == 0) {
-        /* Child */
-        if (chdir(dir) != 0) {
-            mg_cry(conn, "%s: chdir(%s): %s", __func__, dir, strerror(ERRNO));
-        } else if (dup2(fdin, 0) == -1) {
-            mg_cry(conn, "%s: dup2(%d, 0): %s", __func__, fdin, strerror(ERRNO));
-        } else if (dup2(fdout, 1) == -1) {
-            mg_cry(conn, "%s: dup2(%d, 1): %s", __func__, fdout, strerror(ERRNO));
-        } else {
-            /* Not redirecting stderr to stdout, to avoid output being littered
-               with the error messages. */
-            (void) close(fdin);
-            (void) close(fdout);
-
-            /* After exec, all signal handlers are restored to their default
-               values, with one exception of SIGCHLD. According to
-               POSIX.1-2001 and Linux's implementation, SIGCHLD's handler will
-               leave unchanged after exec if it was set to be ignored. Restore
-               it to default action. */
-            signal(SIGCHLD, SIG_DFL);
-
-            interp = conn->ctx->config[CGI_INTERPRETER];
-            if (interp == NULL) {
-                (void) execle(prog, prog, NULL, envp);
-                mg_cry(conn, "%s: execle(%s): %s", __func__, prog, strerror(ERRNO));
-            } else {
-                (void) execle(interp, interp, prog, NULL, envp);
-                mg_cry(conn, "%s: execle(%s %s): %s", __func__, interp, prog,
-                       strerror(ERRNO));
-            }
-        }
-        exit(EXIT_FAILURE);
-    }
-
-    return pid;
-}
-#endif /* !NO_CGI */
-
-static int set_non_blocking_mode(SOCKET sock)
-{
-    int flags;
-
-    flags = fcntl(sock, F_GETFL, 0);
-    (void) fcntl(sock, F_SETFL, flags | O_NONBLOCK);
-
-    return 0;
-}
-#endif /* _WIN32 */
-
-/* Write data to the IO channel - opened file descriptor, socket or SSL
-   descriptor. Return number of bytes written. */
-static int64_t push(FILE *fp, SOCKET sock, SSL *ssl, const char *buf, int64_t len)
-{
-    int64_t sent;
-    int n, k;
-
-    (void) ssl;  /* Get rid of warning */
-    sent = 0;
-    while (sent < len) {
-
-        /* How many bytes we send in this iteration */
-        k = len - sent > INT_MAX ? INT_MAX : (int) (len - sent);
-
-#ifndef NO_SSL
-        if (ssl != NULL) {
-            n = SSL_write(ssl, buf + sent, k);
-        } else
-#endif
-            if (fp != NULL) {
-                n = (int) fwrite(buf + sent, 1, (size_t) k, fp);
-                if (ferror(fp))
-                    n = -1;
-            } else {
-                n = send(sock, buf + sent, (size_t) k, MSG_NOSIGNAL);
-            }
-
-        if (n <= 0)
-            break;
-
-        sent += n;
-    }
-
-    return sent;
-}
-
-/* Read from IO channel - opened file descriptor, socket, or SSL descriptor.
-   Return negative value on error, or number of bytes read on success. */
-static int pull(FILE *fp, struct mg_connection *conn, char *buf, int len)
-{
-    int nread;
-
-    if (fp != NULL) {
-        /* Use read() instead of fread(), because if we're reading from the
-           CGI pipe, fread() may block until IO buffer is filled up. We cannot
-           afford to block and must pass all read bytes immediately to the
-           client. */
-        nread = read(fileno(fp), buf, (size_t) len);
-#ifndef NO_SSL
-    } else if (conn->ssl != NULL) {
-        nread = SSL_read(conn->ssl, buf, len);
-#endif
-    } else {
-        nread = recv(conn->client.sock, buf, (size_t) len, 0);
-    }
-
-    return conn->ctx->stop_flag ? -1 : nread;
-}
-
-static int pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len)
-{
-    int n, nread = 0;
-
-    while (len > 0 && conn->ctx->stop_flag == 0) {
-        n = pull(fp, conn, buf + nread, len);
-        if (n < 0) {
-            nread = n;  /* Propagate the error */
-            break;
-        } else if (n == 0) {
-            break;  /* No more data to read */
-        } else {
-            conn->consumed_content += n;
-            nread += n;
-            len -= n;
-        }
-    }
-
-    return nread;
-}
-
-int mg_read(struct mg_connection *conn, void *buf, size_t len)
-{
-    int64_t n, buffered_len, nread;
-    int64_t len64 = (int64_t)(len > INT_MAX ? INT_MAX : len); /* since the return value is int, we may not read more bytes */
-    const char *body;
-
-    /* If Content-Length is not set for a PUT or POST request, read until socket is closed */
-    if (conn->consumed_content == 0 && conn->content_len == -1) {
-        conn->content_len = INT64_MAX;
-        conn->must_close = 1;
-    }
-
-    nread = 0;
-    if (conn->consumed_content < conn->content_len) {
-        /* Adjust number of bytes to read. */
-        int64_t left_to_read = conn->content_len - conn->consumed_content;
-        if (left_to_read < len64) {
-            /* Do not reade more than the total content length of the request. */
-            len64 = left_to_read;
-        }
-
-        /* Return buffered data */
-        buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len - conn->consumed_content;
-        if (buffered_len > 0) {
-            if (len64 < buffered_len) {
-                buffered_len = len64;
-            }
-            body = conn->buf + conn->request_len + conn->consumed_content;
-            memcpy(buf, body, (size_t) buffered_len);
-            len64 -= buffered_len;
-            conn->consumed_content += buffered_len;
-            nread += buffered_len;
-            buf = (char *) buf + buffered_len;
-        }
-
-        /* We have returned all buffered data. Read new data from the remote
-           socket. */
-        if ((n = pull_all(NULL, conn, (char *) buf, (int)len64)) >= 0) {
-            nread += n;
-        } else {
-            nread = (nread > 0 ? nread : n);
-        }
-    }
-    return (int)nread;
-}
-
-int mg_write(struct mg_connection *conn, const void *buf, size_t len)
-{
-    time_t now;
-    int64_t n, total, allowed;
-
-    if (conn->throttle > 0) {
-        if ((now = time(NULL)) != conn->last_throttle_time) {
-            conn->last_throttle_time = now;
-            conn->last_throttle_bytes = 0;
-        }
-        allowed = conn->throttle - conn->last_throttle_bytes;
-        if (allowed > (int64_t) len) {
-            allowed = len;
-        }
-        if ((total = push(NULL, conn->client.sock, conn->ssl, (const char *) buf,
-                          (int64_t) allowed)) == allowed) {
-            buf = (char *) buf + total;
-            conn->last_throttle_bytes += total;
-            while (total < (int64_t) len && conn->ctx->stop_flag == 0) {
-                allowed = conn->throttle > (int64_t) len - total ?
-                          (int64_t) len - total : conn->throttle;
-                if ((n = push(NULL, conn->client.sock, conn->ssl, (const char *) buf,
-                              (int64_t) allowed)) != allowed) {
-                    break;
-                }
-                sleep(1);
-                conn->last_throttle_bytes = allowed;
-                conn->last_throttle_time = time(NULL);
-                buf = (char *) buf + n;
-                total += n;
-            }
-        }
-    } else {
-        total = push(NULL, conn->client.sock, conn->ssl, (const char *) buf,
-                     (int64_t) len);
-    }
-    return (int) total;
-}
-
-/* Alternative alloc_vprintf() for non-compliant C runtimes */
-static int alloc_vprintf2(char **buf, const char *fmt, va_list ap)
-{
-    va_list ap_copy;
-    int size = MG_BUF_LEN;
-    int len = -1;
-
-    *buf = NULL;
-    while (len == -1) {
-        if (*buf) mg_free(*buf);
-        *buf = (char *)mg_malloc(size *= 4);
-        if (!*buf) break;
-        va_copy(ap_copy, ap);
-        len = vsnprintf(*buf, size, fmt, ap_copy);
-        va_end(ap_copy);
-    }
-
-    return len;
-}
-
-/* Print message to buffer. If buffer is large enough to hold the message,
-   return buffer. If buffer is to small, allocate large enough buffer on heap,
-   and return allocated buffer. */
-static int alloc_vprintf(char **buf, size_t size, const char *fmt, va_list ap)
-{
-    va_list ap_copy;
-    int len;
-
-    /* Windows is not standard-compliant, and vsnprintf() returns -1 if
-       buffer is too small. Also, older versions of msvcrt.dll do not have
-       _vscprintf().  However, if size is 0, vsnprintf() behaves correctly.
-       Therefore, we make two passes: on first pass, get required message
-       length.
-       On second pass, actually print the message. */
-    va_copy(ap_copy, ap);
-    len = vsnprintf(NULL, 0, fmt, ap_copy);
-    va_end(ap_copy);
-
-    if (len < 0) {
-        /* C runtime is not standard compliant, vsnprintf() returned -1.
-           Switch to alternative code path that uses incremental allocations.
-        */
-        va_copy(ap_copy, ap);
-        len = alloc_vprintf2(buf, fmt, ap);
-        va_end(ap_copy);
-    } else if (len > (int) size &&
-               (size = len + 1) > 0 &&
-               (*buf = (char *) mg_malloc(size)) == NULL) {
-        len = -1;  /* Allocation failed, mark failure */
-    } else {
-        va_copy(ap_copy, ap);
-        IGNORE_UNUSED_RESULT(vsnprintf(*buf, size, fmt, ap_copy));
-        va_end(ap_copy);
-    }
-
-    return len;
-}
-
-int mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap)
-{
-    char mem[MG_BUF_LEN], *buf = mem;
-    int len;
-
-    if ((len = alloc_vprintf(&buf, sizeof(mem), fmt, ap)) > 0) {
-        len = mg_write(conn, buf, (size_t) len);
-    }
-    if (buf != mem && buf != NULL) {
-        mg_free(buf);
-    }
-
-    return len;
-}
-
-int mg_printf(struct mg_connection *conn, const char *fmt, ...)
-{
-    va_list ap;
-    int result;
-
-    va_start(ap, fmt);
-    result = mg_vprintf(conn, fmt, ap);
-    va_end(ap);
-
-    return result;
-}
-
-int mg_url_decode(const char *src, int src_len, char *dst,
-                  int dst_len, int is_form_url_encoded)
-{
-    int i, j, a, b;
-#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
-
-    for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) {
-        if (i < src_len - 2 && src[i] == '%' &&
-            isxdigit(* (const unsigned char *) (src + i + 1)) &&
-            isxdigit(* (const unsigned char *) (src + i + 2))) {
-            a = tolower(* (const unsigned char *) (src + i + 1));
-            b = tolower(* (const unsigned char *) (src + i + 2));
-            dst[j] = (char) ((HEXTOI(a) << 4) | HEXTOI(b));
-            i += 2;
-        } else if (is_form_url_encoded && src[i] == '+') {
-            dst[j] = ' ';
-        } else {
-            dst[j] = src[i];
-        }
-    }
-
-    dst[j] = '\0'; /* Null-terminate the destination */
-
-    return i >= src_len ? j : -1;
-}
-
-int mg_get_var(const char *data, size_t data_len, const char *name,
-               char *dst, size_t dst_len)
-{
-    return mg_get_var2(data,data_len,name,dst,dst_len,0);
-}
-
-int mg_get_var2(const char *data, size_t data_len, const char *name,
-                char *dst, size_t dst_len, size_t occurrence)
-{
-    const char *p, *e, *s;
-    size_t name_len;
-    int len;
-
-    if (dst == NULL || dst_len == 0) {
-        len = -2;
-    } else if (data == NULL || name == NULL || data_len == 0) {
-        len = -1;
-        dst[0] = '\0';
-    } else {
-        name_len = strlen(name);
-        e = data + data_len;
-        len = -1;
-        dst[0] = '\0';
-
-        /* data is "var1=val1&var2=val2...". Find variable first */
-        for (p = data; p + name_len < e; p++) {
-            if ((p == data || p[-1] == '&') && p[name_len] == '=' &&
-                !mg_strncasecmp(name, p, name_len) && 0 == occurrence--) {
-
-                /* Point p to variable value */
-                p += name_len + 1;
-
-                /* Point s to the end of the value */
-                s = (const char *) memchr(p, '&', (size_t)(e - p));
-                if (s == NULL) {
-                    s = e;
-                }
-                assert(s >= p);
-
-                /* Decode variable into destination buffer */
-                len = mg_url_decode(p, (int)(s - p), dst, (int)dst_len, 1);
-
-                /* Redirect error code from -1 to -2 (destination buffer too
-                   small). */
-                if (len == -1) {
-                    len = -2;
-                }
-                break;
-            }
-        }
-    }
-
-    return len;
-}
-
-int mg_get_cookie(const char *cookie_header, const char *var_name,
-                  char *dst, size_t dst_size)
-{
-    const char *s, *p, *end;
-    int name_len, len = -1;
-
-    if (dst == NULL || dst_size == 0) {
-        len = -2;
-    } else if (var_name == NULL || (s = cookie_header) == NULL) {
-        len = -1;
-        dst[0] = '\0';
-    } else {
-        name_len = (int) strlen(var_name);
-        end = s + strlen(s);
-        dst[0] = '\0';
-
-        for (; (s = mg_strcasestr(s, var_name)) != NULL; s += name_len) {
-

<TRUNCATED>

[5/8] celix git commit: CELIX-417: Refactors CMake usage for the RSA bundles

Posted by pn...@apache.org.
http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/civetweb/src/md5.inl
----------------------------------------------------------------------
diff --git a/remote_services/civetweb/src/md5.inl b/remote_services/civetweb/src/md5.inl
new file mode 100644
index 0000000..4da933d
--- /dev/null
+++ b/remote_services/civetweb/src/md5.inl
@@ -0,0 +1,461 @@
+/*
+ * This an amalgamation of md5.c and md5.h into a single file
+ * with all static declaration to reduce linker conflicts
+ * in Civetweb.
+ *
+ * The MD5_STATIC declaration was added to facilitate static
+ * inclusion.
+ * No Face Press, LLC
+ */
+
+/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321, whose
+  text is available at
+	http://www.ietf.org/rfc/rfc1321.txt
+  The code is derived from the text of the RFC, including the test suite
+  (section A.5) but excluding the rest of Appendix A.  It does not include
+  any code or documentation that is identified in the RFC as being
+  copyrighted.
+
+  The original and principal author of md5.h is L. Peter Deutsch
+  <gh...@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2002-04-13 lpd Removed support for non-ANSI compilers; removed
+	references to Ghostscript; clarified derivation from RFC 1321;
+	now handles byte order either statically or dynamically.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+	added conditionalization for C++ compilation from Martin
+	Purschke <pu...@bnl.gov>.
+  1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+#  define md5_INCLUDED
+
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order.  If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+    md5_word_t count[2];	/* message length in bits, lsw first */
+    md5_word_t abcd[4];		/* digest buffer */
+    md5_byte_t buf[64];		/* accumulate block */
+} md5_state_t;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Initialize the algorithm. */
+MD5_STATIC void md5_init(md5_state_t *pms);
+
+/* Append a string to the message. */
+MD5_STATIC void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+/* Finish the message and return the digest. */
+MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+#ifdef __cplusplus
+}  /* end extern "C" */
+#endif
+
+#endif /* md5_INCLUDED */
+
+/*
+  Copyright (C) 1999, 2000, 2002 Aladdin Enterprises.  All rights reserved.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost@aladdin.com
+
+ */
+/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321, whose
+  text is available at
+	http://www.ietf.org/rfc/rfc1321.txt
+  The code is derived from the text of the RFC, including the test suite
+  (section A.5) but excluding the rest of Appendix A.  It does not include
+  any code or documentation that is identified in the RFC as being
+  copyrighted.
+
+  The original and principal author of md5.c is L. Peter Deutsch
+  <gh...@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+	either statically or dynamically; added missing #include <string.h>
+	in library.
+  2002-03-11 lpd Corrected argument list for main(), and added int return
+	type, in test program and T value program.
+  2002-02-21 lpd Added missing #include <stdio.h> in test program.
+  2000-07-03 lpd Patched to eliminate warnings about "constant is
+	unsigned in ANSI C, signed in traditional"; made test program
+	self-checking.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+  1999-05-03 lpd Original version.
+ */
+
+#ifndef MD5_STATIC
+#include <string.h>
+#endif
+
+#undef BYTE_ORDER	/* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#ifdef ARCH_IS_BIG_ENDIAN
+#  define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+#else
+#  define BYTE_ORDER 0
+#endif
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3    0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6    0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9    0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13    0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16    0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19    0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22    0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25    0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28    0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31    0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35    0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38    0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41    0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44    0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47    0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50    0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53    0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57    0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60    0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63    0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+    md5_word_t
+    a = pms->abcd[0], b = pms->abcd[1],
+    c = pms->abcd[2], d = pms->abcd[3];
+    md5_word_t t;
+#if BYTE_ORDER > 0
+    /* Define storage only for big-endian CPUs. */
+    md5_word_t X[16];
+#else
+    /* Define storage for little-endian or both types of CPUs. */
+    md5_word_t xbuf[16];
+    const md5_word_t *X;
+#endif
+
+    {
+#if BYTE_ORDER == 0
+        /*
+         * Determine dynamically whether this is a big-endian or
+         * little-endian machine, since we can use a more efficient
+         * algorithm on the latter.
+         */
+        static const int w = 1;
+
+        if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+#endif
+#if BYTE_ORDER <= 0		/* little-endian */
+        {
+            /*
+             * On little-endian machines, we can process properly aligned
+             * data without copying it.
+             */
+            if (!((data - (const md5_byte_t *)0) & 3)) {
+                /* data are properly aligned */
+                X = (const md5_word_t *)data;
+            } else {
+                /* not aligned */
+                memcpy(xbuf, data, 64);
+                X = xbuf;
+            }
+        }
+#endif
+#if BYTE_ORDER == 0
+        else			/* dynamic big-endian */
+#endif
+#if BYTE_ORDER >= 0		/* big-endian */
+        {
+            /*
+             * On big-endian machines, we must arrange the bytes in the
+             * right order.
+             */
+            const md5_byte_t *xp = data;
+            int i;
+
+#  if BYTE_ORDER == 0
+            X = xbuf;		/* (dynamic only) */
+#  else
+#    define xbuf X		/* (static only) */
+#  endif
+            for (i = 0; i < 16; ++i, xp += 4)
+                xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+        }
+#endif
+    }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+    /* Round 1. */
+    /* Let [abcd k s i] denote the operation
+       a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + F(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+    /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  7,  T1);
+    SET(d, a, b, c,  1, 12,  T2);
+    SET(c, d, a, b,  2, 17,  T3);
+    SET(b, c, d, a,  3, 22,  T4);
+    SET(a, b, c, d,  4,  7,  T5);
+    SET(d, a, b, c,  5, 12,  T6);
+    SET(c, d, a, b,  6, 17,  T7);
+    SET(b, c, d, a,  7, 22,  T8);
+    SET(a, b, c, d,  8,  7,  T9);
+    SET(d, a, b, c,  9, 12, T10);
+    SET(c, d, a, b, 10, 17, T11);
+    SET(b, c, d, a, 11, 22, T12);
+    SET(a, b, c, d, 12,  7, T13);
+    SET(d, a, b, c, 13, 12, T14);
+    SET(c, d, a, b, 14, 17, T15);
+    SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+    /* Round 2. */
+    /* Let [abcd k s i] denote the operation
+         a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + G(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+    /* Do the following 16 operations. */
+    SET(a, b, c, d,  1,  5, T17);
+    SET(d, a, b, c,  6,  9, T18);
+    SET(c, d, a, b, 11, 14, T19);
+    SET(b, c, d, a,  0, 20, T20);
+    SET(a, b, c, d,  5,  5, T21);
+    SET(d, a, b, c, 10,  9, T22);
+    SET(c, d, a, b, 15, 14, T23);
+    SET(b, c, d, a,  4, 20, T24);
+    SET(a, b, c, d,  9,  5, T25);
+    SET(d, a, b, c, 14,  9, T26);
+    SET(c, d, a, b,  3, 14, T27);
+    SET(b, c, d, a,  8, 20, T28);
+    SET(a, b, c, d, 13,  5, T29);
+    SET(d, a, b, c,  2,  9, T30);
+    SET(c, d, a, b,  7, 14, T31);
+    SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+    /* Round 3. */
+    /* Let [abcd k s t] denote the operation
+         a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + H(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+    /* Do the following 16 operations. */
+    SET(a, b, c, d,  5,  4, T33);
+    SET(d, a, b, c,  8, 11, T34);
+    SET(c, d, a, b, 11, 16, T35);
+    SET(b, c, d, a, 14, 23, T36);
+    SET(a, b, c, d,  1,  4, T37);
+    SET(d, a, b, c,  4, 11, T38);
+    SET(c, d, a, b,  7, 16, T39);
+    SET(b, c, d, a, 10, 23, T40);
+    SET(a, b, c, d, 13,  4, T41);
+    SET(d, a, b, c,  0, 11, T42);
+    SET(c, d, a, b,  3, 16, T43);
+    SET(b, c, d, a,  6, 23, T44);
+    SET(a, b, c, d,  9,  4, T45);
+    SET(d, a, b, c, 12, 11, T46);
+    SET(c, d, a, b, 15, 16, T47);
+    SET(b, c, d, a,  2, 23, T48);
+#undef SET
+
+    /* Round 4. */
+    /* Let [abcd k s t] denote the operation
+         a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + I(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+    /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  6, T49);
+    SET(d, a, b, c,  7, 10, T50);
+    SET(c, d, a, b, 14, 15, T51);
+    SET(b, c, d, a,  5, 21, T52);
+    SET(a, b, c, d, 12,  6, T53);
+    SET(d, a, b, c,  3, 10, T54);
+    SET(c, d, a, b, 10, 15, T55);
+    SET(b, c, d, a,  1, 21, T56);
+    SET(a, b, c, d,  8,  6, T57);
+    SET(d, a, b, c, 15, 10, T58);
+    SET(c, d, a, b,  6, 15, T59);
+    SET(b, c, d, a, 13, 21, T60);
+    SET(a, b, c, d,  4,  6, T61);
+    SET(d, a, b, c, 11, 10, T62);
+    SET(c, d, a, b,  2, 15, T63);
+    SET(b, c, d, a,  9, 21, T64);
+#undef SET
+
+    /* Then perform the following additions. (That is increment each
+       of the four registers by the value it had before this block
+       was started.) */
+    pms->abcd[0] += a;
+    pms->abcd[1] += b;
+    pms->abcd[2] += c;
+    pms->abcd[3] += d;
+}
+
+MD5_STATIC void
+md5_init(md5_state_t *pms)
+{
+    pms->count[0] = pms->count[1] = 0;
+    pms->abcd[0] = 0x67452301;
+    pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+    pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+    pms->abcd[3] = 0x10325476;
+}
+
+MD5_STATIC void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+    const md5_byte_t *p = data;
+    int left = nbytes;
+    int offset = (pms->count[0] >> 3) & 63;
+    md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+    if (nbytes <= 0)
+        return;
+
+    /* Update the message length. */
+    pms->count[1] += nbytes >> 29;
+    pms->count[0] += nbits;
+    if (pms->count[0] < nbits)
+        pms->count[1]++;
+
+    /* Process an initial partial block. */
+    if (offset) {
+        int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+        memcpy(pms->buf + offset, p, copy);
+        if (offset + copy < 64)
+            return;
+        p += copy;
+        left -= copy;
+        md5_process(pms, pms->buf);
+    }
+
+    /* Process full blocks. */
+    for (; left >= 64; p += 64, left -= 64)
+        md5_process(pms, p);
+
+    /* Process a final partial block. */
+    if (left)
+        memcpy(pms->buf, p, left);
+}
+
+MD5_STATIC void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+    static const md5_byte_t pad[64] = {
+        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+    };
+    md5_byte_t data[8];
+    int i;
+
+    /* Save the length before padding. */
+    for (i = 0; i < 8; ++i)
+        data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+    /* Pad to 56 bytes mod 64. */
+    md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+    /* Append the length. */
+    md5_append(pms, data, 8);
+    for (i = 0; i < 16; ++i)
+        digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_common/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/discovery_common/CMakeLists.txt b/remote_services/discovery_common/CMakeLists.txt
index 9388c90..5b28b13 100644
--- a/remote_services/discovery_common/CMakeLists.txt
+++ b/remote_services/discovery_common/CMakeLists.txt
@@ -18,16 +18,22 @@
 
 find_package(LibXml2 REQUIRED)
 
-add_library(discovery_common STATIC
+add_library(discovery_common OBJECT
 		src/discovery.c
 		src/discovery_activator.c
 		src/endpoint_descriptor_reader.c
 		src/endpoint_descriptor_writer.c
 		src/endpoint_discovery_poller.c
 		src/endpoint_discovery_server.c
-        src/civetweb.c
 )
-target_include_directories(discovery_common PUBLIC include)
-target_include_directories(discovery_common PRIVATE src ${LIBXML2_INCLUDE_DIR})
-target_link_libraries(discovery_common PRIVATE ${LIBXML2_LIBRARIES} Celix::framework)
-target_link_libraries(discovery_common PUBLIC Celix::log_helper Celix::remote_service_admin_api)
\ No newline at end of file
+target_include_directories(discovery_common PUBLIC
+		include src
+		$<TARGET_PROPERTY:Celix::framework,INTERFACE_INCLUDE_DIRECTORIES>
+		$<TARGET_PROPERTY:Celix::utils,INTERFACE_INCLUDE_DIRECTORIES>
+		$<TARGET_PROPERTY:Celix::log_helper,INTERFACE_INCLUDE_DIRECTORIES>
+		$<TARGET_PROPERTY:Celix::remote_service_admin_api,INTERFACE_INCLUDE_DIRECTORIES>
+		$<TARGET_PROPERTY:Celix::remote_service_admin_api,INTERFACE_INCLUDE_DIRECTORIES>
+		$<TARGET_PROPERTY:civetweb,INCLUDE_DIRECTORIES>
+		${LIBXML2_INCLUDE_DIR})
+
+add_library(Celix::discovery_common ALIAS discovery_common)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_common/include/civetweb.h
----------------------------------------------------------------------
diff --git a/remote_services/discovery_common/include/civetweb.h b/remote_services/discovery_common/include/civetweb.h
deleted file mode 100644
index 61a8e98..0000000
--- a/remote_services/discovery_common/include/civetweb.h
+++ /dev/null
@@ -1,657 +0,0 @@
-/* Copyright (c) 2013-2014 the Civetweb developers
- * Copyright (c) 2004-2013 Sergey Lyubka
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#ifndef CIVETWEB_HEADER_INCLUDED
-#define CIVETWEB_HEADER_INCLUDED
-
-#ifndef CIVETWEB_VERSION
-#define CIVETWEB_VERSION "1.7"
-#endif
-
-#ifndef CIVETWEB_API
-    #if defined(_WIN32)
-        #if defined(CIVETWEB_DLL_EXPORTS)
-            #define CIVETWEB_API __declspec(dllexport)
-        #elif defined(CIVETWEB_DLL_IMPORTS)
-            #define CIVETWEB_API __declspec(dllimport)
-        #else
-            #define CIVETWEB_API
-        #endif
-    #else
-        #define CIVETWEB_API
-    #endif
-#endif
-
-#include <stdio.h>
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-struct mg_context;     /* Handle for the HTTP service itself */
-struct mg_connection;  /* Handle for the individual connection */
-
-
-/* This structure contains information about the HTTP request. */
-struct mg_request_info {
-    const char *request_method; /* "GET", "POST", etc */
-    const char *uri;            /* URL-decoded URI */
-    const char *http_version;   /* E.g. "1.0", "1.1" */
-    const char *query_string;   /* URL part after '?', not including '?', or
-                                   NULL */
-    const char *remote_user;    /* Authenticated user, or NULL if no auth
-                                   used */
-    char remote_addr[48];       /* Client's IP address as a string. */
-    long remote_ip;             /* Client's IP address. Deprecated: use remote_addr instead */
-
-    long long content_length;   /* Length (in bytes) of the request body,
-                                   can be -1 if no length was given. */
-    int remote_port;            /* Client's port */
-    int is_ssl;                 /* 1 if SSL-ed, 0 if not */
-    void *user_data;            /* User data pointer passed to mg_start() */
-    void *conn_data;            /* Connection-specific user data */
-
-    int num_headers;            /* Number of HTTP headers */
-    struct mg_header {
-        const char *name;       /* HTTP header name */
-        const char *value;      /* HTTP header value */
-    } http_headers[64];         /* Maximum 64 headers */
-};
-
-
-/* This structure needs to be passed to mg_start(), to let civetweb know
-   which callbacks to invoke. For a detailed description, see
-   https://github.com/bel2125/civetweb/blob/master/docs/UserManual.md */
-struct mg_callbacks {
-    /* Called when civetweb has received new HTTP request.
-       If the callback returns one, it must process the request
-       by sending valid HTTP headers and a body. Civetweb will not do
-       any further processing. Otherwise it must return zero.
-       Note that since V1.7 the "begin_request" function is called
-       before an authorization check. If an authorization check is
-       required, use a request_handler instead.
-       Return value:
-         0: civetweb will process the request itself. In this case,
-            the callback must not send any data to the client.
-         1: callback already processed the request. Civetweb will
-            not send any data after the callback returned. */
-    int  (*begin_request)(struct mg_connection *);
-
-    /* Called when civetweb has finished processing request. */
-    void (*end_request)(const struct mg_connection *, int reply_status_code);
-
-    /* Called when civetweb is about to log a message. If callback returns
-       non-zero, civetweb does not log anything. */
-    int  (*log_message)(const struct mg_connection *, const char *message);
-
-    /* Called when civetweb initializes SSL library.
-       Parameters:
-         user_data: parameter user_data passed when starting the server.
-       Return value:
-         0: civetweb will set up the SSL certificate.
-         1: civetweb assumes the callback already set up the certificate.
-        -1: initializing ssl fails. */
-    int  (*init_ssl)(void *ssl_context, void *user_data);
-
-    /* Called when websocket request is received, before websocket handshake.
-       Return value:
-         0: civetweb proceeds with websocket handshake.
-         1: connection is closed immediately. */
-    int (*websocket_connect)(const struct mg_connection *);
-
-    /* Called when websocket handshake is successfully completed, and
-       connection is ready for data exchange. */
-    void (*websocket_ready)(struct mg_connection *);
-
-    /* Called when data frame has been received from the client.
-       Parameters:
-         bits: first byte of the websocket frame, see websocket RFC at
-               http://tools.ietf.org/html/rfc6455, section 5.2
-         data, data_len: payload, with mask (if any) already applied.
-       Return value:
-         1: keep this websocket connection open.
-         0: close this websocket connection. */
-    int  (*websocket_data)(struct mg_connection *, int bits,
-                           char *data, size_t data_len);
-
-    /* Called when civetweb is closing a connection.  The per-context mutex is
-       locked when this is invoked.  This is primarily useful for noting when
-       a websocket is closing and removing it from any application-maintained
-       list of clients. */
-    void (*connection_close)(struct mg_connection *);
-
-    /* Called when civetweb tries to open a file. Used to intercept file open
-       calls, and serve file data from memory instead.
-       Parameters:
-          path:     Full path to the file to open.
-          data_len: Placeholder for the file size, if file is served from
-                    memory.
-       Return value:
-         NULL: do not serve file from memory, proceed with normal file open.
-         non-NULL: pointer to the file contents in memory. data_len must be
-           initilized with the size of the memory block. */
-    const char * (*open_file)(const struct mg_connection *,
-                              const char *path, size_t *data_len);
-
-    /* Called when civetweb is about to serve Lua server page, if
-       Lua support is enabled.
-       Parameters:
-         lua_context: "lua_State *" pointer. */
-    void (*init_lua)(struct mg_connection *, void *lua_context);
-
-    /* Called when civetweb has uploaded a file to a temporary directory as a
-       result of mg_upload() call.
-       Parameters:
-         file_name: full path name to the uploaded file. */
-    void (*upload)(struct mg_connection *, const char *file_name);
-
-    /* Called when civetweb is about to send HTTP error to the client.
-       Implementing this callback allows to create custom error pages.
-       Parameters:
-         status: HTTP error status code.
-       Return value:
-         1: run civetweb error handler.
-         0: callback already handled the error. */
-    int  (*http_error)(struct mg_connection *, int status);
-
-    /* Called after civetweb context has been created, before requests
-       are processed.
-       Parameters:
-         ctx: context handle */
-    void (*init_context)(struct mg_context * ctx);
-
-    /* Called when civetweb context is deleted.
-       Parameters:
-         ctx: context handle */
-    void (*exit_context)(struct mg_context * ctx);
-};
-
-
-/* Start web server.
-
-   Parameters:
-     callbacks: mg_callbacks structure with user-defined callbacks.
-     options: NULL terminated list of option_name, option_value pairs that
-              specify Civetweb configuration parameters.
-
-   Side-effects: on UNIX, ignores SIGCHLD and SIGPIPE signals. If custom
-      processing is required for these, signal handlers must be set up
-      after calling mg_start().
-
-
-   Example:
-     const char *options[] = {
-       "document_root", "/var/www",
-       "listening_ports", "80,443s",
-       NULL
-     };
-     struct mg_context *ctx = mg_start(&my_func, NULL, options);
-
-   Refer to https://github.com/bel2125/civetweb/blob/master/docs/UserManual.md
-   for the list of valid option and their possible values.
-
-   Return:
-     web server context, or NULL on error. */
-CIVETWEB_API struct mg_context *mg_start(const struct mg_callbacks *callbacks,
-                            void *user_data,
-                            const char **configuration_options);
-
-
-/* Stop the web server.
-
-   Must be called last, when an application wants to stop the web server and
-   release all associated resources. This function blocks until all Civetweb
-   threads are stopped. Context pointer becomes invalid. */
-CIVETWEB_API void mg_stop(struct mg_context *);
-
-
-/* mg_request_handler
-
-   Called when a new request comes in.  This callback is URI based
-   and configured with mg_set_request_handler().
-
-   Parameters:
-      conn: current connection information.
-      cbdata: the callback data configured with mg_set_request_handler().
-   Returns:
-      0: the handler could not handle the request, so fall through.
-      1: the handler processed the request. */
-typedef int (* mg_request_handler)(struct mg_connection *conn, void *cbdata);
-
-
-/* mg_set_request_handler
-
-   Sets or removes a URI mapping for a request handler.
-
-   URI's are ordered and prefixed URI's are supported. For example,
-   consider two URIs: /a/b and /a
-           /a   matches /a
-           /a/b matches /a/b
-           /a/c matches /a
-
-   Parameters:
-      ctx: server context
-      uri: the URI to configure
-      handler: the callback handler to use when the URI is requested.
-               If NULL, the URI will be removed.
-      cbdata: the callback data to give to the handler when it s requested. */
-CIVETWEB_API void mg_set_request_handler(struct mg_context *ctx, const char *uri, mg_request_handler handler, void *cbdata);
-
-
-/* Get the value of particular configuration parameter.
-   The value returned is read-only. Civetweb does not allow changing
-   configuration at run time.
-   If given parameter name is not valid, NULL is returned. For valid
-   names, return value is guaranteed to be non-NULL. If parameter is not
-   set, zero-length string is returned. */
-CIVETWEB_API const char *mg_get_option(const struct mg_context *ctx, const char *name);
-
-
-/* Get context from connection. */
-CIVETWEB_API struct mg_context *mg_get_context(struct mg_connection *conn);
-
-
-/* Get user data passed to mg_start from context. */
-CIVETWEB_API void *mg_get_user_data(struct mg_context *ctx);
-
-
-#if defined(MG_LEGACY_INTERFACE)
-/* Return array of strings that represent valid configuration options.
-   For each option, option name and default value is returned, i.e. the
-   number of entries in the array equals to number_of_options x 2.
-   Array is NULL terminated. */
-/* Deprecated: Use mg_get_valid_options instead. */
-CIVETWEB_API const char **mg_get_valid_option_names(void);
-#endif
-
-
-struct mg_option {
-    const char * name;
-    int type;
-    const char * default_value;
-};
-
-enum {
-    CONFIG_TYPE_UNKNOWN = 0x0,
-    CONFIG_TYPE_NUMBER = 0x1,
-    CONFIG_TYPE_STRING = 0x2,
-    CONFIG_TYPE_FILE = 0x3,
-    CONFIG_TYPE_DIRECTORY = 0x4,
-    CONFIG_TYPE_BOOLEAN = 0x5,
-    CONFIG_TYPE_EXT_PATTERN = 0x6
-};
-
-
-/* Return array of struct mg_option, representing all valid configuration
-   options of civetweb.c.
-   The array is terminated by a NULL name option. */
-CIVETWEB_API const struct mg_option *mg_get_valid_options(void);
-
-
-/* Get the list of ports that civetweb is listening on.
-   size is the size of the ports int array and ssl int array to fill.
-   It is the caller's responsibility to make sure ports and ssl each
-   contain at least size int elements worth of memory to write into.
-   Return value is the number of ports and ssl information filled in.
-   The value returned is read-only. Civetweb does not allow changing
-   configuration at run time. */
-CIVETWEB_API size_t mg_get_ports(const struct mg_context *ctx, size_t size, int* ports, int* ssl);
-
-
-/* Add, edit or delete the entry in the passwords file.
-
-   This function allows an application to manipulate .htpasswd files on the
-   fly by adding, deleting and changing user records. This is one of the
-   several ways of implementing authentication on the server side. For another,
-   cookie-based way please refer to the examples/chat in the source tree.
-
-   If password is not NULL, entry is added (or modified if already exists).
-   If password is NULL, entry is deleted.
-
-   Return:
-     1 on success, 0 on error. */
-CIVETWEB_API int mg_modify_passwords_file(const char *passwords_file_name,
-                                          const char *domain,
-                                          const char *user,
-                                          const char *password);
-
-
-/* Return information associated with the request. */
-CIVETWEB_API struct mg_request_info *mg_get_request_info(struct mg_connection *);
-
-
-/* Send data to the client.
-   Return:
-    0   when the connection has been closed
-    -1  on error
-    >0  number of bytes written on success */
-CIVETWEB_API int mg_write(struct mg_connection *, const void *buf, size_t len);
-
-
-/* Send data to a websocket client wrapped in a websocket frame.  Uses mg_lock
-   to ensure that the transmission is not interrupted, i.e., when the
-   application is proactively communicating and responding to a request
-   simultaneously.
-
-   Send data to a websocket client wrapped in a websocket frame.
-   This function is available when civetweb is compiled with -DUSE_WEBSOCKET
-
-   Return:
-    0   when the connection has been closed
-    -1  on error
-    >0  number of bytes written on success */
-CIVETWEB_API int mg_websocket_write(struct mg_connection* conn, int opcode,
-                                    const char *data, size_t data_len);
-
-
-/* Blocks until unique access is obtained to this connection. Intended for use
-   with websockets only.
-   Invoke this before mg_write or mg_printf when communicating with a
-   websocket if your code has server-initiated communication as well as
-   communication in direct response to a message. */
-CIVETWEB_API void mg_lock_connection(struct mg_connection* conn);
-CIVETWEB_API void mg_unlock_connection(struct mg_connection* conn);
-
-#if defined(MG_LEGACY_INTERFACE)
-#define mg_lock mg_lock_connection
-#define mg_unlock mg_unlock_connection
-#endif
-
-/* Lock server context.  This lock may be used to protect ressources
-   that are shared between different connection/worker threads. */
-CIVETWEB_API void mg_lock_context(struct mg_context* ctx);
-CIVETWEB_API void mg_unlock_context(struct mg_context* ctx);
-
-
-/* Opcodes, from http://tools.ietf.org/html/rfc6455 */
-enum {
-    WEBSOCKET_OPCODE_CONTINUATION = 0x0,
-    WEBSOCKET_OPCODE_TEXT = 0x1,
-    WEBSOCKET_OPCODE_BINARY = 0x2,
-    WEBSOCKET_OPCODE_CONNECTION_CLOSE = 0x8,
-    WEBSOCKET_OPCODE_PING = 0x9,
-    WEBSOCKET_OPCODE_PONG = 0xa
-};
-
-
-/* Macros for enabling compiler-specific checks forprintf-like arguments. */
-#undef PRINTF_FORMAT_STRING
-#if defined(_MSC_VER) && _MSC_VER >= 1400
-#include <sal.h>
-#if defined(_MSC_VER) && _MSC_VER > 1400
-#define PRINTF_FORMAT_STRING(s) _Printf_format_string_ s
-#else
-#define PRINTF_FORMAT_STRING(s) __format_string s
-#endif
-#else
-#define PRINTF_FORMAT_STRING(s) s
-#endif
-
-#ifdef __GNUC__
-#define PRINTF_ARGS(x, y) __attribute__((format(printf, x, y)))
-#else
-#define PRINTF_ARGS(x, y)
-#endif
-
-/* Send data to the client usingprintf() semantics.
-   Works exactly like mg_write(), but allows to do message formatting. */
-CIVETWEB_API int mg_printf(struct mg_connection *,
-                           PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3);
-
-
-/* Send contents of the entire file together with HTTP headers. */
-CIVETWEB_API void mg_send_file(struct mg_connection *conn, const char *path);
-
-
-/* Read data from the remote end, return number of bytes read.
-   Return:
-     0     connection has been closed by peer. No more data could be read.
-     < 0   read error. No more data could be read from the connection.
-     > 0   number of bytes read into the buffer. */
-CIVETWEB_API int mg_read(struct mg_connection *, void *buf, size_t len);
-
-
-/* Get the value of particular HTTP header.
-
-   This is a helper function. It traverses request_info->http_headers array,
-   and if the header is present in the array, returns its value. If it is
-   not present, NULL is returned. */
-CIVETWEB_API const char *mg_get_header(const struct mg_connection *, const char *name);
-
-
-/* Get a value of particular form variable.
-
-   Parameters:
-     data: pointer to form-uri-encoded buffer. This could be either POST data,
-           or request_info.query_string.
-     data_len: length of the encoded data.
-     var_name: variable name to decode from the buffer
-     dst: destination buffer for the decoded variable
-     dst_len: length of the destination buffer
-
-   Return:
-     On success, length of the decoded variable.
-     On error:
-        -1 (variable not found).
-        -2 (destination buffer is NULL, zero length or too small to hold the
-            decoded variable).
-
-   Destination buffer is guaranteed to be '\0' - terminated if it is not
-   NULL or zero length. */
-CIVETWEB_API int mg_get_var(const char *data, size_t data_len,
-                            const char *var_name, char *dst, size_t dst_len);
-
-
-/* Get a value of particular form variable.
-
-   Parameters:
-     data: pointer to form-uri-encoded buffer. This could be either POST data,
-           or request_info.query_string.
-     data_len: length of the encoded data.
-     var_name: variable name to decode from the buffer
-     dst: destination buffer for the decoded variable
-     dst_len: length of the destination buffer
-     occurrence: which occurrence of the variable, 0 is the first, 1 the
-                 second...
-                this makes it possible to parse a query like
-                b=x&a=y&a=z which will have occurrence values b:0, a:0 and a:1
-
-   Return:
-     On success, length of the decoded variable.
-     On error:
-        -1 (variable not found).
-        -2 (destination buffer is NULL, zero length or too small to hold the
-            decoded variable).
-
-   Destination buffer is guaranteed to be '\0' - terminated if it is not
-   NULL or zero length. */
-CIVETWEB_API int mg_get_var2(const char *data, size_t data_len,
-                             const char *var_name, char *dst, size_t dst_len, size_t occurrence);
-
-
-/* Fetch value of certain cookie variable into the destination buffer.
-
-   Destination buffer is guaranteed to be '\0' - terminated. In case of
-   failure, dst[0] == '\0'. Note that RFC allows many occurrences of the same
-   parameter. This function returns only first occurrence.
-
-   Return:
-     On success, value length.
-     On error:
-        -1 (either "Cookie:" header is not present at all or the requested
-            parameter is not found).
-        -2 (destination buffer is NULL, zero length or too small to hold the
-            value). */
-CIVETWEB_API int mg_get_cookie(const char *cookie, const char *var_name,
-                               char *buf, size_t buf_len);
-
-
-/* Download data from the remote web server.
-     host: host name to connect to, e.g. "foo.com", or "10.12.40.1".
-     port: port number, e.g. 80.
-     use_ssl: wether to use SSL connection.
-     error_buffer, error_buffer_size: error message placeholder.
-     request_fmt,...: HTTP request.
-   Return:
-     On success, valid pointer to the new connection, suitable for mg_read().
-     On error, NULL. error_buffer contains error message.
-   Example:
-     char ebuf[100];
-     struct mg_connection *conn;
-     conn = mg_download("google.com", 80, 0, ebuf, sizeof(ebuf),
-                        "%s", "GET / HTTP/1.0\r\nHost: google.com\r\n\r\n");
- */
-CIVETWEB_API struct mg_connection *mg_download(const char *host, int port, int use_ssl,
-                                               char *error_buffer, size_t error_buffer_size,
-                                               PRINTF_FORMAT_STRING(const char *request_fmt),
-                                               ...) PRINTF_ARGS(6, 7);
-
-
-/* Close the connection opened by mg_download(). */
-CIVETWEB_API void mg_close_connection(struct mg_connection *conn);
-
-
-/* File upload functionality. Each uploaded file gets saved into a temporary
-   file and MG_UPLOAD event is sent.
-   Return number of uploaded files. */
-CIVETWEB_API int mg_upload(struct mg_connection *conn, const char *destination_dir);
-
-
-/* Convenience function -- create detached thread.
-   Return: 0 on success, non-0 on error. */
-typedef void * (*mg_thread_func_t)(void *);
-CIVETWEB_API int mg_start_thread(mg_thread_func_t f, void *p);
-
-
-/* Return builtin mime type for the given file name.
-   For unrecognized extensions, "text/plain" is returned. */
-CIVETWEB_API const char *mg_get_builtin_mime_type(const char *file_name);
-
-
-/* Return Civetweb version. */
-CIVETWEB_API const char *mg_version(void);
-
-
-/* URL-decode input buffer into destination buffer.
-   0-terminate the destination buffer.
-   form-url-encoded data differs from URI encoding in a way that it
-   uses '+' as character for space, see RFC 1866 section 8.2.1
-   http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
-   Return: length of the decoded data, or -1 if dst buffer is too small. */
-CIVETWEB_API int mg_url_decode(const char *src, int src_len, char *dst,
-                               int dst_len, int is_form_url_encoded);
-
-
-/* URL-encode input buffer into destination buffer.
-   returns the length of the resulting buffer or -1
-   is the buffer is too small. */
-CIVETWEB_API int mg_url_encode(const char *src, char *dst, size_t dst_len);
-
-
-/* MD5 hash given strings.
-   Buffer 'buf' must be 33 bytes long. Varargs is a NULL terminated list of
-   ASCIIz strings. When function returns, buf will contain human-readable
-   MD5 hash. Example:
-     char buf[33];
-     mg_md5(buf, "aa", "bb", NULL); */
-CIVETWEB_API char *mg_md5(char buf[33], ...);
-
-
-/* Print error message to the opened error log stream.
-   This utilizes the provided logging configuration.
-     conn: connection
-     fmt: format string without the line return
-     ...: variable argument list
-   Example:
-     mg_cry(conn,"i like %s", "logging"); */
-CIVETWEB_API void mg_cry(struct mg_connection *conn,
-                         PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3);
-
-
-/* utility method to compare two buffers, case incensitive. */
-CIVETWEB_API int mg_strncasecmp(const char *s1, const char *s2, size_t len);
-
-/* Connect to a websocket as a client
-   Parameters:
-     host: host to connect to, i.e. "echo.websocket.org" or "192.168.1.1" or "localhost"
-     port: server port
-     use_ssl: make a secure connection to server
-     error_buffer, error_buffer_size: buffer for an error message
-     path: server path you are trying to connect to, i.e. if connection to localhost/app, path should be "/app"
-     origin: value of the Origin HTTP header
-     data_func: callback that should be used when data is received from the server
-     user_data: user supplied argument
-
-   Return:
-     On success, valid mg_connection object.
-     On error, NULL. Se error_buffer for details.
-*/
-
-typedef int  (*websocket_data_func)(struct mg_connection *, int bits,
-                           char *data, size_t data_len);
-
-typedef void (*websocket_close_func)(struct mg_connection *);
-
-CIVETWEB_API struct mg_connection *mg_connect_websocket_client(const char *host, int port, int use_ssl,
-                                               char *error_buffer, size_t error_buffer_size,
-                                               const char *path, const char *origin,
-                                               websocket_data_func data_func, websocket_close_func close_func,
-                                               void * user_data);
-
-/* Connect to a TCP server as a client (can be used to connect to a HTTP server)
-   Parameters:
-     host: host to connect to, i.e. "www.wikipedia.org" or "192.168.1.1" or "localhost"
-     port: server port
-     use_ssl: make a secure connection to server
-     error_buffer, error_buffer_size: buffer for an error message
-
-   Return:
-     On success, valid mg_connection object.
-     On error, NULL. Se error_buffer for details.
-*/
-CIVETWEB_API struct mg_connection *mg_connect_client(const char *host, int port, int use_ssl,
-                                               char *error_buffer, size_t error_buffer_size);
-
-
-enum {
-    TIMEOUT_INFINITE = -1
-};
-
-/* Wait for a response from the server
-   Parameters:
-     conn: connection
-     ebuf, ebuf_len: error message placeholder.
-     timeout: time to wait for a response in milliseconds (if < 0 then wait forever)
-
-   Return:
-     On success, >= 0
-     On error/timeout, < 0
-*/
-CIVETWEB_API int mg_get_response(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int timeout);
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CIVETWEB_HEADER_INCLUDED */

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_common/include/discovery.h
----------------------------------------------------------------------
diff --git a/remote_services/discovery_common/include/discovery.h b/remote_services/discovery_common/include/discovery.h
index ee79caf..ede3d5e 100644
--- a/remote_services/discovery_common/include/discovery.h
+++ b/remote_services/discovery_common/include/discovery.h
@@ -27,12 +27,18 @@
 #ifndef DISCOVERY_H_
 #define DISCOVERY_H_
 
+#include "discovery_type.h"
 #include "bundle_context.h"
 #include "service_reference.h"
 
 #include "endpoint_description.h"
 #include "endpoint_listener.h"
 
+#include "endpoint_discovery_server.h"
+#include "endpoint_discovery_poller.h"
+
+#include "log_helper.h"
+
 #define DISCOVERY_SERVER_INTERFACE	"DISCOVERY_CFG_SERVER_INTERFACE"
 #define DISCOVERY_SERVER_IP 		"DISCOVERY_CFG_SERVER_IP"
 #define DISCOVERY_SERVER_PORT 		"DISCOVERY_CFG_SERVER_PORT"
@@ -40,7 +46,22 @@
 #define DISCOVERY_POLL_ENDPOINTS 	"DISCOVERY_CFG_POLL_ENDPOINTS"
 #define DISCOVERY_SERVER_MAX_EP	"DISCOVERY_CFG_SERVER_MAX_EP"
 
-typedef struct discovery *discovery_pt;
+struct discovery {
+    bundle_context_t* context;
+
+    celix_thread_mutex_t listenerReferencesMutex;
+    celix_thread_mutex_t discoveredServicesMutex;
+
+    hash_map_t* listenerReferences; //key=serviceReference, value=nop
+    hash_map_t* discoveredServices; //key=endpointId (string), value=endpoint_description_pt
+
+    endpoint_discovery_poller_t* poller;
+    endpoint_discovery_server_t* server;
+
+    log_helper_t* loghelper;
+
+    discovery_impl_t* pImpl;
+};
 
 
 /* those one could be put into a general discovery.h - file */

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_common/include/discovery_type.h
----------------------------------------------------------------------
diff --git a/remote_services/discovery_common/include/discovery_type.h b/remote_services/discovery_common/include/discovery_type.h
new file mode 100644
index 0000000..222a495
--- /dev/null
+++ b/remote_services/discovery_common/include/discovery_type.h
@@ -0,0 +1,27 @@
+/**
+ *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 DISCOVERY_TYPE_H_
+#define DISCOVERY_TYPE_H_
+
+typedef struct discovery  discovery_t;
+typedef struct discovery* discovery_pt;
+typedef struct discovery_impl discovery_impl_t;
+
+#endif //DISCOVERY_TYPE_H_
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_common/include/endpoint_discovery_poller.h
----------------------------------------------------------------------
diff --git a/remote_services/discovery_common/include/endpoint_discovery_poller.h b/remote_services/discovery_common/include/endpoint_discovery_poller.h
index d344e55..3c537f1 100644
--- a/remote_services/discovery_common/include/endpoint_discovery_poller.h
+++ b/remote_services/discovery_common/include/endpoint_discovery_poller.h
@@ -28,9 +28,12 @@
 #define ENDPOINT_DISCOVERY_POLLER_H_
 
 #include "celix_errno.h"
-#include "discovery.h"
+#include "discovery_type.h"
 #include "log_helper.h"
 
+typedef struct endpoint_discovery_poller endpoint_discovery_poller_t;
+typedef struct endpoint_discovery_poller *endpoint_discovery_poller_pt;
+
 struct endpoint_discovery_poller {
     discovery_pt discovery;
     hash_map_pt entries;
@@ -43,9 +46,7 @@ struct endpoint_discovery_poller {
     volatile bool running;
 };
 
-typedef struct endpoint_discovery_poller *endpoint_discovery_poller_pt;
-
-celix_status_t endpointDiscoveryPoller_create(discovery_pt discovery, bundle_context_pt context, endpoint_discovery_poller_pt *poller);
+celix_status_t endpointDiscoveryPoller_create(discovery_pt discovery, bundle_context_pt context, const char* defaultPollEndpoints, endpoint_discovery_poller_pt *poller);
 celix_status_t endpointDiscoveryPoller_destroy(endpoint_discovery_poller_pt poller);
 
 celix_status_t endpointDiscoveryPoller_addDiscoveryEndpoint(endpoint_discovery_poller_pt poller, char *url);

http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/discovery_common/include/endpoint_discovery_server.h
----------------------------------------------------------------------
diff --git a/remote_services/discovery_common/include/endpoint_discovery_server.h b/remote_services/discovery_common/include/endpoint_discovery_server.h
index 51082b5..d70c145 100644
--- a/remote_services/discovery_common/include/endpoint_discovery_server.h
+++ b/remote_services/discovery_common/include/endpoint_discovery_server.h
@@ -28,8 +28,9 @@
 #define ENDPOINT_DISCOVERY_SERVER_H_
 
 #include "celix_errno.h"
-#include "discovery.h"
+#include "discovery_type.h"
 
+typedef struct endpoint_discovery_server endpoint_discovery_server_t;
 typedef struct endpoint_discovery_server *endpoint_discovery_server_pt;
 
 /**
@@ -40,7 +41,13 @@ typedef struct endpoint_discovery_server *endpoint_discovery_server_pt;
  * @param server [out] the pointer to the created instance.
  * @return CELIX_SUCCESS when successful.
  */
-celix_status_t endpointDiscoveryServer_create(discovery_pt discovery, bundle_context_pt context, endpoint_discovery_server_pt *server);
+celix_status_t endpointDiscoveryServer_create(
+        discovery_pt discovery,
+        bundle_context_pt context,
+        const char* defaultServerPath,
+        const char* defaultServerPort,
+        const char* defaultServerIp,
+        endpoint_discovery_server_pt *server);
 
 /**
  * Stops and destroys a given instance of an endpoint discovery server.


[6/8] celix git commit: CELIX-417: Refactors CMake usage for the RSA bundles

Posted by pn...@apache.org.
http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/civetweb/src/civetweb.c
----------------------------------------------------------------------
diff --git a/remote_services/civetweb/src/civetweb.c b/remote_services/civetweb/src/civetweb.c
new file mode 100644
index 0000000..a6093b7
--- /dev/null
+++ b/remote_services/civetweb/src/civetweb.c
@@ -0,0 +1,7907 @@
+	/* Copyright (c) 2013-2015 the Civetweb developers
+ * Copyright (c) 2004-2013 Sergey Lyubka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#if defined(_WIN32)
+#if !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005 */
+#endif
+#else
+#ifdef __linux__
+#define _XOPEN_SOURCE 600     /* For flockfile() on Linux */
+#endif
+#ifndef _LARGEFILE_SOURCE
+#define _LARGEFILE_SOURCE     /* For fseeko(), ftello() */
+#endif
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64  /* Use 64-bit file offsets by default */
+#endif
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS  /* <inttypes.h> wants this for C++ */
+#endif
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS   /* C++ wants that for INT64_MAX */
+#endif
+#endif
+
+#if defined (_MSC_VER)
+/* 'type cast' : conversion from 'int' to 'HANDLE' of greater size */
+#pragma warning (disable : 4306 )
+/* conditional expression is constant: introduced by FD_SET(..) */
+#pragma warning (disable : 4127)
+/* non-constant aggregate initializer: issued due to missing C99 support */
+#pragma warning (disable : 4204)
+#endif
+
+/* Disable WIN32_LEAN_AND_MEAN.
+   This makes windows.h always include winsock2.h */
+#if defined(WIN32_LEAN_AND_MEAN)
+#undef WIN32_LEAN_AND_MEAN
+#endif
+
+#if defined USE_IPV6 && defined(_WIN32)
+#include <ws2tcpip.h>
+#endif
+
+#if defined(__SYMBIAN32__)
+#define NO_SSL /* SSL is not supported */
+#define NO_CGI /* CGI is not supported */
+#define PATH_MAX FILENAME_MAX
+#endif /* __SYMBIAN32__ */
+
+#ifndef IGNORE_UNUSED_RESULT
+#define IGNORE_UNUSED_RESULT(a) (void)((a) && 1)
+#endif
+
+#ifndef _WIN32_WCE /* Some ANSI #includes are not available on Windows CE */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#endif /* !_WIN32_WCE */
+
+#include <time.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#ifndef MAX_WORKER_THREADS
+#define MAX_WORKER_THREADS (1024*64)
+#endif
+
+#if defined(_WIN32) && !defined(__SYMBIAN32__) /* Windows specific */
+#if defined(_MSC_VER) && _MSC_VER <= 1400
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0400 /* To make it link in VS2005 */
+#endif
+#include <windows.h>
+typedef const char * SOCK_OPT_TYPE;
+
+#ifndef PATH_MAX
+#define PATH_MAX MAX_PATH
+#endif
+
+#ifndef _IN_PORT_T
+#ifndef in_port_t
+#define in_port_t u_short
+#endif
+#endif
+
+#ifndef _WIN32_WCE
+#include <process.h>
+#include <direct.h>
+#include <io.h>
+#else /* _WIN32_WCE */
+#define NO_CGI /* WinCE has no pipes */
+
+typedef long off_t;
+
+#define errno   GetLastError()
+#define strerror(x)  _ultoa(x, (char *) _alloca(sizeof(x) *3 ), 10)
+#endif /* _WIN32_WCE */
+
+#define MAKEUQUAD(lo, hi) ((uint64_t)(((uint32_t)(lo)) | \
+      ((uint64_t)((uint32_t)(hi))) << 32))
+#define RATE_DIFF 10000000 /* 100 nsecs */
+#define EPOCH_DIFF MAKEUQUAD(0xd53e8000, 0x019db1de)
+#define SYS2UNIX_TIME(lo, hi) \
+  (time_t) ((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF)
+
+/* Visual Studio 6 does not know __func__ or __FUNCTION__
+   The rest of MS compilers use __FUNCTION__, not C99 __func__
+   Also use _strtoui64 on modern M$ compilers */
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#define STRX(x) #x
+#define STR(x) STRX(x)
+#define __func__ __FILE__ ":" STR(__LINE__)
+#define strtoull(x, y, z) (unsigned __int64) _atoi64(x)
+#define strtoll(x, y, z) _atoi64(x)
+#else
+#define __func__  __FUNCTION__
+#define strtoull(x, y, z) _strtoui64(x, y, z)
+#define strtoll(x, y, z) _strtoi64(x, y, z)
+#endif /* _MSC_VER */
+
+#define ERRNO   GetLastError()
+#define NO_SOCKLEN_T
+#define SSL_LIB   "ssleay32.dll"
+#define CRYPTO_LIB  "libeay32.dll"
+#define O_NONBLOCK  0
+#define W_OK (2) /* http://msdn.microsoft.com/en-us/library/1w06ktdy.aspx */
+#if !defined(EWOULDBLOCK)
+#define EWOULDBLOCK  WSAEWOULDBLOCK
+#endif /* !EWOULDBLOCK */
+#define _POSIX_
+#define INT64_FMT  "I64d"
+
+#define WINCDECL __cdecl
+#define SHUT_WR 1
+#define snprintf _snprintf
+#define vsnprintf _vsnprintf
+#define access _access
+#define mg_sleep(x) Sleep(x)
+
+#define pipe(x) _pipe(x, MG_BUF_LEN, _O_BINARY)
+#ifndef popen
+#define popen(x, y) _popen(x, y)
+#endif
+#ifndef pclose
+#define pclose(x) _pclose(x)
+#endif
+#define close(x) _close(x)
+#define dlsym(x,y) GetProcAddress((HINSTANCE) (x), (y))
+#define RTLD_LAZY  0
+#define fseeko(x, y, z) _lseeki64(_fileno(x), (y), (z))
+#define fdopen(x, y) _fdopen((x), (y))
+#define write(x, y, z) _write((x), (y), (unsigned) z)
+#define read(x, y, z) _read((x), (y), (unsigned) z)
+#define flockfile(x) EnterCriticalSection(&global_log_file_lock)
+#define funlockfile(x) LeaveCriticalSection(&global_log_file_lock)
+#define sleep(x) Sleep((x) * 1000)
+#define rmdir(x) _rmdir(x)
+
+#if defined(USE_LUA) && defined(USE_WEBSOCKET)
+#define USE_TIMERS
+#endif
+
+#if !defined(va_copy)
+#define va_copy(x, y) x = y
+#endif /* !va_copy MINGW #defines va_copy */
+
+#if !defined(fileno)
+#define fileno(x) _fileno(x)
+#endif /* !fileno MINGW #defines fileno */
+
+typedef HANDLE pthread_mutex_t;
+typedef DWORD pthread_key_t;
+typedef HANDLE pthread_t;
+typedef struct {
+    CRITICAL_SECTION threadIdSec;
+    int waitingthreadcount;        /* The number of threads queued. */
+    pthread_t *waitingthreadhdls;  /* The thread handles. */
+} pthread_cond_t;
+
+#ifndef __clockid_t_defined
+typedef DWORD clockid_t;
+#endif
+#ifndef CLOCK_MONOTONIC
+#define CLOCK_MONOTONIC (1)
+#endif
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME  (2)
+#endif
+
+#ifndef _TIMESPEC_DEFINED
+struct timespec {
+    time_t   tv_sec;        /* seconds */
+    long     tv_nsec;       /* nanoseconds */
+};
+#endif
+
+#define pid_t HANDLE /* MINGW typedefs pid_t to int. Using #define here. */
+
+static int pthread_mutex_lock(pthread_mutex_t *);
+static int pthread_mutex_unlock(pthread_mutex_t *);
+static void to_unicode(const char *path, wchar_t *wbuf, size_t wbuf_len);
+struct file;
+static char *mg_fgets(char *buf, size_t size, struct file *filep, char **p);
+
+#if defined(HAVE_STDINT)
+#include <stdint.h>
+#else
+typedef unsigned int  uint32_t;
+typedef unsigned short  uint16_t;
+typedef unsigned __int64 uint64_t;
+typedef __int64   int64_t;
+#define INT64_MAX  9223372036854775807
+#endif /* HAVE_STDINT */
+
+/* POSIX dirent interface */
+struct dirent {
+    char d_name[PATH_MAX];
+};
+
+typedef struct DIR {
+    HANDLE   handle;
+    WIN32_FIND_DATAW info;
+    struct dirent  result;
+} DIR;
+
+#if !defined(USE_IPV6) && defined(_WIN32)
+#ifndef HAVE_POLL
+struct pollfd {
+    SOCKET fd;
+    short events;
+    short revents;
+};
+#define POLLIN 1
+#endif
+#endif
+
+/* Mark required libraries */
+#ifdef _MSC_VER
+#pragma comment(lib, "Ws2_32.lib")
+#endif
+
+#else    /* UNIX  specific */
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <sys/utsname.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <netdb.h>
+typedef const void * SOCK_OPT_TYPE;
+
+//#if defined(ANDROID)
+typedef unsigned short int in_port_t;
+//#endif
+
+#include <pwd.h>
+#include <unistd.h>
+#include <dirent.h>
+#if !defined(NO_SSL_DL) && !defined(NO_SSL)
+#include <dlfcn.h>
+#endif
+#include <pthread.h>
+#if defined(__MACH__)
+#define SSL_LIB   "libssl.dylib"
+#define CRYPTO_LIB  "libcrypto.dylib"
+#else
+#if !defined(SSL_LIB)
+#define SSL_LIB   "libssl.so"
+#endif
+#if !defined(CRYPTO_LIB)
+#define CRYPTO_LIB  "libcrypto.so"
+#endif
+#endif
+#ifndef O_BINARY
+#define O_BINARY  0
+#endif /* O_BINARY */
+#define closesocket(a) close(a)
+#define mg_mkdir(x, y) mkdir(x, y)
+#define mg_remove(x) remove(x)
+#define mg_sleep(x) usleep((x) * 1000)
+#define ERRNO errno
+#define INVALID_SOCKET (-1)
+#define INT64_FMT PRId64
+typedef int SOCKET;
+#define WINCDECL
+
+#endif /* End of Windows and UNIX specific includes */
+
+#ifdef _WIN32
+static CRITICAL_SECTION global_log_file_lock;
+static DWORD pthread_self(void)
+{
+    return GetCurrentThreadId();
+}
+
+int pthread_key_create(pthread_key_t *key, void (*_must_be_zero)(void*) /* destructor function not supported for windows */)
+{
+    assert(_must_be_zero == NULL);
+    if ((key!=0) && (_must_be_zero == NULL)) {
+        *key = TlsAlloc();
+        return (*key != TLS_OUT_OF_INDEXES) ? 0 : -1;
+    }
+    return -2;
+}
+
+int pthread_key_delete(pthread_key_t key)
+{
+    return TlsFree(key) ? 0 : 1;
+}
+
+int pthread_setspecific(pthread_key_t key, void * value)
+{
+    return TlsSetValue(key, value) ? 0 : 1;
+}
+
+void *pthread_getspecific(pthread_key_t key)
+{
+    return TlsGetValue(key);
+}
+#endif /* _WIN32 */
+
+
+#include "civetweb.h"
+
+#define PASSWORDS_FILE_NAME ".htpasswd"
+#define CGI_ENVIRONMENT_SIZE 4096
+#define MAX_CGI_ENVIR_VARS 64
+#define MG_BUF_LEN 8192
+#ifndef MAX_REQUEST_SIZE
+#define MAX_REQUEST_SIZE 16384
+#endif
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
+
+#if !defined(DEBUG_TRACE)
+#if defined(CWDEBUG)
+
+static void DEBUG_TRACE_FUNC(const char *func, unsigned line, PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(3, 4);
+
+static void DEBUG_TRACE_FUNC(const char *func, unsigned line, const char *fmt, ...) {
+
+  va_list args;
+  flockfile(stdout);
+ printf("*** %lu.%p.%s.%u: ",
+         (unsigned long) time(NULL), (void *) pthread_self(),
+         func, line);
+  va_start(args, fmt);
+  vprintf(fmt, args);
+  va_end(args);
+  putchar('\n');
+  fflush(stdout);
+  funlockfile(stdout);
+}
+
+#define DEBUG_TRACE(fmt, ...) DEBUG_TRACE_FUNC(__func__, __LINE__, fmt, __VA_ARGS__)
+
+#else
+#define DEBUG_TRACE(fmt, ...)
+#endif /* CWDEBUG */
+#endif /* DEBUG_TRACE */
+
+#if defined(MEMORY_DEBUGGING)
+static unsigned long blockCount = 0;
+static unsigned long totalMemUsed = 0;
+
+static void * mg_malloc_ex(size_t size, const char * file, unsigned line) {
+
+    void * data = malloc(size + sizeof(size_t));
+    void * memory = 0;
+    char mallocStr[256];
+
+    if (data) {
+        *(size_t*)data = size;
+        totalMemUsed += size;
+        blockCount++;
+        memory = (void *)(((char*)data)+sizeof(size_t));
+    }
+
+    sprintf(mallocStr, "MEM: %p %5lu alloc   %7lu %4lu --- %s:%u\n", memory, (unsigned long)size, totalMemUsed, blockCount, file, line);
+#if defined(_WIN32)
+    OutputDebugStringA(mallocStr);
+#else
+    DEBUG_TRACE("%s", mallocStr);
+#endif
+
+    return memory;
+}
+
+static void * mg_calloc_ex(size_t count, size_t size, const char * file, unsigned line) {
+
+    void * data = mg_malloc_ex(size*count, file, line);
+    if (data) memset(data, 0, size);
+
+    return data;
+}
+
+static void mg_free_ex(void * memory, const char * file, unsigned line) {
+
+    char mallocStr[256];
+    void * data = (void *)(((char*)memory)-sizeof(size_t));
+    size_t size;
+
+    if (memory) {
+        size = *(size_t*)data;
+        totalMemUsed -= size;
+        blockCount--;
+        sprintf(mallocStr, "MEM: %p %5lu free    %7lu %4lu --- %s:%u\n", memory, (unsigned long)size, totalMemUsed, blockCount, file, line);
+#if defined(_WIN32)
+        OutputDebugStringA(mallocStr);
+#else
+        DEBUG_TRACE("%s", mallocStr);
+#endif
+
+        free(data);
+    }
+}
+
+static void * mg_realloc_ex(void * memory, size_t newsize, const char * file, unsigned line) {
+
+    char mallocStr[256];
+    void * data;
+    void * _realloc;
+    size_t oldsize;
+
+    if (newsize) {
+        if (memory) {
+            data = (void *)(((char*)memory)-sizeof(size_t));
+            oldsize = *(size_t*)data;
+            _realloc = realloc(data, newsize+sizeof(size_t));
+            if (_realloc) {
+                data = _realloc;
+                totalMemUsed -= oldsize;
+                sprintf(mallocStr, "MEM: %p %5lu r-free  %7lu %4lu --- %s:%u\n", memory, (unsigned long)oldsize, totalMemUsed, blockCount, file, line);
+#if defined(_WIN32)
+                OutputDebugStringA(mallocStr);
+#else
+                DEBUG_TRACE("%s", mallocStr);
+#endif
+                totalMemUsed += newsize;
+                sprintf(mallocStr, "MEM: %p %5lu r-alloc %7lu %4lu --- %s:%u\n", memory, (unsigned long)newsize, totalMemUsed, blockCount, file, line);
+#if defined(_WIN32)
+                OutputDebugStringA(mallocStr);
+#else
+                DEBUG_TRACE("%s", mallocStr);
+#endif
+                *(size_t*)data = newsize;
+                data = (void *)(((char*)data)+sizeof(size_t));
+            } else {
+#if defined(_WIN32)
+                OutputDebugStringA("MEM: realloc failed\n");
+#else
+                DEBUG_TRACE("%s", "MEM: realloc failed\n");
+#endif
+                return _realloc;
+            }
+        } else {
+            data = mg_malloc_ex(newsize, file, line);
+        }
+    } else {
+        data = 0;
+        mg_free_ex(memory, file, line);
+    }
+
+    return data;
+}
+
+#define mg_malloc(a)      mg_malloc_ex(a, __FILE__, __LINE__)
+#define mg_calloc(a,b)    mg_calloc_ex(a, b, __FILE__, __LINE__)
+#define mg_realloc(a, b)  mg_realloc_ex(a, b, __FILE__, __LINE__)
+#define mg_free(a)        mg_free_ex(a, __FILE__, __LINE__)
+
+#else
+static __inline void * mg_malloc(size_t a)             {return malloc(a);}
+static __inline void * mg_calloc(size_t a, size_t b)   {return calloc(a, b);}
+static __inline void * mg_realloc(void * a, size_t b)  {return realloc(a, b);}
+static __inline void   mg_free(void * a)               {free(a);}
+#endif
+
+/* This following lines are just meant as a reminder to use the mg-functions for memory management */
+#ifdef malloc
+    #undef malloc
+#endif
+#ifdef calloc
+    #undef calloc
+#endif
+#ifdef realloc
+    #undef realloc
+#endif
+#ifdef free
+    #undef free
+#endif
+#define malloc  DO_NOT_USE_THIS_FUNCTION__USE_mg_malloc
+#define calloc  DO_NOT_USE_THIS_FUNCTION__USE_mg_calloc
+#define realloc DO_NOT_USE_THIS_FUNCTION__USE_mg_realloc
+#define free    DO_NOT_USE_THIS_FUNCTION__USE_mg_free
+
+
+#define MD5_STATIC static
+#include "md5.inl"
+
+/* Darwin prior to 7.0 and Win32 do not have socklen_t */
+#ifdef NO_SOCKLEN_T
+typedef int socklen_t;
+#endif /* NO_SOCKLEN_T */
+#define _DARWIN_UNLIMITED_SELECT
+
+#define IP_ADDR_STR_LEN 50  /* IPv6 hex string is 46 chars */
+
+#if !defined(MSG_NOSIGNAL)
+#define MSG_NOSIGNAL 0
+#endif
+
+#if !defined(SOMAXCONN)
+#define SOMAXCONN 100
+#endif
+
+#if !defined(PATH_MAX)
+#define PATH_MAX 4096
+#endif
+
+/* Size of the accepted socket queue */
+#if !defined(MGSQLEN)
+#define MGSQLEN 20
+#endif
+
+#if defined(NO_SSL_DL)
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#else
+/* SSL loaded dynamically from DLL.
+   I put the prototypes here to be independent from OpenSSL source
+   installation. */
+
+typedef struct ssl_st SSL;
+typedef struct ssl_method_st SSL_METHOD;
+typedef struct ssl_ctx_st SSL_CTX;
+
+struct ssl_func {
+    const char *name;   /* SSL function name */
+    void  (*ptr)(void); /* Function pointer */
+};
+
+#define SSL_free (* (void (*)(SSL *)) ssl_sw[0].ptr)
+#define SSL_accept (* (int (*)(SSL *)) ssl_sw[1].ptr)
+#define SSL_connect (* (int (*)(SSL *)) ssl_sw[2].ptr)
+#define SSL_read (* (int (*)(SSL *, void *, int)) ssl_sw[3].ptr)
+#define SSL_write (* (int (*)(SSL *, const void *,int)) ssl_sw[4].ptr)
+#define SSL_get_error (* (int (*)(SSL *, int)) ssl_sw[5].ptr)
+#define SSL_set_fd (* (int (*)(SSL *, SOCKET)) ssl_sw[6].ptr)
+#define SSL_new (* (SSL * (*)(SSL_CTX *)) ssl_sw[7].ptr)
+#define SSL_CTX_new (* (SSL_CTX * (*)(SSL_METHOD *)) ssl_sw[8].ptr)
+#define SSLv23_server_method (* (SSL_METHOD * (*)(void)) ssl_sw[9].ptr)
+#define SSL_library_init (* (int (*)(void)) ssl_sw[10].ptr)
+#define SSL_CTX_use_PrivateKey_file (* (int (*)(SSL_CTX *, \
+        const char *, int)) ssl_sw[11].ptr)
+#define SSL_CTX_use_certificate_file (* (int (*)(SSL_CTX *, \
+        const char *, int)) ssl_sw[12].ptr)
+#define SSL_CTX_set_default_passwd_cb \
+  (* (void (*)(SSL_CTX *, mg_callback_t)) ssl_sw[13].ptr)
+#define SSL_CTX_free (* (void (*)(SSL_CTX *)) ssl_sw[14].ptr)
+#define SSL_load_error_strings (* (void (*)(void)) ssl_sw[15].ptr)
+#define SSL_CTX_use_certificate_chain_file \
+  (* (int (*)(SSL_CTX *, const char *)) ssl_sw[16].ptr)
+#define SSLv23_client_method (* (SSL_METHOD * (*)(void)) ssl_sw[17].ptr)
+#define SSL_pending (* (int (*)(SSL *)) ssl_sw[18].ptr)
+#define SSL_CTX_set_verify (* (void (*)(SSL_CTX *, int, int)) ssl_sw[19].ptr)
+#define SSL_shutdown (* (int (*)(SSL *)) ssl_sw[20].ptr)
+
+#define CRYPTO_num_locks (* (int (*)(void)) crypto_sw[0].ptr)
+#define CRYPTO_set_locking_callback \
+  (* (void (*)(void (*)(int, int, const char *, int))) crypto_sw[1].ptr)
+#define CRYPTO_set_id_callback \
+  (* (void (*)(unsigned long (*)(void))) crypto_sw[2].ptr)
+#define ERR_get_error (* (unsigned long (*)(void)) crypto_sw[3].ptr)
+#define ERR_error_string (* (char * (*)(unsigned long,char *)) crypto_sw[4].ptr)
+
+/* set_ssl_option() function updates this array.
+   It loads SSL library dynamically and changes NULLs to the actual addresses
+   of respective functions. The macros above (like SSL_connect()) are really
+   just calling these functions indirectly via the pointer. */
+static struct ssl_func ssl_sw[] = {
+    {"SSL_free",   NULL},
+    {"SSL_accept",   NULL},
+    {"SSL_connect",   NULL},
+    {"SSL_read",   NULL},
+    {"SSL_write",   NULL},
+    {"SSL_get_error",  NULL},
+    {"SSL_set_fd",   NULL},
+    {"SSL_new",   NULL},
+    {"SSL_CTX_new",   NULL},
+    {"SSLv23_server_method", NULL},
+    {"SSL_library_init",  NULL},
+    {"SSL_CTX_use_PrivateKey_file", NULL},
+    {"SSL_CTX_use_certificate_file",NULL},
+    {"SSL_CTX_set_default_passwd_cb",NULL},
+    {"SSL_CTX_free",  NULL},
+    {"SSL_load_error_strings", NULL},
+    {"SSL_CTX_use_certificate_chain_file", NULL},
+    {"SSLv23_client_method", NULL},
+    {"SSL_pending", NULL},
+    {"SSL_CTX_set_verify", NULL},
+    {"SSL_shutdown",   NULL},
+    {NULL,    NULL}
+};
+
+/* Similar array as ssl_sw. These functions could be located in different
+   lib. */
+#if !defined(NO_SSL)
+static struct ssl_func crypto_sw[] = {
+    {"CRYPTO_num_locks",  NULL},
+    {"CRYPTO_set_locking_callback", NULL},
+    {"CRYPTO_set_id_callback", NULL},
+    {"ERR_get_error",  NULL},
+    {"ERR_error_string", NULL},
+    {NULL,    NULL}
+};
+#endif /* NO_SSL */
+#endif /* NO_SSL_DL */
+
+static const char *month_names[] = {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+/* Unified socket address. For IPv6 support, add IPv6 address structure
+   in the union u. */
+union usa {
+    struct sockaddr sa;
+    struct sockaddr_in sin;
+#if defined(USE_IPV6)
+    struct sockaddr_in6 sin6;
+#endif
+};
+
+/* Describes a string (chunk of memory). */
+struct vec {
+    const char *ptr;
+    size_t len;
+};
+
+struct file {
+    int is_directory;
+    time_t modification_time;
+    int64_t size;
+    FILE *fp;
+    const char *membuf;   /* Non-NULL if file data is in memory */
+    /* set to 1 if the content is gzipped
+       in which case we need a content-encoding: gzip header */
+    int gzipped;
+};
+#define STRUCT_FILE_INITIALIZER {0, 0, 0, NULL, NULL, 0}
+
+/* Describes listening socket, or socket which was accept()-ed by the master
+   thread and queued for future handling by the worker thread. */
+struct socket {
+    SOCKET sock;          /* Listening socket */
+    union usa lsa;        /* Local socket address */
+    union usa rsa;        /* Remote socket address */
+    unsigned is_ssl:1;    /* Is port SSL-ed */
+    unsigned ssl_redir:1; /* Is port supposed to redirect everything to SSL
+                             port */
+};
+
+/* NOTE(lsm): this enum shoulds be in sync with the config_options below. */
+enum {
+    CGI_EXTENSIONS, CGI_ENVIRONMENT, PUT_DELETE_PASSWORDS_FILE, CGI_INTERPRETER,
+    PROTECT_URI, AUTHENTICATION_DOMAIN, SSI_EXTENSIONS, THROTTLE,
+    ACCESS_LOG_FILE, ENABLE_DIRECTORY_LISTING, ERROR_LOG_FILE,
+    GLOBAL_PASSWORDS_FILE, INDEX_FILES, ENABLE_KEEP_ALIVE, ACCESS_CONTROL_LIST,
+    EXTRA_MIME_TYPES, LISTENING_PORTS, DOCUMENT_ROOT, SSL_CERTIFICATE,
+    NUM_THREADS, RUN_AS_USER, REWRITE, HIDE_FILES, REQUEST_TIMEOUT,
+    DECODE_URL,
+
+#if defined(USE_LUA)
+    LUA_PRELOAD_FILE, LUA_SCRIPT_EXTENSIONS, LUA_SERVER_PAGE_EXTENSIONS,
+#endif
+#if defined(USE_WEBSOCKET)
+    WEBSOCKET_ROOT,
+#endif
+#if defined(USE_LUA) && defined(USE_WEBSOCKET)
+    LUA_WEBSOCKET_EXTENSIONS,
+#endif
+    ACCESS_CONTROL_ALLOW_ORIGIN, ERROR_PAGES,
+
+    NUM_OPTIONS
+};
+
+/* Config option name, config types, default value */
+static struct mg_option config_options[] = {
+    {"cgi_pattern",                 CONFIG_TYPE_EXT_PATTERN,   "**.cgi$|**.pl$|**.php$"},
+    {"cgi_environment",             CONFIG_TYPE_STRING,        NULL},
+    {"put_delete_auth_file",        CONFIG_TYPE_FILE,          NULL},
+    {"cgi_interpreter",             CONFIG_TYPE_FILE,          NULL},
+    {"protect_uri",                 CONFIG_TYPE_STRING,        NULL},
+    {"authentication_domain",       CONFIG_TYPE_STRING,        "mydomain.com"},
+    {"ssi_pattern",                 CONFIG_TYPE_EXT_PATTERN,   "**.shtml$|**.shtm$"},
+    {"throttle",                    CONFIG_TYPE_STRING,        NULL},
+    {"access_log_file",             CONFIG_TYPE_FILE,          NULL},
+    {"enable_directory_listing",    CONFIG_TYPE_BOOLEAN,       "yes"},
+    {"error_log_file",              CONFIG_TYPE_FILE,          NULL},
+    {"global_auth_file",            CONFIG_TYPE_FILE,          NULL},
+    {"index_files",                 CONFIG_TYPE_STRING,
+#ifdef USE_LUA
+    "index.xhtml,index.html,index.htm,index.lp,index.lsp,index.lua,index.cgi,index.shtml,index.php"},
+#else
+    "index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php"},
+#endif
+    {"enable_keep_alive",           CONFIG_TYPE_BOOLEAN,       "no"},
+    {"access_control_list",         CONFIG_TYPE_STRING,        NULL},
+    {"extra_mime_types",            CONFIG_TYPE_STRING,        NULL},
+    {"listening_ports",             CONFIG_TYPE_STRING,        "8080"},
+    {"document_root",               CONFIG_TYPE_DIRECTORY,     NULL},
+    {"ssl_certificate",             CONFIG_TYPE_FILE,          NULL},
+    {"num_threads",                 CONFIG_TYPE_NUMBER,        "50"},
+    {"run_as_user",                 CONFIG_TYPE_STRING,        NULL},
+    {"url_rewrite_patterns",        CONFIG_TYPE_STRING,        NULL},
+    {"hide_files_patterns",         CONFIG_TYPE_EXT_PATTERN,   NULL},
+    {"request_timeout_ms",          CONFIG_TYPE_NUMBER,        "30000"},
+    {"decode_url",                  CONFIG_TYPE_BOOLEAN,       "yes"},
+
+#if defined(USE_LUA)
+    {"lua_preload_file",            CONFIG_TYPE_FILE,          NULL},
+    {"lua_script_pattern",          CONFIG_TYPE_EXT_PATTERN,   "**.lua$"},
+    {"lua_server_page_pattern",     CONFIG_TYPE_EXT_PATTERN,   "**.lp$|**.lsp$"},
+#endif
+#if defined(USE_WEBSOCKET)
+    {"websocket_root",              CONFIG_TYPE_DIRECTORY,     NULL},
+#endif
+#if defined(USE_LUA) && defined(USE_WEBSOCKET)
+    {"lua_websocket_pattern",       CONFIG_TYPE_EXT_PATTERN,   "**.lua$"},
+#endif
+    {"access_control_allow_origin", CONFIG_TYPE_STRING,        "*"},
+    {"error_pages",                 CONFIG_TYPE_DIRECTORY,     NULL},
+
+    {NULL, CONFIG_TYPE_UNKNOWN, NULL}
+};
+
+struct mg_request_handler_info {
+    char *uri;
+    size_t uri_len;
+    mg_request_handler handler;
+
+    void *cbdata;
+    struct mg_request_handler_info *next;
+};
+
+struct mg_context {
+    volatile int stop_flag;         /* Should we stop event loop */
+    SSL_CTX *ssl_ctx;               /* SSL context */
+    char *config[NUM_OPTIONS];      /* Civetweb configuration parameters */
+    struct mg_callbacks callbacks;  /* User-defined callback function */
+    void *user_data;                /* User-defined data */
+    int context_type;               /* 1 = server context, 2 = client context */
+
+    struct socket *listening_sockets;
+    in_port_t *listening_ports;
+    int num_listening_sockets;
+
+    volatile int num_threads;       /* Number of threads */
+    pthread_mutex_t thread_mutex;   /* Protects (max|num)_threads */
+    pthread_cond_t thread_cond;     /* Condvar for tracking workers terminations */
+
+    struct socket queue[MGSQLEN];   /* Accepted sockets */
+    volatile int sq_head;           /* Head of the socket queue */
+    volatile int sq_tail;           /* Tail of the socket queue */
+    pthread_cond_t sq_full;         /* Signaled when socket is produced */
+    pthread_cond_t sq_empty;        /* Signaled when socket is consumed */
+    pthread_t masterthreadid;       /* The master thread ID */
+    int workerthreadcount;          /* The amount of worker threads. */
+    pthread_t *workerthreadids;     /* The worker thread IDs */
+
+    unsigned long start_time;       /* Server start time, used for authentication */
+    pthread_mutex_t nonce_mutex;    /* Protects nonce_count */
+    unsigned long nonce_count;      /* Used nonces, used for authentication */
+
+    char *systemName;               /* What operating system is running */
+
+    /* linked list of uri handlers */
+    struct mg_request_handler_info *request_handlers;
+
+#if defined(USE_LUA) && defined(USE_WEBSOCKET)
+    /* linked list of shared lua websockets */
+    struct mg_shared_lua_websocket_list *shared_lua_websockets;
+#endif
+
+#ifdef USE_TIMERS
+    struct ttimers * timers;
+#endif
+};
+
+struct mg_connection {
+    struct mg_request_info request_info;
+    struct mg_context *ctx;
+    SSL *ssl;                       /* SSL descriptor */
+    SSL_CTX *client_ssl_ctx;        /* SSL context for client connections */
+    struct socket client;           /* Connected client */
+    time_t birth_time;              /* Time when request was received */
+    int64_t num_bytes_sent;         /* Total bytes sent to client */
+    int64_t content_len;            /* Content-Length header value */
+    int64_t consumed_content;       /* How many bytes of content have been read */
+    char *buf;                      /* Buffer for received data */
+    char *path_info;                /* PATH_INFO part of the URL */
+    int must_close;                 /* 1 if connection must be closed */
+    int in_error_handler;           /* 1 if in handler for user defined error pages */
+    int buf_size;                   /* Buffer size */
+    int request_len;                /* Size of the request + headers in a buffer */
+    int data_len;                   /* Total size of data in a buffer */
+    int status_code;                /* HTTP reply status code, e.g. 200 */
+    int throttle;                   /* Throttling, bytes/sec. <= 0 means no throttle */
+    time_t last_throttle_time;      /* Last time throttled data was sent */
+    int64_t last_throttle_bytes;    /* Bytes sent this second */
+    pthread_mutex_t mutex;          /* Used by mg_lock_connection/mg_unlock_connection to ensure atomic transmissions for websockets */
+#if defined(USE_LUA) && defined(USE_WEBSOCKET)
+    void * lua_websocket_state;     /* Lua_State for a websocket connection */
+#endif
+};
+
+static pthread_key_t sTlsKey;  /* Thread local storage index */
+static int sTlsInit = 0;
+
+struct mg_workerTLS {
+    int is_master;
+#if defined(_WIN32) && !defined(__SYMBIAN32__)
+    HANDLE pthread_cond_helper_mutex;
+#endif
+};
+
+/* Directory entry */
+struct de {
+    struct mg_connection *conn;
+    char *file_name;
+    struct file file;
+};
+
+#if defined(USE_WEBSOCKET)
+static int is_websocket_protocol(const struct mg_connection *conn);
+#else
+#define is_websocket_protocol(conn) (0)
+#endif
+
+int mg_atomic_inc(volatile int * addr)
+{
+    int ret;
+#if defined(_WIN32) && !defined(__SYMBIAN32__)
+    ret = InterlockedIncrement((volatile unsigned int *) addr);
+#elif defined(__GNUC__)
+    ret = __sync_add_and_fetch(addr, 1);
+#else
+    ret = (++(*addr));
+#endif
+    return ret;
+}
+
+int mg_atomic_dec(volatile int * addr)
+{
+    int ret;
+#if defined(_WIN32) && !defined(__SYMBIAN32__)
+    ret = InterlockedDecrement((volatile unsigned int *) addr);
+#elif defined(__GNUC__)
+    ret = __sync_sub_and_fetch(addr, 1);
+#else
+    ret = (--(*addr));
+#endif
+    return ret;
+}
+
+#if !defined(NO_THREAD_NAME)
+#if defined(_WIN32) && defined(_MSC_VER)
+/* Set the thread name for debugging purposes in Visual Studio
+   http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
+*/
+#pragma pack(push,8)
+typedef struct tagTHREADNAME_INFO
+{
+   DWORD dwType;     /* Must be 0x1000. */
+   LPCSTR szName;    /* Pointer to name (in user addr space). */
+   DWORD dwThreadID; /* Thread ID (-1=caller thread). */
+   DWORD dwFlags;    /* Reserved for future use, must be zero. */
+} THREADNAME_INFO;
+#pragma pack(pop)
+#elif defined(__linux__)
+#include <sys/prctl.h>
+#endif
+
+void mg_set_thread_name(const char* name)
+{
+    char threadName[16]; /* Max. thread length in Linux/OSX/.. */
+
+    if (snprintf(threadName, sizeof(threadName), "civetweb-%s", name)<0) return;
+    threadName[sizeof(threadName)-1] = 0;
+
+#if defined(_WIN32)
+#if defined(_MSC_VER)
+    /* Windows and Visual Studio Compiler */
+    __try
+    {
+        THREADNAME_INFO info;
+        info.dwType     = 0x1000;
+        info.szName     = threadName;
+        info.dwThreadID = -1;
+        info.dwFlags    = 0;
+
+        RaiseException(0x406D1388, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
+    }
+    __except(EXCEPTION_EXECUTE_HANDLER)
+    {
+    }
+#elif defined(__MINGW32__)
+   /* No option known to set thread name for MinGW */
+#endif
+#elif defined(__linux__)
+   /* Linux */
+   (void)prctl(PR_SET_NAME,threadName,0,0,0);
+#elif defined(__APPLE__) || defined(__MACH__)
+   /* OS X (TODO: test) */
+   (void)pthread_setname_np(threadName);
+#elif defined(BSD) || defined(__FreeBSD__) || defined(__OpenBSD__)
+   /* BSD (TODO: test) */
+   pthread_set_name_np(pthread_self(), threadName);
+#else
+   /* POSIX */
+   (void)pthread_setname_np(pthread_self(), threadName);
+#endif
+}
+#else /* !defined(NO_THREAD_NAME) */
+void mg_set_thread_name(const char* threadName) {}
+#endif
+
+#if defined(MG_LEGACY_INTERFACE)
+const char **mg_get_valid_option_names(void)
+{
+    static const char * data[2 * sizeof(config_options) / sizeof(config_options[0])] = {0};
+    int i;
+
+    for (i=0; config_options[i].name != NULL; i++) {
+        data[i * 2] = config_options[i].name;
+        data[i * 2 + 1] = config_options[i].default_value;
+    }
+
+    return data;
+}
+#endif
+
+const struct mg_option *mg_get_valid_options(void)
+{
+    return config_options;
+}
+
+
+static int is_file_in_memory(struct mg_connection *conn, const char *path,
+                             struct file *filep)
+{
+    size_t size = 0;
+    if ((filep->membuf = conn->ctx->callbacks.open_file == NULL ? NULL :
+                         conn->ctx->callbacks.open_file(conn, path, &size)) != NULL) {
+        /* NOTE: override filep->size only on success. Otherwise, it might
+           break constructs like if (!mg_stat() || !mg_fopen()) ... */
+        filep->size = size;
+    }
+    return filep->membuf != NULL;
+}
+
+static int is_file_opened(const struct file *filep)
+{
+    return filep->membuf != NULL || filep->fp != NULL;
+}
+
+static int mg_fopen(struct mg_connection *conn, const char *path,
+                    const char *mode, struct file *filep)
+{
+    if (!is_file_in_memory(conn, path, filep)) {
+#ifdef _WIN32
+        wchar_t wbuf[PATH_MAX], wmode[20];
+        to_unicode(path, wbuf, ARRAY_SIZE(wbuf));
+        MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, ARRAY_SIZE(wmode));
+        filep->fp = _wfopen(wbuf, wmode);
+#else
+        filep->fp = fopen(path, mode);
+#endif
+    }
+
+    return is_file_opened(filep);
+}
+
+static void mg_fclose(struct file *filep)
+{
+    if (filep != NULL && filep->fp != NULL) {
+        fclose(filep->fp);
+    }
+}
+
+static void mg_strlcpy(register char *dst, register const char *src, size_t n)
+{
+    for (; *src != '\0' && n > 1; n--) {
+        *dst++ = *src++;
+    }
+    *dst = '\0';
+}
+
+static int lowercase(const char *s)
+{
+    return tolower(* (const unsigned char *) s);
+}
+
+int mg_strncasecmp(const char *s1, const char *s2, size_t len)
+{
+    int diff = 0;
+
+    if (len > 0)
+        do {
+            diff = lowercase(s1++) - lowercase(s2++);
+        } while (diff == 0 && s1[-1] != '\0' && --len > 0);
+
+    return diff;
+}
+
+static int mg_strcasecmp(const char *s1, const char *s2)
+{
+    int diff;
+
+    do {
+        diff = lowercase(s1++) - lowercase(s2++);
+    } while (diff == 0 && s1[-1] != '\0');
+
+    return diff;
+}
+
+static char * mg_strndup(const char *ptr, size_t len)
+{
+    char *p;
+
+    if ((p = (char *) mg_malloc(len + 1)) != NULL) {
+        mg_strlcpy(p, ptr, len + 1);
+    }
+
+    return p;
+}
+
+static char * mg_strdup(const char *str)
+{
+    return mg_strndup(str, strlen(str));
+}
+
+static const char *mg_strcasestr(const char *big_str, const char *small_str)
+{
+    int i, big_len = (int)strlen(big_str), small_len = (int)strlen(small_str);
+
+    for (i = 0; i <= big_len - small_len; i++) {
+        if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) {
+            return big_str + i;
+        }
+    }
+
+    return NULL;
+}
+
+/* Like snprintf(), but never returns negative value, or a value
+   that is larger than a supplied buffer.
+   Thanks to Adam Zeldis to pointing snprintf()-caused vulnerability
+   in his audit report. */
+static int mg_vsnprintf(struct mg_connection *conn, char *buf, size_t buflen,
+                        const char *fmt, va_list ap)
+{
+    int n;
+
+    if (buflen == 0)
+        return 0;
+
+    n = vsnprintf(buf, buflen, fmt, ap);
+
+    if (n < 0) {
+        mg_cry(conn, "vsnprintf error");
+        n = 0;
+    } else if (n >= (int) buflen) {
+        mg_cry(conn, "truncating vsnprintf buffer: [%.*s]",
+               n > 200 ? 200 : n, buf);
+        n = (int) buflen - 1;
+    }
+    buf[n] = '\0';
+
+    return n;
+}
+
+static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen,
+                       PRINTF_FORMAT_STRING(const char *fmt), ...)
+PRINTF_ARGS(4, 5);
+
+static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen,
+                       const char *fmt, ...)
+{
+    va_list ap;
+    int n;
+
+    va_start(ap, fmt);
+    n = mg_vsnprintf(conn, buf, buflen, fmt, ap);
+    va_end(ap);
+
+    return n;
+}
+
+static int get_option_index(const char *name)
+{
+    int i;
+
+    for (i = 0; config_options[i].name != NULL; i++) {
+        if (strcmp(config_options[i].name, name) == 0) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+const char *mg_get_option(const struct mg_context *ctx, const char *name)
+{
+    int i;
+    if ((i = get_option_index(name)) == -1) {
+        return NULL;
+    } else if (ctx->config[i] == NULL) {
+        return "";
+    } else {
+        return ctx->config[i];
+    }
+}
+
+struct mg_context *mg_get_context(struct mg_connection * conn)
+{
+    return (conn == NULL) ? (struct mg_context *)NULL : (conn->ctx);
+}
+
+void *mg_get_user_data(struct mg_context *ctx)
+{
+    return (ctx == NULL) ? NULL : ctx->user_data;
+}
+
+size_t mg_get_ports(const struct mg_context *ctx, size_t size, int* ports, int* ssl)
+{
+    size_t i;
+    for (i = 0; i < size && i < (size_t)ctx->num_listening_sockets; i++)
+    {
+        ssl[i] = ctx->listening_sockets[i].is_ssl;
+        ports[i] = ctx->listening_ports[i];
+    }
+    return i;
+}
+
+static void sockaddr_to_string(char *buf, size_t len,
+                               const union usa *usa)
+{
+    buf[0] = '\0';
+#if defined(USE_IPV6)
+    inet_ntop(usa->sa.sa_family, usa->sa.sa_family == AF_INET ?
+              (void *) &usa->sin.sin_addr :
+              (void *) &usa->sin6.sin6_addr, buf, len);
+#elif defined(_WIN32)
+    /* Only Windows Vista (and newer) have inet_ntop() */
+    mg_strlcpy(buf, inet_ntoa(usa->sin.sin_addr), len);
+#else
+    inet_ntop(usa->sa.sa_family, (void *) &usa->sin.sin_addr, buf, len);
+#endif
+}
+
+/* Convert time_t to a string. According to RFC2616, Sec 14.18, this must be included in all responses other than 100, 101, 5xx. */
+static void gmt_time_string(char *buf, size_t buf_len, time_t *t)
+{
+    struct tm *tm;
+
+    tm = gmtime(t);
+    if (tm != NULL) {
+        strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", tm);
+    } else {
+        mg_strlcpy(buf, "Thu, 01 Jan 1970 00:00:00 GMT", buf_len);
+        buf[buf_len - 1] = '\0';
+    }
+}
+
+/* Print error message to the opened error log stream. */
+void mg_cry(struct mg_connection *conn, const char *fmt, ...)
+{
+    char buf[MG_BUF_LEN], src_addr[IP_ADDR_STR_LEN];
+    va_list ap;
+    FILE *fp;
+    time_t timestamp;
+
+    va_start(ap, fmt);
+    IGNORE_UNUSED_RESULT(vsnprintf(buf, sizeof(buf), fmt, ap));
+    va_end(ap);
+
+    /* Do not lock when getting the callback value, here and below.
+       I suppose this is fine, since function cannot disappear in the
+       same way string option can. */
+    if (conn->ctx->callbacks.log_message == NULL ||
+        conn->ctx->callbacks.log_message(conn, buf) == 0) {
+        fp = conn->ctx->config[ERROR_LOG_FILE] == NULL ? NULL :
+             fopen(conn->ctx->config[ERROR_LOG_FILE], "a+");
+
+        if (fp != NULL) {
+            flockfile(fp);
+            timestamp = time(NULL);
+
+            sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
+            fprintf(fp, "[%010lu] [error] [client %s] ", (unsigned long) timestamp,
+                    src_addr);
+
+            if (conn->request_info.request_method != NULL) {
+                fprintf(fp, "%s %s: ", conn->request_info.request_method,
+                        conn->request_info.uri);
+            }
+
+            fprintf(fp, "%s", buf);
+            fputc('\n', fp);
+            funlockfile(fp);
+            fclose(fp);
+        }
+    }
+}
+
+/* Return fake connection structure. Used for logging, if connection
+   is not applicable at the moment of logging. */
+static struct mg_connection *fc(struct mg_context *ctx)
+{
+    static struct mg_connection fake_connection;
+    fake_connection.ctx = ctx;
+    return &fake_connection;
+}
+
+const char *mg_version(void)
+{
+    return CIVETWEB_VERSION;
+}
+
+struct mg_request_info *mg_get_request_info(struct mg_connection *conn)
+{
+    return &conn->request_info;
+}
+
+/* Skip the characters until one of the delimiters characters found.
+   0-terminate resulting word. Skip the delimiter and following whitespaces.
+   Advance pointer to buffer to the next word. Return found 0-terminated word.
+   Delimiters can be quoted with quotechar. */
+static char *skip_quoted(char **buf, const char *delimiters,
+                         const char *whitespace, char quotechar)
+{
+    char *p, *begin_word, *end_word, *end_whitespace;
+
+    begin_word = *buf;
+    end_word = begin_word + strcspn(begin_word, delimiters);
+
+    /* Check for quotechar */
+    if (end_word > begin_word) {
+        p = end_word - 1;
+        while (*p == quotechar) {
+            /* TODO (bel): it seems this code is never reached, so quotechar is actually
+               not needed - check if this code may be droped */
+
+            /* If there is anything beyond end_word, copy it */
+            if (*end_word == '\0') {
+                *p = '\0';
+                break;
+            } else {
+                size_t end_off = strcspn(end_word + 1, delimiters);
+                memmove (p, end_word, end_off + 1);
+                p += end_off; /* p must correspond to end_word - 1 */
+                end_word += end_off + 1;
+            }
+        }
+        for (p++; p < end_word; p++) {
+            *p = '\0';
+        }
+    }
+
+    if (*end_word == '\0') {
+        *buf = end_word;
+    } else {
+        end_whitespace = end_word + 1 + strspn(end_word + 1, whitespace);
+
+        for (p = end_word; p < end_whitespace; p++) {
+            *p = '\0';
+        }
+
+        *buf = end_whitespace;
+    }
+
+    return begin_word;
+}
+
+/* Simplified version of skip_quoted without quote char
+   and whitespace == delimiters */
+static char *skip(char **buf, const char *delimiters)
+{
+    return skip_quoted(buf, delimiters, delimiters, 0);
+}
+
+
+/* Return HTTP header value, or NULL if not found. */
+static const char *get_header(const struct mg_request_info *ri,
+                              const char *name)
+{
+    int i;
+
+    for (i = 0; i < ri->num_headers; i++)
+        if (!mg_strcasecmp(name, ri->http_headers[i].name))
+            return ri->http_headers[i].value;
+
+    return NULL;
+}
+
+const char *mg_get_header(const struct mg_connection *conn, const char *name)
+{
+    return get_header(&conn->request_info, name);
+}
+
+/* A helper function for traversing a comma separated list of values.
+   It returns a list pointer shifted to the next value, or NULL if the end
+   of the list found.
+   Value is stored in val vector. If value has form "x=y", then eq_val
+   vector is initialized to point to the "y" part, and val vector length
+   is adjusted to point only to "x". */
+static const char *next_option(const char *list, struct vec *val,
+                               struct vec *eq_val)
+{
+    if (list == NULL || *list == '\0') {
+        /* End of the list */
+        list = NULL;
+    } else {
+        val->ptr = list;
+        if ((list = strchr(val->ptr, ',')) != NULL) {
+            /* Comma found. Store length and shift the list ptr */
+            val->len = list - val->ptr;
+            list++;
+        } else {
+            /* This value is the last one */
+            list = val->ptr + strlen(val->ptr);
+            val->len = list - val->ptr;
+        }
+
+        if (eq_val != NULL) {
+            /* Value has form "x=y", adjust pointers and lengths
+               so that val points to "x", and eq_val points to "y". */
+            eq_val->len = 0;
+            eq_val->ptr = (const char *) memchr(val->ptr, '=', val->len);
+            if (eq_val->ptr != NULL) {
+                eq_val->ptr++;  /* Skip over '=' character */
+                eq_val->len = val->ptr + val->len - eq_val->ptr;
+                val->len = (eq_val->ptr - val->ptr) - 1;
+            }
+        }
+    }
+
+    return list;
+}
+
+/* Perform case-insensitive match of string against pattern */
+static int match_prefix(const char *pattern, int pattern_len, const char *str)
+{
+    const char *or_str;
+    int i, j, len, res;
+
+    if ((or_str = (const char *) memchr(pattern, '|', pattern_len)) != NULL) {
+        res = match_prefix(pattern, (int)(or_str - pattern), str);
+        return res > 0 ? res :
+               match_prefix(or_str + 1, (int)((pattern + pattern_len) - (or_str + 1)), str);
+    }
+
+    i = j = 0;
+    for (; i < pattern_len; i++, j++) {
+        if (pattern[i] == '?' && str[j] != '\0') {
+            continue;
+        } else if (pattern[i] == '$') {
+            return str[j] == '\0' ? j : -1;
+        } else if (pattern[i] == '*') {
+            i++;
+            if (pattern[i] == '*') {
+                i++;
+                len = (int) strlen(str + j);
+            } else {
+                len = (int) strcspn(str + j, "/");
+            }
+            if (i == pattern_len) {
+                return j + len;
+            }
+            do {
+                res = match_prefix(pattern + i, pattern_len - i, str + j + len);
+            } while (res == -1 && len-- > 0);
+            return res == -1 ? -1 : j + res + len;
+        } else if (lowercase(&pattern[i]) != lowercase(&str[j])) {
+            return -1;
+        }
+    }
+    return j;
+}
+
+/* HTTP 1.1 assumes keep alive if "Connection:" header is not set
+   This function must tolerate situations when connection info is not
+   set up, for example if request parsing failed. */
+static int should_keep_alive(const struct mg_connection *conn)
+{
+    const char *http_version = conn->request_info.http_version;
+    const char *header = mg_get_header(conn, "Connection");
+    if (conn->must_close ||
+        conn->status_code == 401 ||
+        mg_strcasecmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes") != 0 ||
+        (header != NULL && mg_strcasecmp(header, "keep-alive") != 0) ||
+        (header == NULL && http_version && 0!=strcmp(http_version, "1.1"))) {
+        return 0;
+    }
+    return 1;
+}
+
+static int should_decode_url(const struct mg_connection *conn)
+{
+    return (mg_strcasecmp(conn->ctx->config[DECODE_URL], "yes") == 0);
+}
+
+static const char *suggest_connection_header(const struct mg_connection *conn)
+{
+    return should_keep_alive(conn) ? "keep-alive" : "close";
+}
+
+static void handle_file_based_request(struct mg_connection *conn, const char *path, struct file *filep);
+static int mg_stat(struct mg_connection *conn, const char *path, struct file *filep);
+
+static const char *mg_get_response_code_text(int response_code, struct mg_connection *conn)
+{
+    switch (response_code)
+    {
+    /* RFC2616 Section 10.1 - Informational 1xx */
+    case 100: return "Continue"; /* RFC2616 Section 10.1.1 */
+    case 101: return "Switching Protocols"; /* RFC2616 Section 10.1.2 */
+    case 102: return "Processing"; /* RFC2518 Section 10.1 */
+
+    /* RFC2616 Section 10.2 - Successful 2xx */
+    case 200: return "OK"; /* RFC2616 Section 10.2.1 */
+    case 201: return "Created"; /* RFC2616 Section 10.2.2 */
+    case 202: return "Accepted"; /* RFC2616 Section 10.2.3 */
+    case 203: return "Non-Authoritative Information"; /* RFC2616 Section 10.2.4 */
+    case 204: return "No Content"; /* RFC2616 Section 10.2.5 */
+    case 205: return "Reset Content"; /* RFC2616 Section 10.2.6 */
+    case 206: return "Partial Content"; /* RFC2616 Section 10.2.7 */
+    case 207: return "Multi-Status"; /* RFC2518 Section 10.2, RFC4918 Section 11.1 */
+
+    /* RFC2616 Section 10.3 - Redirection 3xx */
+    case 300: return "Multiple Choices"; /* RFC2616 Section 10.3.1 */
+    case 301: return "Moved Permanently"; /* RFC2616 Section 10.3.2 */
+    case 302: return "Found"; /* RFC2616 Section 10.3.3 */
+    case 303: return "See Other"; /* RFC2616 Section 10.3.4 */
+    case 304: return "Not Modified"; /* RFC2616 Section 10.3.5 */
+    case 305: return "Use Proxy"; /* RFC2616 Section 10.3.6 */
+    case 307: return "Temporary Redirect"; /* RFC2616 Section 10.3.8 */
+
+    /* RFC2616 Section 10.4 - Client Error 4xx */
+    case 400: return "Bad Request"; /* RFC2616 Section 10.4.1 */
+    case 401: return "Unauthorized"; /* RFC2616 Section 10.4.2 */
+    case 402: return "Payment Required"; /* RFC2616 Section 10.4.3 */
+    case 403: return "Forbidden"; /* RFC2616 Section 10.4.4 */
+    case 404: return "Not Found"; /* RFC2616 Section 10.4.5 */
+    case 405: return "Method Not Allowed"; /* RFC2616 Section 10.4.6 */
+    case 406: return "Not Acceptable"; /* RFC2616 Section 10.4.7 */
+    case 407: return "Proxy Authentication Required"; /* RFC2616 Section 10.4.8 */
+    case 408: return "Request Time-out"; /* RFC2616 Section 10.4.9 */
+    case 409: return "Conflict"; /* RFC2616 Section 10.4.10 */
+    case 410: return "Gone"; /* RFC2616 Section 10.4.11 */
+    case 411: return "Length Required"; /* RFC2616 Section 10.4.12 */
+    case 412: return "Precondition Failed"; /* RFC2616 Section 10.4.13 */
+    case 413: return "Request Entity Too Large"; /* RFC2616 Section 10.4.14 */
+    case 414: return "Request-URI Too Large"; /* RFC2616 Section 10.4.15 */
+    case 415: return "Unsupported Media Type"; /* RFC2616 Section 10.4.16 */
+    case 416: return "Requested range not satisfiable"; /* RFC2616 Section 10.4.17 */
+    case 417: return "Expectation Failed"; /* RFC2616 Section 10.4.18 */
+    case 422: return "Unproccessable entity"; /* RFC2518 Section 10.3, RFC4918 Section 11.2 */
+    case 423: return "Locked"; /* RFC2518 Section 10.4, RFC4918 Section 11.3 */
+    case 424: return "Failed Dependency"; /* RFC2518 Section 10.5, RFC4918 Section 11.4 */
+    case 428: return "Precondition Required"; /* RFC 6585, Section 3 */
+    case 429: return "Too Many Requests"; /* RFC 6585, Section 4 */
+    case 431: return "Request Header Fields Too Large"; /* RFC 6585, Section 5 */
+
+    /* RFC2616 Section 10.5 - Server Error 5xx */
+    case 500: return "Internal Server Error"; /* RFC2616 Section 10.5.1 */
+    case 501: return "Not Implemented"; /* RFC2616 Section 10.5.2 */
+    case 502: return "Bad Gateway"; /* RFC2616 Section 10.5.3 */
+    case 503: return "Service Unavailable"; /* RFC2616 Section 10.5.4 */
+    case 504: return "Gateway Time-out"; /* RFC2616 Section 10.5.5 */
+    case 505: return "HTTP Version not supported"; /* RFC2616 Section 10.5.6 */
+    case 507: return "Insufficient Storage"; /* RFC2518 Section 10.6, , RFC4918 Section 11.5 */
+    case 511: return "Network Authentication Required"; /* RFC 6585, Section 6 */
+
+    /* Other RFCs */
+    case 426: return "Upgrade Required"; /* RFC 2817 */
+
+    /* Return codes from non normative RFCs: */
+    /* Informative and experimental RFCs, "de facto" standards due to common use, ... */
+    case 208: return "Already Reported"; /* RFC5842 Section 7.1 */
+    case 226: return "IM used"; /* RFC3229 Section 10.4.1 */
+    case 308: return "Permanent Redirect"; /* RFC7238 Section 3 */
+    case 418: return "I am a teapot"; /* RFC2324 Section 2.3.2 */
+    case 419: return "Authentication Timeout"; /* common use */
+    case 451: return "Unavailable For Legal Reasons"; /* draft-tbray-http-legally-restricted-status-05, Section 3 */
+    case 506: return "Variant Also Negotiates"; /* RFC 2295, Section 8.1 */
+    case 508: return "Loop Detected"; /* RFC5842 Section 7.1 */
+    case 510: return "Not Extended"; /* RFC 2774, Section 7 */
+
+    default:
+        /* This error code is unknown. This should not happen. */
+        if (conn) {
+            mg_cry(conn, "Unknown HTTP response code: %u", response_code);
+        }
+
+        /* Return at least a category according to RFC 2616 Section 10. */
+        if (response_code>=100 && response_code<200) {
+            /* Unknown informational status code */
+            return "Information";
+        }
+        if (response_code>=200 && response_code<300) {
+            /* Unknown success code */
+            return "Success";
+        }
+        if (response_code>=300 && response_code<400) {
+            /* Unknown redirection code */
+            return "Redirection";
+        }
+        if (response_code>=400 && response_code<500) {
+            /* Unknown request error code */
+            return "Client Error";
+        }
+        if (response_code>=500 && response_code<600) {
+            /* Unknown server error code */
+            return "Server Error";
+        }
+
+        /* Response code not even within reasonable range */
+        return "";
+    }
+}
+
+
+static void send_http_error(struct mg_connection *, int, const char *,
+                            PRINTF_FORMAT_STRING(const char *fmt), ...)
+PRINTF_ARGS(4, 5);
+
+
+static void send_http_error(struct mg_connection *conn, int status,
+                            const char *reason, const char *fmt, ...)
+{
+    char buf[MG_BUF_LEN];
+    va_list ap;
+    int len = 0, i, page_handler_found, scope;
+    char date[64];
+    time_t curtime = time(NULL);
+    const char *error_handler = NULL;
+    struct file error_page_file = STRUCT_FILE_INITIALIZER;
+    const char *error_page_file_ext, *tstr;
+
+    if (!reason) {
+        reason = mg_get_response_code_text(status, conn);
+    }
+
+    conn->status_code = status;
+    if (conn->in_error_handler ||
+        conn->ctx->callbacks.http_error == NULL ||
+        conn->ctx->callbacks.http_error(conn, status)) {
+
+        if (!conn->in_error_handler) {
+            /* Send user defined error pages, if defined */
+            error_handler = conn->ctx->config[ERROR_PAGES];
+            error_page_file_ext = conn->ctx->config[INDEX_FILES];
+            page_handler_found = 0;
+            if (error_handler != NULL) {
+                for (scope=1; (scope<=3) && !page_handler_found; scope++) {
+                    switch (scope) {
+                    case 1:
+                        len = mg_snprintf(conn, buf, sizeof(buf)-32, "%serror%03u.", error_handler, status);
+                        break;
+                    case 2:
+                        len = mg_snprintf(conn, buf, sizeof(buf)-32, "%serror%01uxx.", error_handler, status/100);
+                        break;
+                    default:
+                        len = mg_snprintf(conn, buf, sizeof(buf)-32, "%serror.", error_handler);
+                        break;
+                    }
+                    tstr = strchr(error_page_file_ext, '.');
+                    while (tstr) {
+                        for (i=1; i<32 && tstr[i]!=0 && tstr[i]!=','; i++) buf[len+i-1]=tstr[i];
+                        buf[len+i-1]=0;
+                        if (mg_stat(conn, buf, &error_page_file)) {
+                            page_handler_found = 1;
+                            break;
+                        }
+                        tstr = strchr(tstr+i, '.');
+                    }
+                }
+            }
+
+            if (page_handler_found) {
+                conn->in_error_handler = 1;
+                handle_file_based_request(conn, buf, &error_page_file);
+                conn->in_error_handler = 0;
+                return;
+            }
+        }
+
+        buf[0] = '\0';
+        gmt_time_string(date, sizeof(date), &curtime);
+
+        /* Errors 1xx, 204 and 304 MUST NOT send a body */
+        if (status > 199 && status != 204 && status != 304) {
+            len = mg_snprintf(conn, buf, sizeof(buf)-1, "Error %d: %s", status, reason);
+            buf[len] = '\n';
+            len++;
+            buf[len] = 0;
+
+            va_start(ap, fmt);
+            len += mg_vsnprintf(conn, buf + len, sizeof(buf) - len, fmt, ap);
+            va_end(ap);
+        }
+        DEBUG_TRACE("[%s]", buf);
+
+        mg_printf(conn, "HTTP/1.1 %d %s\r\n"
+                        "Content-Length: %d\r\n"
+                        "Date: %s\r\n"
+                        "Connection: %s\r\n\r\n",
+                        status, reason, len, date,
+                        suggest_connection_header(conn));
+        conn->num_bytes_sent += mg_printf(conn, "%s", buf);
+    }
+}
+
+#if defined(_WIN32) && !defined(__SYMBIAN32__)
+static int pthread_mutex_init(pthread_mutex_t *mutex, void *unused)
+{
+    (void) unused;
+    *mutex = CreateMutex(NULL, FALSE, NULL);
+    return *mutex == NULL ? -1 : 0;
+}
+
+static int pthread_mutex_destroy(pthread_mutex_t *mutex)
+{
+    return CloseHandle(*mutex) == 0 ? -1 : 0;
+}
+
+static int pthread_mutex_lock(pthread_mutex_t *mutex)
+{
+    return WaitForSingleObject(*mutex, INFINITE) == WAIT_OBJECT_0 ? 0 : -1;
+}
+
+static int pthread_mutex_trylock(pthread_mutex_t *mutex)
+{
+    switch (WaitForSingleObject(*mutex, 0)) {
+        case WAIT_OBJECT_0:
+            return 0;
+        case WAIT_TIMEOUT:
+            return -2; /* EBUSY */
+    }
+    return -1;
+}
+
+static int pthread_mutex_unlock(pthread_mutex_t *mutex)
+{
+    return ReleaseMutex(*mutex) == 0 ? -1 : 0;
+}
+
+#ifndef WIN_PTHREADS_TIME_H
+static int clock_gettime(clockid_t clk_id, struct timespec *tp)
+{
+    FILETIME ft;
+    ULARGE_INTEGER li;
+    BOOL ok = FALSE;
+    double d;
+    static double perfcnt_per_sec = 0.0;
+
+    if (tp) {
+        if (clk_id == CLOCK_REALTIME) {
+            GetSystemTimeAsFileTime(&ft);
+            li.LowPart = ft.dwLowDateTime;
+            li.HighPart = ft.dwHighDateTime;
+            li.QuadPart -= 116444736000000000; /* 1.1.1970 in filedate */
+            tp->tv_sec = (time_t)(li.QuadPart / 10000000);
+            tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
+            ok = TRUE;
+        } else if (clk_id == CLOCK_MONOTONIC) {
+            if (perfcnt_per_sec == 0.0) {
+                QueryPerformanceFrequency((LARGE_INTEGER *) &li);
+                perfcnt_per_sec = 1.0 / li.QuadPart;
+            }
+            if (perfcnt_per_sec != 0.0) {
+                QueryPerformanceCounter((LARGE_INTEGER *) &li);
+                d = li.QuadPart * perfcnt_per_sec;
+                tp->tv_sec = (time_t)d;
+                d -= tp->tv_sec;
+                tp->tv_nsec = (long)(d*1.0E9);
+                ok = TRUE;
+            }
+        }
+    }
+
+    return ok ? 0 : -1;
+}
+#endif
+
+static int pthread_cond_init(pthread_cond_t *cv, const void *unused)
+{
+    (void) unused;
+    InitializeCriticalSection(&cv->threadIdSec);
+    cv->waitingthreadcount = 0;
+    cv->waitingthreadhdls = (pthread_t *) mg_calloc(MAX_WORKER_THREADS, sizeof(pthread_t));
+    return (cv->waitingthreadhdls!=NULL) ? 0 : -1;
+}
+
+static int pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mutex, const struct timespec * abstime)
+{
+    struct mg_workerTLS * tls = (struct mg_workerTLS *)TlsGetValue(sTlsKey);
+    int ok;
+    struct timespec tsnow;
+    int64_t nsnow, nswaitabs, nswaitrel;
+    DWORD mswaitrel;
+
+    EnterCriticalSection(&cv->threadIdSec);
+    assert(cv->waitingthreadcount < MAX_WORKER_THREADS);
+    cv->waitingthreadhdls[cv->waitingthreadcount] = tls->pthread_cond_helper_mutex;
+    cv->waitingthreadcount++;
+    LeaveCriticalSection(&cv->threadIdSec);
+
+    if (abstime) {
+        clock_gettime(CLOCK_REALTIME, &tsnow);
+        nsnow = (((uint64_t)tsnow.tv_sec)*1000000000) + tsnow.tv_nsec;
+        nswaitabs = (((uint64_t)abstime->tv_sec)*1000000000) + abstime->tv_nsec;
+        nswaitrel = nswaitabs - nsnow;
+        if (nswaitrel<0) nswaitrel=0;
+        mswaitrel = (DWORD)(nswaitrel / 1000000);
+    } else {
+        mswaitrel = INFINITE;
+    }
+
+    pthread_mutex_unlock(mutex);
+    ok = (WAIT_OBJECT_0 == WaitForSingleObject(tls->pthread_cond_helper_mutex, mswaitrel));
+    pthread_mutex_lock(mutex);
+
+    return ok ? 0 : -1;
+}
+
+static int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex)
+{
+    return pthread_cond_timedwait(cv, mutex, NULL);
+}
+
+static int pthread_cond_signal(pthread_cond_t *cv)
+{
+    int i;
+    HANDLE wkup = NULL;
+    BOOL ok = FALSE;
+
+    EnterCriticalSection(&cv->threadIdSec);
+    if (cv->waitingthreadcount) {
+        wkup = cv->waitingthreadhdls[0];
+        ok = SetEvent(wkup);
+
+        for (i=1; i<cv->waitingthreadcount; i++) {
+            cv->waitingthreadhdls[i-1] = cv->waitingthreadhdls[i];
+        }
+        cv->waitingthreadcount--;
+
+        assert(ok);
+    }
+    LeaveCriticalSection(&cv->threadIdSec);
+
+    return ok ? 0 : 1;
+}
+
+static int pthread_cond_broadcast(pthread_cond_t *cv)
+{
+    EnterCriticalSection(&cv->threadIdSec);
+    while (cv->waitingthreadcount) {
+        pthread_cond_signal(cv);
+    }
+    LeaveCriticalSection(&cv->threadIdSec);
+
+    return 0;
+}
+
+static int pthread_cond_destroy(pthread_cond_t *cv)
+{
+    EnterCriticalSection(&cv->threadIdSec);
+    assert(cv->waitingthreadcount==0);
+    mg_free(cv->waitingthreadhdls);
+    cv->waitingthreadhdls = 0;
+    LeaveCriticalSection(&cv->threadIdSec);
+    DeleteCriticalSection(&cv->threadIdSec);
+
+    return 0;
+}
+
+/* For Windows, change all slashes to backslashes in path names. */
+static void change_slashes_to_backslashes(char *path)
+{
+    int i;
+
+    for (i = 0; path[i] != '\0'; i++) {
+        if (path[i] == '/')
+            path[i] = '\\';
+        /* i > 0 check is to preserve UNC paths, like \\server\file.txt */
+        if (path[i] == '\\' && i > 0)
+            while (path[i + 1] == '\\' || path[i + 1] == '/')
+                (void) memmove(path + i + 1,
+                               path + i + 2, strlen(path + i + 1));
+    }
+}
+
+/* Encode 'path' which is assumed UTF-8 string, into UNICODE string.
+   wbuf and wbuf_len is a target buffer and its length. */
+static void to_unicode(const char *path, wchar_t *wbuf, size_t wbuf_len)
+{
+    char buf[PATH_MAX], buf2[PATH_MAX];
+
+    mg_strlcpy(buf, path, sizeof(buf));
+    change_slashes_to_backslashes(buf);
+
+    /* Convert to Unicode and back. If doubly-converted string does not
+       match the original, something is fishy, reject. */
+    memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
+    MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len);
+    WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2),
+                        NULL, NULL);
+    if (strcmp(buf, buf2) != 0) {
+        wbuf[0] = L'\0';
+    }
+}
+
+#if defined(_WIN32_WCE)
+static time_t time(time_t *ptime)
+{
+    time_t t;
+    SYSTEMTIME st;
+    FILETIME ft;
+
+    GetSystemTime(&st);
+    SystemTimeToFileTime(&st, &ft);
+    t = SYS2UNIX_TIME(ft.dwLowDateTime, ft.dwHighDateTime);
+
+    if (ptime != NULL) {
+        *ptime = t;
+    }
+
+    return t;
+}
+
+static struct tm *localtime(const time_t *ptime, struct tm *ptm)
+{
+    int64_t t = ((int64_t) *ptime) * RATE_DIFF + EPOCH_DIFF;
+    FILETIME ft, lft;
+    SYSTEMTIME st;
+    TIME_ZONE_INFORMATION tzinfo;
+
+    if (ptm == NULL) {
+        return NULL;
+    }
+
+    * (int64_t *) &ft = t;
+    FileTimeToLocalFileTime(&ft, &lft);
+    FileTimeToSystemTime(&lft, &st);
+    ptm->tm_year = st.wYear - 1900;
+    ptm->tm_mon = st.wMonth - 1;
+    ptm->tm_wday = st.wDayOfWeek;
+    ptm->tm_mday = st.wDay;
+    ptm->tm_hour = st.wHour;
+    ptm->tm_min = st.wMinute;
+    ptm->tm_sec = st.wSecond;
+    ptm->tm_yday = 0; /* hope nobody uses this */
+    ptm->tm_isdst =
+        GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT ? 1 : 0;
+
+    return ptm;
+}
+
+static struct tm *gmtime(const time_t *ptime, struct tm *ptm)
+{
+    /* FIXME(lsm): fix this. */
+    return localtime(ptime, ptm);
+}
+
+static size_t strftime(char *dst, size_t dst_size, const char *fmt,
+                       const struct tm *tm)
+{
+    (void) snprintf(dst, dst_size, "implement strftime() for WinCE");
+    return 0;
+}
+#endif
+
+/* Windows happily opens files with some garbage at the end of file name.
+   For example, fopen("a.cgi    ", "r") on Windows successfully opens
+   "a.cgi", despite one would expect an error back.
+   This function returns non-0 if path ends with some garbage. */
+static int path_cannot_disclose_cgi(const char *path)
+{
+    static const char *allowed_last_characters = "_-";
+    int last = path[strlen(path) - 1];
+    return isalnum(last) || strchr(allowed_last_characters, last) != NULL;
+}
+
+static int mg_stat(struct mg_connection *conn, const char *path, struct file *filep)
+{
+    wchar_t wbuf[PATH_MAX];
+    WIN32_FILE_ATTRIBUTE_DATA info;
+
+    if (!is_file_in_memory(conn, path, filep)) {
+        to_unicode(path, wbuf, ARRAY_SIZE(wbuf));
+        if (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0) {
+            filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh);
+            filep->modification_time = SYS2UNIX_TIME(
+                                           info.ftLastWriteTime.dwLowDateTime,
+                                           info.ftLastWriteTime.dwHighDateTime);
+            filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
+            /* If file name is fishy, reset the file structure and return
+               error.
+               Note it is important to reset, not just return the error, cause
+               functions like is_file_opened() check the struct. */
+            if (!filep->is_directory && !path_cannot_disclose_cgi(path)) {
+                memset(filep, 0, sizeof(*filep));
+            }
+        }
+    }
+
+    return filep->membuf != NULL || filep->modification_time != 0;
+}
+
+static int mg_remove(const char *path)
+{
+    wchar_t wbuf[PATH_MAX];
+    to_unicode(path, wbuf, ARRAY_SIZE(wbuf));
+    return DeleteFileW(wbuf) ? 0 : -1;
+}
+
+static int mg_mkdir(const char *path, int mode)
+{
+    char buf[PATH_MAX];
+    wchar_t wbuf[PATH_MAX];
+
+    (void) mode;
+    mg_strlcpy(buf, path, sizeof(buf));
+    change_slashes_to_backslashes(buf);
+
+    (void) MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, ARRAY_SIZE(wbuf));
+
+    return CreateDirectoryW(wbuf, NULL) ? 0 : -1;
+}
+
+/* Implementation of POSIX opendir/closedir/readdir for Windows. */
+static DIR * opendir(const char *name)
+{
+    DIR *dir = NULL;
+    wchar_t wpath[PATH_MAX];
+    DWORD attrs;
+
+    if (name == NULL) {
+        SetLastError(ERROR_BAD_ARGUMENTS);
+    } else if ((dir = (DIR *) mg_malloc(sizeof(*dir))) == NULL) {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    } else {
+        to_unicode(name, wpath, ARRAY_SIZE(wpath));
+        attrs = GetFileAttributesW(wpath);
+        if (attrs != 0xFFFFFFFF &&
+            ((attrs & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)) {
+            (void) wcscat(wpath, L"\\*");
+            dir->handle = FindFirstFileW(wpath, &dir->info);
+            dir->result.d_name[0] = '\0';
+        } else {
+            mg_free(dir);
+            dir = NULL;
+        }
+    }
+
+    return dir;
+}
+
+static int closedir(DIR *dir)
+{
+    int result = 0;
+
+    if (dir != NULL) {
+        if (dir->handle != INVALID_HANDLE_VALUE)
+            result = FindClose(dir->handle) ? 0 : -1;
+
+        mg_free(dir);
+    } else {
+        result = -1;
+        SetLastError(ERROR_BAD_ARGUMENTS);
+    }
+
+    return result;
+}
+
+static struct dirent *readdir(DIR *dir)
+{
+    struct dirent *result = 0;
+
+    if (dir) {
+        if (dir->handle != INVALID_HANDLE_VALUE) {
+            result = &dir->result;
+            (void) WideCharToMultiByte(CP_UTF8, 0,
+                                       dir->info.cFileName, -1, result->d_name,
+                                       sizeof(result->d_name), NULL, NULL);
+
+            if (!FindNextFileW(dir->handle, &dir->info)) {
+                (void) FindClose(dir->handle);
+                dir->handle = INVALID_HANDLE_VALUE;
+            }
+
+        } else {
+            SetLastError(ERROR_FILE_NOT_FOUND);
+        }
+    } else {
+        SetLastError(ERROR_BAD_ARGUMENTS);
+    }
+
+    return result;
+}
+
+#ifndef HAVE_POLL
+static int poll(struct pollfd *pfd, int n, int milliseconds)
+{
+    struct timeval tv;
+    fd_set set;
+    int i, result;
+    SOCKET maxfd = 0;
+
+    tv.tv_sec = milliseconds / 1000;
+    tv.tv_usec = (milliseconds % 1000) * 1000;
+    FD_ZERO(&set);
+
+    for (i = 0; i < n; i++) {
+        FD_SET((SOCKET) pfd[i].fd, &set);
+        pfd[i].revents = 0;
+
+        if (pfd[i].fd > maxfd) {
+            maxfd = pfd[i].fd;
+        }
+    }
+
+    if ((result = select((int)maxfd + 1, &set, NULL, NULL, &tv)) > 0) {
+        for (i = 0; i < n; i++) {
+            if (FD_ISSET(pfd[i].fd, &set)) {
+                pfd[i].revents = POLLIN;
+            }
+        }
+    }
+
+    return result;
+}
+#endif /* HAVE_POLL */
+
+static void set_close_on_exec(SOCKET sock, struct mg_connection *conn /* may be null */)
+{
+    (void) conn; /* Unused. */
+    (void) SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0);
+}
+
+int mg_start_thread(mg_thread_func_t f, void *p)
+{
+#if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
+    /* Compile-time option to control stack size, e.g. -DUSE_STACK_SIZE=16384 */
+    return ((_beginthread((void (__cdecl *)(void *)) f, USE_STACK_SIZE, p) == ((uintptr_t)(-1L))) ? -1 : 0);
+#else
+    return ((_beginthread((void (__cdecl *)(void *)) f, 0, p) == ((uintptr_t)(-1L))) ? -1 : 0);
+#endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
+}
+
+/* Start a thread storing the thread context. */
+
+static int mg_start_thread_with_id(unsigned (__stdcall *f)(void *), void *p,
+                                   pthread_t *threadidptr)
+{
+    uintptr_t uip;
+    HANDLE threadhandle;
+    int result = -1;
+
+    uip = _beginthreadex(NULL, 0, (unsigned (__stdcall *)(void *)) f, p, 0,
+                         NULL);
+    threadhandle = (HANDLE) uip;
+    if ((uip != (uintptr_t)(-1L)) && (threadidptr != NULL)) {
+        *threadidptr = threadhandle;
+        result = 0;
+    }
+
+    return result;
+}
+
+/* Wait for a thread to finish. */
+
+static int mg_join_thread(pthread_t threadid)
+{
+    int result;
+    DWORD dwevent;
+
+    result = -1;
+    dwevent = WaitForSingleObject(threadid, INFINITE);
+    if (dwevent == WAIT_FAILED) {
+        int err;
+
+        err = GetLastError();
+        DEBUG_TRACE("WaitForSingleObject() failed, error %d", err);
+    } else {
+        if (dwevent == WAIT_OBJECT_0) {
+            CloseHandle(threadid);
+            result = 0;
+        }
+    }
+
+    return result;
+}
+
+static HANDLE dlopen(const char *dll_name, int flags)
+{
+    wchar_t wbuf[PATH_MAX];
+    (void) flags;
+    to_unicode(dll_name, wbuf, ARRAY_SIZE(wbuf));
+    return LoadLibraryW(wbuf);
+}
+
+static int dlclose(void *handle)
+{
+    int result;
+
+    if (FreeLibrary((HMODULE) handle) != 0) {
+        result = 0;
+    } else {
+        result = -1;
+    }
+
+    return result;
+}
+
+#if !defined(NO_CGI)
+#define SIGKILL 0
+static int kill(pid_t pid, int sig_num)
+{
+    (void) TerminateProcess(pid, sig_num);
+    (void) CloseHandle(pid);
+    return 0;
+}
+
+static void trim_trailing_whitespaces(char *s)
+{
+    char *e = s + strlen(s) - 1;
+    while (e > s && isspace(* (unsigned char *) e)) {
+        *e-- = '\0';
+    }
+}
+
+static pid_t spawn_process(struct mg_connection *conn, const char *prog,
+                           char *envblk, char *envp[], int fdin,
+                           int fdout, const char *dir)
+{
+    HANDLE me;
+    char *p, *interp, full_interp[PATH_MAX], full_dir[PATH_MAX],
+         cmdline[PATH_MAX], buf[PATH_MAX];
+    struct file file = STRUCT_FILE_INITIALIZER;
+    STARTUPINFOA si;
+    PROCESS_INFORMATION pi = { 0 };
+
+    (void) envp;
+
+    memset(&si, 0, sizeof(si));
+    si.cb = sizeof(si);
+
+    /* TODO(lsm): redirect CGI errors to the error log file */
+    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+    si.wShowWindow = SW_HIDE;
+
+    me = GetCurrentProcess();
+    DuplicateHandle(me, (HANDLE) _get_osfhandle(fdin), me,
+                    &si.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS);
+    DuplicateHandle(me, (HANDLE) _get_osfhandle(fdout), me,
+                    &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS);
+
+    /* If CGI file is a script, try to read the interpreter line */
+    interp = conn->ctx->config[CGI_INTERPRETER];
+    if (interp == NULL) {
+        buf[0] = buf[1] = '\0';
+
+        /* Read the first line of the script into the buffer */
+        snprintf(cmdline, sizeof(cmdline), "%s%c%s", dir, '/', prog);
+        if (mg_fopen(conn, cmdline, "r", &file)) {
+            p = (char *) file.membuf;
+            mg_fgets(buf, sizeof(buf), &file, &p);
+            mg_fclose(&file);
+            buf[sizeof(buf) - 1] = '\0';
+        }
+
+        if (buf[0] == '#' && buf[1] == '!') {
+            trim_trailing_whitespaces(buf + 2);
+        } else {
+            buf[2] = '\0';
+        }
+        interp = buf + 2;
+    }
+
+    if (interp[0] != '\0') {
+        GetFullPathNameA(interp, sizeof(full_interp), full_interp, NULL);
+        interp = full_interp;
+    }
+    GetFullPathNameA(dir, sizeof(full_dir), full_dir, NULL);
+
+    mg_snprintf(conn, cmdline, sizeof(cmdline), "%s%s\"%s\\%s\"",
+                interp, interp[0] == '\0' ? "" : " ", full_dir, prog);
+
+    DEBUG_TRACE("Running [%s]", cmdline);
+    if (CreateProcessA(NULL, cmdline, NULL, NULL, TRUE,
+                       CREATE_NEW_PROCESS_GROUP, envblk, NULL, &si, &pi) == 0) {
+        mg_cry(conn, "%s: CreateProcess(%s): %ld",
+               __func__, cmdline, ERRNO);
+        pi.hProcess = (pid_t) -1;
+    }
+
+    (void) CloseHandle(si.hStdOutput);
+    (void) CloseHandle(si.hStdInput);
+    if (pi.hThread != NULL)
+        (void) CloseHandle(pi.hThread);
+
+    return (pid_t) pi.hProcess;
+}
+#endif /* !NO_CGI */
+
+static int set_non_blocking_mode(SOCKET sock)
+{
+    unsigned long on = 1;
+    return ioctlsocket(sock, FIONBIO, &on);
+}
+
+#else
+static int mg_stat(struct mg_connection *conn, const char *path,
+                   struct file *filep)
+{
+    struct stat st;
+
+    if (!is_file_in_memory(conn, path, filep) && !stat(path, &st)) {
+        filep->size = st.st_size;
+        filep->modification_time = st.st_mtime;
+        filep->is_directory = S_ISDIR(st.st_mode);
+    } else {
+        filep->modification_time = (time_t) 0;
+    }
+
+    return filep->membuf != NULL || filep->modification_time != (time_t) 0;
+}
+
+static void set_close_on_exec(int fd, struct mg_connection *conn /* may be null */)
+{
+    if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
+        if (conn) {
+            mg_cry(conn, "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s", __func__, strerror(ERRNO));
+        }
+    }
+}
+
+int mg_start_thread(mg_thread_func_t func, void *param)
+{
+    pthread_t thread_id;
+    pthread_attr_t attr;
+    int result;
+
+    (void) pthread_attr_init(&attr);
+    (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+#if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
+    /* Compile-time option to control stack size,
+       e.g. -DUSE_STACK_SIZE=16384 */
+    (void) pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
+#endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
+
+    result = pthread_create(&thread_id, &attr, func, param);
+    pthread_attr_destroy(&attr);
+
+    return result;
+}
+
+/* Start a thread storing the thread context. */
+
+static int mg_start_thread_with_id(mg_thread_func_t func, void *param, pthread_t *threadidptr)
+{
+    pthread_t thread_id;
+    pthread_attr_t attr;
+    int result;
+
+    (void) pthread_attr_init(&attr);
+
+#if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
+    /* Compile-time option to control stack size,
+       e.g. -DUSE_STACK_SIZE=16384 */
+    (void) pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
+#endif /* defined(USE_STACK_SIZE) && USE_STACK_SIZE > 1 */
+
+    result = pthread_create(&thread_id, &attr, func, param);
+    pthread_attr_destroy(&attr);
+    if ((result == 0) && (threadidptr != NULL)) {
+        *threadidptr = thread_id;
+    }
+    return result;
+}
+
+/* Wait for a thread to finish. */
+
+static int mg_join_thread(pthread_t threadid)
+{
+    int result;
+
+    result = pthread_join(threadid, NULL);
+    return result;
+}
+
+#ifndef NO_CGI
+static pid_t spawn_process(struct mg_connection *conn, const char *prog,
+                           char *envblk, char *envp[], int fdin,
+                           int fdout, const char *dir)
+{
+    pid_t pid;
+    const char *interp;
+
+    (void) envblk;
+
+    if ((pid = fork()) == -1) {
+        /* Parent */
+        send_http_error(conn, 500, NULL,
+            "Error: Creating CGI process\nfork(): %s", strerror(ERRNO));
+    } else if (pid == 0) {
+        /* Child */
+        if (chdir(dir) != 0) {
+            mg_cry(conn, "%s: chdir(%s): %s", __func__, dir, strerror(ERRNO));
+        } else if (dup2(fdin, 0) == -1) {
+            mg_cry(conn, "%s: dup2(%d, 0): %s", __func__, fdin, strerror(ERRNO));
+        } else if (dup2(fdout, 1) == -1) {
+            mg_cry(conn, "%s: dup2(%d, 1): %s", __func__, fdout, strerror(ERRNO));
+        } else {
+            /* Not redirecting stderr to stdout, to avoid output being littered
+               with the error messages. */
+            (void) close(fdin);
+            (void) close(fdout);
+
+            /* After exec, all signal handlers are restored to their default
+               values, with one exception of SIGCHLD. According to
+               POSIX.1-2001 and Linux's implementation, SIGCHLD's handler will
+               leave unchanged after exec if it was set to be ignored. Restore
+               it to default action. */
+            signal(SIGCHLD, SIG_DFL);
+
+            interp = conn->ctx->config[CGI_INTERPRETER];
+            if (interp == NULL) {
+                (void) execle(prog, prog, NULL, envp);
+                mg_cry(conn, "%s: execle(%s): %s", __func__, prog, strerror(ERRNO));
+            } else {
+                (void) execle(interp, interp, prog, NULL, envp);
+                mg_cry(conn, "%s: execle(%s %s): %s", __func__, interp, prog,
+                       strerror(ERRNO));
+            }
+        }
+        exit(EXIT_FAILURE);
+    }
+
+    return pid;
+}
+#endif /* !NO_CGI */
+
+static int set_non_blocking_mode(SOCKET sock)
+{
+    int flags;
+
+    flags = fcntl(sock, F_GETFL, 0);
+    (void) fcntl(sock, F_SETFL, flags | O_NONBLOCK);
+
+    return 0;
+}
+#endif /* _WIN32 */
+
+/* Write data to the IO channel - opened file descriptor, socket or SSL
+   descriptor. Return number of bytes written. */
+static int64_t push(FILE *fp, SOCKET sock, SSL *ssl, const char *buf, int64_t len)
+{
+    int64_t sent;
+    int n, k;
+
+    (void) ssl;  /* Get rid of warning */
+    sent = 0;
+    while (sent < len) {
+
+        /* How many bytes we send in this iteration */
+        k = len - sent > INT_MAX ? INT_MAX : (int) (len - sent);
+
+#ifndef NO_SSL
+        if (ssl != NULL) {
+            n = SSL_write(ssl, buf + sent, k);
+        } else
+#endif
+            if (fp != NULL) {
+                n = (int) fwrite(buf + sent, 1, (size_t) k, fp);
+                if (ferror(fp))
+                    n = -1;
+            } else {
+                n = send(sock, buf + sent, (size_t) k, MSG_NOSIGNAL);
+            }
+
+        if (n <= 0)
+            break;
+
+        sent += n;
+    }
+
+    return sent;
+}
+
+/* Read from IO channel - opened file descriptor, socket, or SSL descriptor.
+   Return negative value on error, or number of bytes read on success. */
+static int pull(FILE *fp, struct mg_connection *conn, char *buf, int len)
+{
+    int nread;
+
+    if (fp != NULL) {
+        /* Use read() instead of fread(), because if we're reading from the
+           CGI pipe, fread() may block until IO buffer is filled up. We cannot
+           afford to block and must pass all read bytes immediately to the
+           client. */
+        nread = read(fileno(fp), buf, (size_t) len);
+#ifndef NO_SSL
+    } else if (conn->ssl != NULL) {
+        nread = SSL_read(conn->ssl, buf, len);
+#endif
+    } else {
+        nread = recv(conn->client.sock, buf, (size_t) len, 0);
+    }
+
+    return conn->ctx->stop_flag ? -1 : nread;
+}
+
+static int pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len)
+{
+    int n, nread = 0;
+
+    while (len > 0 && conn->ctx->stop_flag == 0) {
+        n = pull(fp, conn, buf + nread, len);
+        if (n < 0) {
+            nread = n;  /* Propagate the error */
+            break;
+        } else if (n == 0) {
+            break;  /* No more data to read */
+        } else {
+            conn->consumed_content += n;
+            nread += n;
+            len -= n;
+        }
+    }
+
+    return nread;
+}
+
+int mg_read(struct mg_connection *conn, void *buf, size_t len)
+{
+    int64_t n, buffered_len, nread;
+    int64_t len64 = (int64_t)(len > INT_MAX ? INT_MAX : len); /* since the return value is int, we may not read more bytes */
+    const char *body;
+
+    /* If Content-Length is not set for a PUT or POST request, read until socket is closed */
+    if (conn->consumed_content == 0 && conn->content_len == -1) {
+        conn->content_len = INT64_MAX;
+        conn->must_close = 1;
+    }
+
+    nread = 0;
+    if (conn->consumed_content < conn->content_len) {
+        /* Adjust number of bytes to read. */
+        int64_t left_to_read = conn->content_len - conn->consumed_content;
+        if (left_to_read < len64) {
+            /* Do not reade more than the total content length of the request. */
+            len64 = left_to_read;
+        }
+
+        /* Return buffered data */
+        buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len - conn->consumed_content;
+        if (buffered_len > 0) {
+            if (len64 < buffered_len) {
+                buffered_len = len64;
+            }
+            body = conn->buf + conn->request_len + conn->consumed_content;
+            memcpy(buf, body, (size_t) buffered_len);
+            len64 -= buffered_len;
+            conn->consumed_content += buffered_len;
+            nread += buffered_len;
+            buf = (char *) buf + buffered_len;
+        }
+
+        /* We have returned all buffered data. Read new data from the remote
+           socket. */
+        if ((n = pull_all(NULL, conn, (char *) buf, (int)len64)) >= 0) {
+            nread += n;
+        } else {
+            nread = (nread > 0 ? nread : n);
+        }
+    }
+    return (int)nread;
+}
+
+int mg_write(struct mg_connection *conn, const void *buf, size_t len)
+{
+    time_t now;
+    int64_t n, total, allowed;
+
+    if (conn->throttle > 0) {
+        if ((now = time(NULL)) != conn->last_throttle_time) {
+            conn->last_throttle_time = now;
+            conn->last_throttle_bytes = 0;
+        }
+        allowed = conn->throttle - conn->last_throttle_bytes;
+        if (allowed > (int64_t) len) {
+            allowed = len;
+        }
+        if ((total = push(NULL, conn->client.sock, conn->ssl, (const char *) buf,
+                          (int64_t) allowed)) == allowed) {
+            buf = (char *) buf + total;
+            conn->last_throttle_bytes += total;
+            while (total < (int64_t) len && conn->ctx->stop_flag == 0) {
+                allowed = conn->throttle > (int64_t) len - total ?
+                          (int64_t) len - total : conn->throttle;
+                if ((n = push(NULL, conn->client.sock, conn->ssl, (const char *) buf,
+                              (int64_t) allowed)) != allowed) {
+                    break;
+                }
+                sleep(1);
+                conn->last_throttle_bytes = allowed;
+                conn->last_throttle_time = time(NULL);
+                buf = (char *) buf + n;
+                total += n;
+            }
+        }
+    } else {
+        total = push(NULL, conn->client.sock, conn->ssl, (const char *) buf,
+                     (int64_t) len);
+    }
+    return (int) total;
+}
+
+/* Alternative alloc_vprintf() for non-compliant C runtimes */
+static int alloc_vprintf2(char **buf, const char *fmt, va_list ap)
+{
+    va_list ap_copy;
+    int size = MG_BUF_LEN;
+    int len = -1;
+
+    *buf = NULL;
+    while (len == -1) {
+        if (*buf) mg_free(*buf);
+        *buf = (char *)mg_malloc(size *= 4);
+        if (!*buf) break;
+        va_copy(ap_copy, ap);
+        len = vsnprintf(*buf, size, fmt, ap_copy);
+        va_end(ap_copy);
+    }
+
+    return len;
+}
+
+/* Print message to buffer. If buffer is large enough to hold the message,
+   return buffer. If buffer is to small, allocate large enough buffer on heap,
+   and return allocated buffer. */
+static int alloc_vprintf(char **buf, size_t size, const char *fmt, va_list ap)
+{
+    va_list ap_copy;
+    int len;
+
+    /* Windows is not standard-compliant, and vsnprintf() returns -1 if
+       buffer is too small. Also, older versions of msvcrt.dll do not have
+       _vscprintf().  However, if size is 0, vsnprintf() behaves correctly.
+       Therefore, we make two passes: on first pass, get required message
+       length.
+       On second pass, actually print the message. */
+    va_copy(ap_copy, ap);
+    len = vsnprintf(NULL, 0, fmt, ap_copy);
+    va_end(ap_copy);
+
+    if (len < 0) {
+        /* C runtime is not standard compliant, vsnprintf() returned -1.
+           Switch to alternative code path that uses incremental allocations.
+        */
+        va_copy(ap_copy, ap);
+        len = alloc_vprintf2(buf, fmt, ap);
+        va_end(ap_copy);
+    } else if (len > (int) size &&
+               (size = len + 1) > 0 &&
+               (*buf = (char *) mg_malloc(size)) == NULL) {
+        len = -1;  /* Allocation failed, mark failure */
+    } else {
+        va_copy(ap_copy, ap);
+        IGNORE_UNUSED_RESULT(vsnprintf(*buf, size, fmt, ap_copy));
+        va_end(ap_copy);
+    }
+
+    return len;
+}
+
+int mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap)
+{
+    char mem[MG_BUF_LEN], *buf = mem;
+    int len;
+
+    if ((len = alloc_vprintf(&buf, sizeof(mem), fmt, ap)) > 0) {
+        len = mg_write(conn, buf, (size_t) len);
+    }
+    if (buf != mem && buf != NULL) {
+        mg_free(buf);
+    }
+
+    return len;
+}
+
+int mg_printf(struct mg_connection *conn, const char *fmt, ...)
+{
+    va_list ap;
+    int result;
+
+    va_start(ap, fmt);
+    result = mg_vprintf(conn, fmt, ap);
+    va_end(ap);
+
+    return result;
+}
+
+int mg_url_decode(const char *src, int src_len, char *dst,
+                  int dst_len, int is_form_url_encoded)
+{
+    int i, j, a, b;
+#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
+
+    for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) {
+        if (i < src_len - 2 && src[i] == '%' &&
+            isxdigit(* (const unsigned char *) (src + i + 1)) &&
+            isxdigit(* (const unsigned char *) (src + i + 2))) {
+            a = tolower(* (const unsigned char *) (src + i + 1));
+            b = tolower(* (const unsigned char *) (src + i + 2));
+            dst[j] = (char) ((HEXTOI(a) << 4) | HEXTOI(b));
+            i += 2;
+        } else if (is_form_url_encoded && src[i] == '+') {
+            dst[j] = ' ';
+        } else {
+            dst[j] = src[i];
+        }
+    }
+
+    dst[j] = '\0'; /* Null-terminate the destination */
+
+    return i >= src_len ? j : -1;
+}
+
+int mg_get_var(const char *data, size_t data_len, const char *name,
+               char *dst, size_t dst_len)
+{
+    return mg_get_var2(data,data_len,name,dst,dst_len,0);
+}
+
+int mg_get_var2(const char *data, size_t data_len, const char *name,
+                char *dst, size_t dst_len, size_t occurrence)
+{
+    const char *p, *e, *s;
+    size_t name_len;
+    int len;
+
+    if (dst == NULL || dst_len == 0) {
+        len = -2;
+    } else if (data == NULL || name == NULL || data_len == 0) {
+        len = -1;
+        dst[0] = '\0';
+    } else {
+        name_len = strlen(name);
+        e = data + data_len;
+        len = -1;
+        dst[0] = '\0';
+
+        /* data is "var1=val1&var2=val2...". Find variable first */
+        for (p = data; p + name_len < e; p++) {
+            if ((p == data || p[-1] == '&') && p[name_len] == '=' &&
+                !mg_strncasecmp(name, p, name_len) && 0 == occurrence--) {
+
+                /* Point p to variable value */
+                p += name_len + 1;
+
+                /* Point s to the end of the value */
+                s = (const char *) memchr(p, '&', (size_t)(e - p));
+                if (s == NULL) {
+                    s = e;
+                }
+                assert(s >= p);
+
+                /* Decode variable into destination buffer */
+                len = mg_url_decode(p, (int)(s - p), dst, (int)dst_len, 1);
+
+                /* Redirect error code from -1 to -2 (destination buffer too
+                   small). */
+                if (len == -1) {
+                    len = -2;
+                }
+                break;
+            }
+        }
+    }
+
+    return len;
+}
+
+int mg_get_cookie(const char *cookie_header, const char *var_name,
+                  char *dst, size_t dst_size)
+{
+    const char *s, *p, *end;
+    int name_len, len = -1;
+
+    if (dst == NULL || dst_size == 0) {
+        len = -2;
+    } else if (var_name == NULL || (s = cookie_header) == NULL) {
+        len = -1;
+        dst[0] = '\0';
+    } else {
+        name_len = (int) strlen(var_name);
+        end = s + strlen(s);
+        dst[0] = '\0';
+
+        for (; (s = mg_strcasestr(s, var_name)) != NULL; s += name_len) {
+            if (s[name_len] == '=') 

<TRUNCATED>