You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by ab...@apache.org on 2014/01/07 11:33:56 UTC

svn commit: r1556172 [2/2] - in /incubator/celix/trunk: remote_services/ remote_services/discovery_shm/ remote_services/discovery_shm/private/ remote_services/discovery_shm/private/include/ remote_services/discovery_shm/private/src/ remote_services/rem...

Added: incubator/celix/trunk/remote_services/remote_service_admin_shm/private/src/remote_service_admin_impl.c
URL: http://svn.apache.org/viewvc/incubator/celix/trunk/remote_services/remote_service_admin_shm/private/src/remote_service_admin_impl.c?rev=1556172&view=auto
==============================================================================
--- incubator/celix/trunk/remote_services/remote_service_admin_shm/private/src/remote_service_admin_impl.c (added)
+++ incubator/celix/trunk/remote_services/remote_service_admin_shm/private/src/remote_service_admin_impl.c Tue Jan  7 10:33:55 2014
@@ -0,0 +1,828 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * remote_service_admin_impl.c
+ *
+ *  \date       Sep 14, 2013
+ *  \author     <a href="mailto:celix-dev@incubator.apache.org">Apache Celix Project Team</a>
+ *  \copyright  Apache License, Version 2.0
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+#include <unistd.h>
+#include <apr_uuid.h>
+#include <apr_strings.h>
+
+#include "remote_service_admin_shm.h"
+#include "remote_service_admin_shm_impl.h"
+
+#include "export_registration_impl.h"
+#include "import_registration_impl.h"
+#include "remote_constants.h"
+#include "constants.h"
+#include "utils.h"
+#include "bundle_context.h"
+#include "bundle.h"
+#include "service_reference.h"
+#include "service_registration.h"
+#include "netstring.h"
+
+celix_status_t remoteServiceAdmin_installEndpoint(remote_service_admin_pt admin, export_registration_pt registration, service_reference_pt reference, char *interface);
+celix_status_t remoteServiceAdmin_createEndpointDescription(remote_service_admin_pt admin, properties_pt serviceProperties, properties_pt endpointProperties, char *interface, endpoint_description_pt *description);
+
+celix_status_t remoteServiceAdmin_lock(int semId, int semNr);
+celix_status_t remoteServiceAdmin_unlock(int semId, int semNr);
+celix_status_t remoteServiceAdmin_wait(int semId, int semNr);
+
+
+celix_status_t remoteServiceAdmin_createOrAttachShm(hash_map_pt ipcSegment, remote_service_admin_pt admin, endpoint_description_pt endpointDescription, bool createIfNotFound);
+celix_status_t remoteServiceAdmin_create(apr_pool_t *pool, bundle_context_pt context, remote_service_admin_pt *admin)
+{
+    celix_status_t status = CELIX_SUCCESS;
+
+    *admin = apr_palloc(pool, sizeof(**admin));
+    if (!*admin)
+    {
+        status = CELIX_ENOMEM;
+    }
+    else
+    {
+        (*admin)->pool = pool;
+        (*admin)->context = context;
+        (*admin)->exportedServices = hashMap_create(NULL, NULL, NULL, NULL);
+        (*admin)->importedServices = hashMap_create(NULL, NULL, NULL, NULL);
+        (*admin)->exportedIpcSegment = hashMap_create(NULL, NULL, NULL, NULL);
+        (*admin)->importedIpcSegment = hashMap_create(NULL, NULL, NULL, NULL);
+        (*admin)->pollThread = hashMap_create(NULL, NULL, NULL, NULL);
+        (*admin)->pollThreadRunning =  hashMap_create(NULL, NULL, NULL, NULL);
+    }
+
+    return status;
+}
+
+
+
+
+celix_status_t remoteServiceAdmin_stop(remote_service_admin_pt admin)
+{
+    celix_status_t status = CELIX_SUCCESS;
+
+    hash_map_iterator_pt iter = hashMapIterator_create(admin->importedServices);
+    while (hashMapIterator_hasNext(iter))
+    {
+        array_list_pt exports = hashMapIterator_nextValue(iter);
+        int i;
+        for (i = 0; i < arrayList_size(exports); i++)
+        {
+            import_registration_pt export = arrayList_get(exports, i);
+            importRegistration_stopTracking(export);
+        }
+    }
+
+    // set stop-thread-variable
+    iter = hashMapIterator_create(admin->pollThreadRunning);
+    while (hashMapIterator_hasNext(iter))
+    {
+        bool *pollThreadRunning = hashMapIterator_nextValue(iter);
+        *pollThreadRunning = false;
+    }
+
+    // release lock
+    iter = hashMapIterator_create(admin->exportedIpcSegment);
+    while (hashMapIterator_hasNext(iter))
+    {
+        ipc_segment_pt ipc = hashMapIterator_nextValue(iter);
+        remoteServiceAdmin_unlock(ipc->semId, 0);
+    }
+
+    // wait till threads has stopped
+    iter = hashMapIterator_create(admin->pollThread);
+    while (hashMapIterator_hasNext(iter))
+    {
+        apr_status_t tstat;
+        apr_thread_t *pollThread = hashMapIterator_nextValue(iter);
+
+        if (pollThread != NULL)
+        {
+            apr_status_t stat = apr_thread_join(&tstat, pollThread);
+
+            if (stat != APR_SUCCESS && tstat != APR_SUCCESS)
+            {
+                status = CELIX_BUNDLE_EXCEPTION;
+            }
+        }
+    }
+
+    iter = hashMapIterator_create(admin->importedIpcSegment);
+    while (hashMapIterator_hasNext(iter))
+    {
+        ipc_segment_pt ipc = hashMapIterator_nextValue(iter);
+        shmdt(ipc->shmBaseAdress);
+    }
+
+
+    iter = hashMapIterator_create(admin->exportedIpcSegment);
+    while (hashMapIterator_hasNext(iter))
+    {
+        ipc_segment_pt ipc = hashMapIterator_nextValue(iter);
+
+        semctl(ipc->semId, 1 /*ignored*/, IPC_RMID);
+        shmctl(ipc->shmId, IPC_RMID, 0);
+    }
+
+    return status;
+}
+
+
+celix_status_t remoteServiceAdmin_lock(int semId, int semNr)
+{
+    celix_status_t status = CELIX_SUCCESS;
+    int semOpStatus = 0;
+    struct sembuf semOperation;
+
+    semOperation.sem_num = semNr;
+    semOperation.sem_op = -1;
+    semOperation.sem_flg = 0;
+
+    do
+    {
+        status = CELIX_SUCCESS;
+
+        if ((semOpStatus = semop(semId, &semOperation, 1)) != 0)
+        {
+            status = CELIX_BUNDLE_EXCEPTION;
+        }
+    }
+    while (semOpStatus == -1 && errno == EINTR);
+
+
+    return status;
+}
+
+
+celix_status_t remoteServiceAdmin_unlock(int semId, int semNr)
+{
+    celix_status_t status = CELIX_SUCCESS;
+    int semOpStatus = 0;
+    struct sembuf semOperation;
+
+    semOperation.sem_num = semNr;
+    semOperation.sem_op = 1;
+    semOperation.sem_flg = 0;
+
+    do
+    {
+        status = CELIX_SUCCESS;
+
+        if ((semOpStatus = semop(semId, &semOperation, 1)) != 0)
+        {
+            status = CELIX_BUNDLE_EXCEPTION;
+        }
+    }
+    while (semOpStatus == -1 && errno == EINTR);
+
+    return status;
+}
+
+celix_status_t remoteServiceAdmin_wait(int semId, int semNr)
+{
+    celix_status_t status = CELIX_SUCCESS;
+    int semOpStatus = 0;
+    struct sembuf semOperation;
+
+    semOperation.sem_num = semNr;
+    semOperation.sem_op = 0;
+    semOperation.sem_flg = 0;
+
+    do
+    {
+        status = CELIX_SUCCESS;
+
+        if ((semOpStatus = semop(semId, &semOperation, 1)) != 0)
+        {
+            status = CELIX_BUNDLE_EXCEPTION;
+        }
+    }
+    while (semOpStatus == -1 && errno == EINTR);
+
+    return status;
+}
+
+
+celix_status_t remoteServiceAdmin_send(remote_service_admin_pt admin, endpoint_description_pt recpEndpoint, char *method, char *data, char **reply, int *replyStatus)
+{
+
+    celix_status_t status = CELIX_SUCCESS;
+    ipc_segment_pt ipc = NULL;
+
+    if ((ipc = hashMap_get(admin->importedIpcSegment, recpEndpoint->service)) != NULL)
+    {
+        hash_map_pt fncCallProps = hashMap_create(utils_stringHash, utils_stringHash, utils_stringEquals, utils_stringEquals);
+        char *encFncCallProps = NULL;
+        int semid = ipc->semId;
+
+        /* write method and data */
+        hashMap_put(fncCallProps, RSA_FUNCTIONCALL_METHOD_PROPERTYNAME, method);
+        hashMap_put(fncCallProps, RSA_FUNCTIONCALL_DATA_PROPERTYNAME, data);
+
+        if ((status = netstring_encodeFromHashMap(admin->pool, fncCallProps, &encFncCallProps)) == CELIX_SUCCESS)
+        {
+            char *fncCallReply = NULL;
+            char *fncCallReplyStatus = CELIX_SUCCESS;
+
+            strcpy(ipc->shmBaseAdress, encFncCallProps);
+
+            remoteServiceAdmin_unlock(semid, 0);//sem0: 0 -> 1
+            remoteServiceAdmin_wait(semid, 2);//sem2: when 0 continue
+            remoteServiceAdmin_lock(semid, 1);//sem1: 1 -> 0
+
+            if ((status = netstring_decodeToHashMap(admin->pool, ipc->shmBaseAdress, fncCallProps)) == CELIX_SUCCESS)
+            {
+                fncCallReply = hashMap_get(fncCallProps, RSA_FUNCTIONCALL_RETURN_PROPERTYNAME);
+                fncCallReplyStatus = hashMap_get(fncCallProps, RSA_FUNCTIONCALL_RETURNSTATUS_PROPERTYNAME);
+            }
+
+            if (fncCallReply != NULL)
+            {
+            	*reply = strdup(fncCallReply);
+            }
+
+            if (fncCallReplyStatus != NULL)
+            {
+            	*replyStatus = apr_atoi64(fncCallReplyStatus);
+            }
+        }
+
+        hashMap_destroy(fncCallProps, false, false);
+    }
+    else
+    {
+        status = CELIX_ILLEGAL_STATE;       /* could not find ipc segment */
+    }
+
+    return status;
+}
+
+
+static void *APR_THREAD_FUNC remoteServiceAdmin_receiveFromSharedMemory(apr_thread_t *thd, void *data)
+{
+    celix_status_t status = CELIX_SUCCESS;
+    recv_shm_thread_pt thread_data = data;
+
+    remote_service_admin_pt admin = thread_data->admin;
+    endpoint_description_pt exportedEndpointDesc = thread_data->endpointDescription;
+
+    ipc_segment_pt ipc;
+
+    if ((ipc = hashMap_get(admin->exportedIpcSegment, exportedEndpointDesc->service)) != NULL)
+    {
+        celix_status_t status = CELIX_SUCCESS;
+        bool *pollThreadRunning = hashMap_get(admin->pollThreadRunning, exportedEndpointDesc);
+
+        while (*pollThreadRunning == true)
+        {
+            // wait on semaphore 3 //sem3: when 0 continue
+            if ((remoteServiceAdmin_wait(ipc->semId, 3) != CELIX_SUCCESS))
+            {
+                printf("RSA : Error waiting on semaphore 3");
+            }
+            // acquire READ semaphore //sem0: 1 -> 0
+            else if (((status = remoteServiceAdmin_lock(ipc->semId, 0)) == CELIX_SUCCESS) && (*pollThreadRunning == true))
+            {
+                hash_map_pt receivedMethodCall = hashMap_create(utils_stringHash, utils_stringHash, utils_stringEquals, utils_stringEquals);
+
+                if ((status = netstring_decodeToHashMap(admin->pool, ipc->shmBaseAdress, receivedMethodCall)) != CELIX_SUCCESS)
+                {
+                    printf("DISCOVERY : receiveFromSharedMemory : decoding data to Properties\n");
+                }
+                else
+                {
+                    char *method = hashMap_get(receivedMethodCall, RSA_FUNCTIONCALL_METHOD_PROPERTYNAME);
+                    char *data = hashMap_get(receivedMethodCall, RSA_FUNCTIONCALL_DATA_PROPERTYNAME);
+
+                    if (method == NULL)
+                    {
+                        printf("RSA : receiveFromSharedMemory : no method found. \n");
+                    }
+                    else
+                    {
+                        hash_map_iterator_pt iter = hashMapIterator_create(admin->exportedServices);
+
+                        while (hashMapIterator_hasNext(iter))
+                        {
+                            hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+                            array_list_pt exports = hashMapEntry_getValue(entry);
+                            int expIt = 0;
+
+                            for (expIt = 0; expIt < arrayList_size(exports); expIt++)
+                            {
+                                export_registration_pt export = arrayList_get(exports, expIt);
+
+                                if ( (strcmp(exportedEndpointDesc->service, export->endpointDescription->service) == 0) && (export->endpoint != NULL))
+                                {
+                                    char *reply = NULL;
+                                    char *encReply = NULL;
+
+                                    celix_status_t replyStatus = export->endpoint->handleRequest(export->endpoint->endpoint, method, data, &reply);
+                                    hashMap_put(receivedMethodCall, RSA_FUNCTIONCALL_RETURNSTATUS_PROPERTYNAME, apr_itoa(admin->pool, replyStatus));
+
+                                    if (reply != NULL)
+                                    {
+                                        hashMap_put(receivedMethodCall, RSA_FUNCTIONCALL_RETURN_PROPERTYNAME, reply);
+
+                                        // write back
+                                        if ((status = netstring_encodeFromHashMap(admin->pool, receivedMethodCall, &encReply)) == CELIX_SUCCESS)
+                                        {
+
+                                            if ((strlen(encReply) * sizeof(char)) >= RSA_SHM_MEMSIZE)
+                                            {
+                                                printf("RSA : receiveFromSharedMemory : size of message bigger than shared memory message. NOT SENDING.\n");
+                                            }
+                                            else
+                                            {
+                                                strcpy(ipc->shmBaseAdress, encReply);
+                                            }
+                                        }
+                                        else
+                                        {
+                                            printf("RSA : receiveFromSharedMemory : encoding of reply failed\n");
+                                        }
+                                    }
+                                }
+                                else
+                                {
+                                    printf("RSA : receiveFromSharedMemory : No endpoint set for %s\n", export->endpointDescription->service );
+                                }
+                            }
+                        }
+
+                        remoteServiceAdmin_unlock(ipc->semId, 1); //sem1: 0 -> 1
+                    }
+                }
+                hashMap_destroy(receivedMethodCall, false, false);
+            }
+        }
+    }
+    apr_thread_exit(thd, (status == CELIX_SUCCESS) ? APR_SUCCESS : -1);
+
+    return NULL;
+}
+
+
+
+
+
+
+
+
+celix_status_t remoteServiceAdmin_exportService(remote_service_admin_pt admin, char *serviceId, properties_pt properties, array_list_pt *registrations)
+{
+    celix_status_t status = CELIX_SUCCESS;
+    arrayList_create(registrations);
+
+    array_list_pt references = NULL;
+    service_reference_pt reference = NULL;
+    service_registration_pt registration = NULL;
+
+    apr_pool_t *tmpPool = NULL;
+
+    apr_pool_create(&tmpPool, admin->pool);
+    if (tmpPool == NULL)
+    {
+        return CELIX_ENOMEM;
+    }
+    else
+    {
+        char *filter = apr_pstrcat(admin->pool, "(", (char *) OSGI_FRAMEWORK_SERVICE_ID, "=", serviceId, ")", NULL); /*FIXME memory leak*/
+        bundleContext_getServiceReferences(admin->context, NULL, filter, &references);
+        apr_pool_destroy(tmpPool);
+        if (arrayList_size(references) >= 1)
+        {
+            reference = arrayList_get(references, 0);
+        }
+    }
+
+    if (reference == NULL)
+    {
+        printf("ERROR: expected a reference for service id %s\n", serviceId);
+        return CELIX_ILLEGAL_STATE;
+    }
+
+    serviceReference_getServiceRegistration(reference, &registration);
+    properties_pt serviceProperties = NULL;
+    serviceRegistration_getProperties(registration, &serviceProperties);
+    char *exports = properties_get(serviceProperties, (char *) OSGI_RSA_SERVICE_EXPORTED_INTERFACES);
+    char *provided = properties_get(serviceProperties, (char *) OSGI_FRAMEWORK_OBJECTCLASS);
+
+    if (exports == NULL || provided == NULL)
+    {
+        printf("RSA: No Services to export.\n");
+    }
+    else
+    {
+        printf("RSA: Export services (%s)\n", exports);
+        array_list_pt interfaces = NULL;
+        arrayList_create(&interfaces);
+        if (strcmp(utils_stringTrim(exports), "*") == 0)
+        {
+            char *token;
+            char *interface = apr_strtok(provided, ",", &token);
+            while (interface != NULL)
+            {
+                arrayList_add(interfaces, utils_stringTrim(interface));
+                interface = apr_strtok(NULL, ",", &token);
+            }
+        }
+        else
+        {
+            char *exportToken;
+            char *providedToken;
+
+            char *pinterface = apr_strtok(provided, ",", &providedToken);
+            while (pinterface != NULL)
+            {
+                char *einterface = apr_strtok(exports, ",", &exportToken);
+                while (einterface != NULL)
+                {
+                    if (strcmp(einterface, pinterface) == 0)
+                    {
+                        arrayList_add(interfaces, einterface);
+                    }
+                    einterface = apr_strtok(NULL, ",", &exportToken);
+                }
+                pinterface = apr_strtok(NULL, ",", &providedToken);
+            }
+        }
+
+        if (arrayList_size(interfaces) != 0)
+        {
+            int iter = 0;
+            for (iter = 0; iter < arrayList_size(interfaces); iter++)
+            {
+                char *interface = arrayList_get(interfaces, iter);
+                export_registration_pt registration = NULL;
+
+                exportRegistration_create(admin->pool, reference, NULL, admin, admin->context, &registration);
+
+                arrayList_add(*registrations, registration);
+
+                remoteServiceAdmin_installEndpoint(admin, registration, reference, interface);
+                exportRegistration_open(registration);
+                exportRegistration_startTracking(registration);
+
+                if ( remoteServiceAdmin_createOrAttachShm(admin->exportedIpcSegment, admin, registration->endpointDescription, true) == CELIX_SUCCESS)
+                {
+                    recv_shm_thread_pt recvThreadData = NULL;
+
+                    if ((recvThreadData = apr_palloc(admin->pool, sizeof(*recvThreadData))) == NULL)
+                    {
+                        status = CELIX_ENOMEM;
+                    }
+                    else
+                    {
+                        recvThreadData->admin = admin;
+                        recvThreadData->endpointDescription = registration->endpointDescription;
+
+                        apr_thread_t *pollThread = NULL;
+                        bool *pollThreadRunningPtr = apr_palloc(admin->pool, sizeof(*pollThreadRunningPtr));
+                        *pollThreadRunningPtr  = true;
+
+                        hashMap_put(admin->pollThreadRunning, registration->endpointDescription, pollThreadRunningPtr);
+
+                        // start receiving thread
+                        apr_thread_create(&pollThread, NULL, remoteServiceAdmin_receiveFromSharedMemory, recvThreadData, (admin)->pool);
+
+                        hashMap_put(admin->pollThread, registration->endpointDescription, pollThread);
+                    }
+                }
+            }
+
+            hashMap_put(admin->exportedServices, reference, *registrations);
+        }
+    }
+
+    return status;
+}
+
+
+celix_status_t remoteServiceAdmin_removeExportedService(export_registration_pt registration)
+{
+    celix_status_t status = CELIX_SUCCESS;
+    remote_service_admin_pt admin = registration->rsa;
+    bool *pollThreadRunning = NULL;
+    ipc_segment_pt ipc = NULL;
+    apr_thread_t *pollThread = NULL;
+
+    hashMap_remove(admin->exportedServices, registration->reference);
+
+    if ((pollThreadRunning = hashMap_get(admin->pollThreadRunning, registration->endpointDescription)) != NULL)
+    {
+        *pollThreadRunning = false;
+    }
+
+    if ((ipc = hashMap_get(admin->exportedIpcSegment, registration->endpointDescription->service)) != NULL)
+    {
+        remoteServiceAdmin_unlock(ipc->semId, 0);
+
+        if ( (pollThread = hashMap_get(admin->pollThread, registration->endpointDescription)) != NULL)
+        {
+            apr_status_t tstat;
+            apr_status_t stat = apr_thread_join(&tstat, pollThread);
+
+            if (stat != APR_SUCCESS && tstat != APR_SUCCESS)
+            {
+                status = CELIX_BUNDLE_EXCEPTION;
+            }
+            else
+            {
+                semctl(ipc->semId, 1 /*ignored*/, IPC_RMID);
+                shmctl(ipc->shmId, IPC_RMID, 0);
+
+                hashMap_remove(admin->pollThreadRunning, registration->endpointDescription);
+                hashMap_remove(admin->exportedIpcSegment, registration->endpointDescription->service);
+                hashMap_remove(admin->pollThread, registration->endpointDescription);
+            }
+        }
+    }
+
+
+    return status;
+}
+
+
+celix_status_t remoteServiceAdmin_createOrAttachShm(hash_map_pt ipcSegment, remote_service_admin_pt admin, endpoint_description_pt endpointDescription, bool createIfNotFound)
+{
+    celix_status_t status = CELIX_SUCCESS;
+
+    apr_pool_t *pool = admin->pool;
+    apr_pool_t *shmPool = NULL;
+
+    apr_status_t aprStatus = 0;
+
+    /* setup ipc sehment */
+    ipc_segment_pt ipc = NULL;
+
+    properties_pt endpointProperties = endpointDescription->properties;
+
+    char *shmPath = NULL;
+    char *shmFtokId = NULL;
+
+    char *semPath = NULL;
+    char *semFtokId = NULL;
+
+
+    if ((shmPath = properties_get(endpointProperties, (char *) RSA_SHM_PATH_PROPERTYNAME)) == NULL)
+    {
+        printf("RSA : No value found for key %s in endpointProperties\n", RSA_SHM_PATH_PROPERTYNAME);
+        status = CELIX_BUNDLE_EXCEPTION;
+    }
+    else if ((shmFtokId = properties_get(endpointProperties, (char *) RSA_SHM_FTOK_ID_PROPERTYNAME)) == NULL)
+    {
+        printf("RSA : No value found for key %s in endpointProperties\n", RSA_SHM_FTOK_ID_PROPERTYNAME);
+        status = CELIX_BUNDLE_EXCEPTION;
+    }
+    else if ((semPath = properties_get(endpointProperties, (char *) RSA_SEM_PATH_PROPERTYNAME)) == NULL)
+    {
+        printf("RSA : No value found for key %s in endpointProperties\n", RSA_SEM_PATH_PROPERTYNAME);
+        status = CELIX_BUNDLE_EXCEPTION;
+    }
+    else if ((semFtokId = properties_get(endpointProperties, (char *) RSA_SEM_FTOK_ID_PROPERTYNAME)) == NULL)
+    {
+        printf("RSA : No value found for key %s in endpointProperties\n", RSA_SEM_FTOK_ID_PROPERTYNAME);
+        status = CELIX_BUNDLE_EXCEPTION;
+    }
+    else
+    {
+        key_t shmKey = ftok(shmPath, atoi(shmFtokId));
+        ipc = apr_palloc(admin->pool, sizeof(*ipc));
+
+        if ((ipc->shmId = shmget(shmKey, RSA_SHM_MEMSIZE, 0666)) < 0)
+        {
+            printf("RSA : Could not attach to shared memory\n");
+
+            if (createIfNotFound == true)
+            {
+                if ((ipc->shmId = shmget(shmKey, RSA_SHM_MEMSIZE, IPC_CREAT | 0666)) < 0)
+                {
+                    printf("RSA : Creation of shared memory segment failed\n");
+                    status = CELIX_BUNDLE_EXCEPTION;
+                }
+                else if ((ipc->shmBaseAdress = shmat(ipc->shmId, 0, 0)) == (char *) - 1 )
+                {
+                    printf("RSA : Attaching of shared memory segment failed\n");
+                    status = CELIX_BUNDLE_EXCEPTION;
+                }
+                else
+                {
+                    printf("RSA : shared memory segment sucessfully created at %p \n", ipc->shmBaseAdress);
+                }
+            }
+        }
+        else if ((ipc->shmBaseAdress = shmat(ipc->shmId, 0, 0)) == (char *) - 1 )
+        {
+            printf("RSA : Attaching of shared memory segment failed\n");
+            status = CELIX_BUNDLE_EXCEPTION;
+        }
+        else
+        {
+            printf("RSA : sucessfully attached to shared memory at %p \n", ipc->shmBaseAdress);
+        }
+    }
+
+    if ((status == CELIX_SUCCESS) && (ipc != NULL))
+    {
+        key_t semkey = ftok(semPath, atoi(semFtokId));
+        int semflg = (createIfNotFound == true) ? (0666 | IPC_CREAT) : (0666);
+        int semid = semget(semkey, 4, semflg);
+
+        if (semid != -1)
+        {
+            // only reset semaphores if a create was supposed
+            if ((createIfNotFound == true) && ((semctl (semid, 0, SETVAL, (int) 0) == -1) || (semctl (semid, 1, SETVAL, (int) 0) == -1) || (semctl (semid, 2, SETVAL, (int) 0) == -1) || (semctl (semid, 3, SETVAL, (int) 0) == -1)))
+            {
+                printf("RSA : error while initialize semaphores \n");
+            }
+
+            printf("RSA : semaphores w/ key %s and id %i added \n", endpointDescription->service, semid);
+            ipc->semId = semid;
+
+            hashMap_put(ipcSegment, endpointDescription->service, ipc);
+        }
+        else
+        {
+            printf("RSA : error getting semaphores.\n");
+            status = CELIX_BUNDLE_EXCEPTION;
+        }
+    }
+
+    return status;
+}
+
+
+
+celix_status_t remoteServiceAdmin_installEndpoint(remote_service_admin_pt admin, export_registration_pt registration, service_reference_pt reference, char *interface)
+{
+    celix_status_t status = CELIX_SUCCESS;
+    properties_pt endpointProperties = properties_create();
+    properties_pt serviceProperties = NULL;
+
+    service_registration_pt sRegistration = NULL;
+    serviceReference_getServiceRegistration(reference, &sRegistration);
+
+    serviceRegistration_getProperties(sRegistration, &serviceProperties);
+
+    hash_map_iterator_pt iter = hashMapIterator_create(serviceProperties);
+    while (hashMapIterator_hasNext(iter))
+    {
+        hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+        char *key = (char *) hashMapEntry_getKey(entry);
+        char *value = (char *) hashMapEntry_getValue(entry);
+
+        properties_set(endpointProperties, key, value);
+    }
+    char *serviceId = (char *) hashMap_remove(endpointProperties, (void *) OSGI_FRAMEWORK_SERVICE_ID);
+    properties_set(endpointProperties, (char *) OSGI_FRAMEWORK_OBJECTCLASS, interface);
+    properties_set(endpointProperties, (char *) OSGI_RSA_ENDPOINT_SERVICE_ID, serviceId);
+
+    char *uuid = NULL;
+    bundleContext_getProperty(admin->context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &uuid);
+    properties_set(endpointProperties, (char *) OSGI_RSA_ENDPOINT_FRAMEWORK_UUID, uuid);
+    properties_set(endpointProperties, (char *) OSGI_RSA_SERVICE_LOCATION, apr_pstrdup(admin->pool, interface));
+    if (properties_get(endpointProperties, (char *) RSA_SHM_PATH_PROPERTYNAME) == NULL)
+    {
+        properties_set(endpointProperties, (char *) RSA_SHM_PATH_PROPERTYNAME, apr_pstrdup(admin->pool, (char *) RSA_SHM_DEFAULTPATH));
+    }
+    if (properties_get(endpointProperties, (char *) RSA_SHM_FTOK_ID_PROPERTYNAME) == NULL)
+    {
+        properties_set(endpointProperties, (char *) RSA_SHM_FTOK_ID_PROPERTYNAME, apr_pstrdup(admin->pool, (char *) RSA_SHM_DEFAULT_FTOK_ID));
+    }
+    if (properties_get(endpointProperties, (char *) RSA_SEM_PATH_PROPERTYNAME) == NULL)
+    {
+        properties_set(endpointProperties, (char *) RSA_SEM_PATH_PROPERTYNAME, apr_pstrdup(admin->pool, RSA_SEM_DEFAULTPATH));
+    }
+    if (properties_get(endpointProperties, (char *) RSA_SEM_FTOK_ID_PROPERTYNAME) == NULL)
+    {
+        properties_set(endpointProperties, (char *) RSA_SEM_FTOK_ID_PROPERTYNAME, apr_pstrdup(admin->pool, (char *) RSA_SEM_DEFAULT_FTOK_ID));
+    }
+
+    endpoint_description_pt endpointDescription = NULL;
+    remoteServiceAdmin_createEndpointDescription(admin, serviceProperties, endpointProperties, interface, &endpointDescription);
+    exportRegistration_setEndpointDescription(registration, endpointDescription);
+
+    return status;
+}
+
+celix_status_t remoteServiceAdmin_createEndpointDescription(remote_service_admin_pt admin, properties_pt serviceProperties,
+        properties_pt endpointProperties, char *interface, endpoint_description_pt *description)
+{
+    celix_status_t status = CELIX_SUCCESS;
+
+    apr_pool_t *childPool = NULL;
+    apr_pool_create(&childPool, admin->pool);
+
+    *description = apr_palloc(childPool, sizeof(*description));
+
+    if (!*description)
+    {
+        status = CELIX_ENOMEM;
+    }
+    else
+    {
+        char *uuid = NULL;
+        status = bundleContext_getProperty(admin->context, OSGI_RSA_ENDPOINT_FRAMEWORK_UUID, &uuid);
+        if (status == CELIX_SUCCESS)
+        {
+            (*description)->properties = endpointProperties;
+            (*description)->frameworkUUID = uuid;
+            (*description)->serviceId = apr_atoi64(properties_get(serviceProperties, (char *) OSGI_FRAMEWORK_SERVICE_ID));
+            (*description)->id = properties_get(endpointProperties, (char *) OSGI_RSA_SERVICE_LOCATION);
+            (*description)->service = interface;
+        }
+    }
+
+    return status;
+}
+
+celix_status_t remoteServiceAdmin_getExportedServices(remote_service_admin_pt admin, array_list_pt *services)
+{
+    celix_status_t status = CELIX_SUCCESS;
+    return status;
+}
+
+celix_status_t remoteServiceAdmin_getImportedEndpoints(remote_service_admin_pt admin, array_list_pt *services)
+{
+    celix_status_t status = CELIX_SUCCESS;
+    return status;
+}
+
+celix_status_t remoteServiceAdmin_importService(remote_service_admin_pt admin, endpoint_description_pt endpointDescription, import_registration_pt *registration)
+{
+    celix_status_t status = CELIX_SUCCESS;
+
+    printf("RSA: Import service %s\n", endpointDescription->service);
+
+    importRegistration_create(admin->pool, endpointDescription, admin, admin->context, registration);
+
+    array_list_pt importedRegs = hashMap_get(admin->importedServices, endpointDescription);
+    if (importedRegs == NULL)
+    {
+        arrayList_create(&importedRegs);
+        hashMap_put(admin->importedServices, endpointDescription, importedRegs);
+
+    }
+    arrayList_add(importedRegs, *registration);
+
+    importRegistration_open(*registration);
+    importRegistration_startTracking(*registration);
+    remoteServiceAdmin_createOrAttachShm(admin->importedIpcSegment, admin, endpointDescription, false);
+
+    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)
+{
+    celix_status_t status = CELIX_SUCCESS;
+    return status;
+}
+
+celix_status_t importReference_getImportedEndpoint(import_reference_pt reference)
+{
+    celix_status_t status = CELIX_SUCCESS;
+    return status;
+}
+
+celix_status_t importReference_getImportedService(import_reference_pt reference)
+{
+    celix_status_t status = CELIX_SUCCESS;
+    return status;
+}
+

Added: incubator/celix/trunk/remote_services/remote_service_admin_shm/public/include/remote_service_admin_shm.h
URL: http://svn.apache.org/viewvc/incubator/celix/trunk/remote_services/remote_service_admin_shm/public/include/remote_service_admin_shm.h?rev=1556172&view=auto
==============================================================================
--- incubator/celix/trunk/remote_services/remote_service_admin_shm/public/include/remote_service_admin_shm.h (added)
+++ incubator/celix/trunk/remote_services/remote_service_admin_shm/public/include/remote_service_admin_shm.h Tue Jan  7 10:33:55 2014
@@ -0,0 +1,36 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * remote_service_admin_shm.h
+ *
+ *  \date       Sep 30, 2011
+ *  \author    	<a href="mailto:celix-dev@incubator.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef REMOTE_SERVICE_ADMIN_SHM_H_
+#define REMOTE_SERVICE_ADMIN_SHM_H_
+
+#define RSA_FUNCTIONCALL_METHOD_PROPERTYNAME "method"
+#define RSA_FUNCTIONCALL_DATA_PROPERTYNAME "data"
+#define RSA_FUNCTIONCALL_RETURN_PROPERTYNAME "reply"
+#define RSA_FUNCTIONCALL_RETURNSTATUS_PROPERTYNAME "replyStatus"
+
+
+#endif /* REMOTE_SERVICE_ADMIN_SHM_H_ */

Modified: incubator/celix/trunk/utils/CMakeLists.txt
URL: http://svn.apache.org/viewvc/incubator/celix/trunk/utils/CMakeLists.txt?rev=1556172&r1=1556171&r2=1556172&view=diff
==============================================================================
--- incubator/celix/trunk/utils/CMakeLists.txt (original)
+++ incubator/celix/trunk/utils/CMakeLists.txt Tue Jan  7 10:33:55 2014
@@ -37,7 +37,9 @@ if (UTILS) 
 		public/include/linkedlist.h
 		public/include/linked_list_iterator.h 
 		private/include/linked_list_private.h
-		
+
+		private/src/netstring.c
+		public/include/netstring.h
 		public/include/exports.h
 	)
     
@@ -71,11 +73,16 @@ if (UTILS) 
 	    
 	    add_executable(linked_list_test private/test/linked_list_test.c)
 	    target_link_libraries(linked_list_test celix_utils ${CUNIT_LIBRARIES})
+
+	    add_executable(netstring_test private/test/netstring_test.c)
+	    target_link_libraries(netstring_test celix_utils celix_framework ${CUNIT_LIBRARIES})
+		    
 	    
 	    run_test(array_list_test2)
 	    run_test(hash_map_test)
 	    run_test(hash_map_test_hash)
 	    run_test(linked_list_test)
+	    run_test(netstring_test)
 	    
 	    ADD_TARGET_FOR_TEST(array_list_test)
     endif(UTILS-TESTS)

Added: incubator/celix/trunk/utils/private/src/netstring.c
URL: http://svn.apache.org/viewvc/incubator/celix/trunk/utils/private/src/netstring.c?rev=1556172&view=auto
==============================================================================
--- incubator/celix/trunk/utils/private/src/netstring.c (added)
+++ incubator/celix/trunk/utils/private/src/netstring.c Tue Jan  7 10:33:55 2014
@@ -0,0 +1,507 @@
+/**
+ *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.
+ */
+/*
+ * netstring.c
+ *
+ *  \date       Sep 13, 2013
+ *  \author    	<a href="mailto:celix-dev@incubator.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#include <apr_general.h>
+#include <apr_strings.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+
+#include "hash_map.h"
+#include "netstring.h"
+#include "utils.h"
+
+
+
+int netstring_getNetStringLength(char* inNetStr)
+{
+	int posCnt = 0;
+	int inNetStrLen = 0;
+
+	while((posCnt < strlen(inNetStr)) && (isdigit(inNetStr[posCnt])))
+	{
+		inNetStrLen = (inNetStrLen*10) + (inNetStr[posCnt] - '0');
+		posCnt++;
+	}
+
+	return inNetStrLen;
+}
+
+/**
+ * in: "hallo"
+ * out: "5:hallo,"
+ */
+celix_status_t netstring_encode(apr_pool_t *pool, char* inStr, char **outNetStr)
+{
+	celix_status_t status = CELIX_SUCCESS;
+
+	if((inStr != NULL) && (strlen(inStr) > 0))
+	{
+		char* inStrLen = apr_itoa(pool, strlen(inStr));
+		*outNetStr = apr_pstrcat(pool, inStrLen, ":", inStr, ",", NULL);
+	}
+	else
+	{
+		status = CELIX_BUNDLE_EXCEPTION;
+	}
+
+	return status;
+}
+
+/**
+ * in: "5:hallo,"
+ * out: "hallo"
+ *
+ */
+celix_status_t netstring_decode(apr_pool_t *pool, char* inNetStr, char **outStr)
+{
+	celix_status_t status = CELIX_SUCCESS;
+
+	if((inNetStr != NULL) && (strlen(inNetStr) > 0))
+	{
+		int inNetStrNumOfDigits = 0;
+		int inNetStrLen = 0;
+
+		// retrieve length of netstring
+		inNetStrLen = netstring_getNetStringLength(inNetStr);
+		inNetStrNumOfDigits = ceil(log10( (double) inNetStrLen + 1 ));
+
+		if((inNetStrNumOfDigits == strlen(inNetStr)) || (inNetStr[inNetStrNumOfDigits] !=':') || ((inNetStrLen+inNetStrNumOfDigits+2) > strlen(inNetStr)))
+		{
+			status = CELIX_ILLEGAL_ARGUMENT;
+		}
+		else
+		{
+			*outStr = apr_pstrmemdup(pool, (inNetStr+inNetStrNumOfDigits+1), inNetStrLen);
+		}
+	}
+	else
+	{
+		status = CELIX_BUNDLE_EXCEPTION;
+	}
+
+	return status;
+}
+
+celix_status_t netstring_custEncodeFromArray(apr_pool_t *pool, void *inStrArr[], customEncoderCallback inCallback, int inArrLen, char** outNetStr)
+{
+	celix_status_t status = CELIX_SUCCESS;
+
+	int arrCnt = 0;
+	char* totalOutStr = "";
+
+	for(; (arrCnt < inArrLen) && (status == CELIX_SUCCESS); arrCnt++)
+	{
+		char* singleOutStr = NULL;
+
+		if ((status = inCallback(pool, inStrArr[arrCnt], &singleOutStr)) == CELIX_SUCCESS)
+		{
+			totalOutStr = apr_pstrcat(pool, totalOutStr, singleOutStr, NULL);
+		}
+	}
+
+	if (status == CELIX_SUCCESS)
+	{
+		*outNetStr = totalOutStr;
+	}
+
+	return status;
+}
+
+
+/**
+ * in: {"hallo", "tom" }
+ * out: "5:hallo,3:tom,"
+  */
+
+celix_status_t netstring_encodeFromArray(apr_pool_t *pool, char *inStrArr[], int inArrLen, char** outNetStr)
+{
+	return netstring_custEncodeFromArray(pool, (void**) inStrArr, (customEncoderCallback) netstring_encode, inArrLen, outNetStr);
+}
+
+
+
+celix_status_t netstring_custDecodeFromArray(apr_pool_t *pool, char* inNetStr, customDecoderCallback inCallback, void **outStrArr[], int *outArrSize)
+{
+	celix_status_t status = CELIX_SUCCESS;
+
+	// get number of elements
+	int netStrElementCnt = 0;
+	int netStrElementLen = netstring_getNetStringLength(inNetStr);
+	int netStrTotalLen = 0;
+	int netStrNumOfDigits = 0;
+
+	for(;netStrTotalLen < strlen(inNetStr) && netStrElementLen > 0; netStrElementCnt++)
+	{
+		netStrElementLen = netstring_getNetStringLength(inNetStr + netStrTotalLen);
+
+		netStrNumOfDigits = ceil(log10( (double) netStrElementLen + 1 ));
+		netStrTotalLen += netStrElementLen + netStrNumOfDigits + 2; /* colon and comma */;
+	}
+
+	// num of elements
+	*outStrArr = apr_palloc(pool, netStrElementCnt * sizeof(*outStrArr));
+	*outArrSize = netStrElementCnt;
+
+	// assign
+	for(netStrTotalLen = 0, netStrElementCnt = 0; (netStrTotalLen < strlen(inNetStr)) && (status == CELIX_SUCCESS); netStrElementCnt++)
+	{
+		netStrElementLen = netstring_getNetStringLength(inNetStr + netStrTotalLen);
+		status = inCallback(pool, (inNetStr + netStrTotalLen), &(*outStrArr)[netStrElementCnt]);
+		//status = netstring_decode(pool, (inNetStr + netStrTotalLen), &(*outStrArr)[netStrElementCnt]);
+		netStrNumOfDigits = ceil(log10( (double) netStrElementLen + 1 ));
+		netStrTotalLen += netStrElementLen + netStrNumOfDigits + 2; /* colon and comman */;
+	}
+
+	return status;
+}
+
+
+/**
+ * in: "5:hallo,3:tom,"
+ * out: {"hallo", "tom" }
+  */
+celix_status_t netstring_decodetoArray(apr_pool_t *pool, char* inNetStr, char **outStrArr[], int *outArrSize)
+{
+
+	return netstring_custDecodeFromArray(pool, inNetStr, (customDecoderCallback) netstring_decode, (void***) outStrArr, outArrSize);
+}
+
+
+
+
+celix_status_t netstring_encodeFromHashMap(apr_pool_t *pool, hash_map_pt inHashMap, char** outNetStr)
+{
+	celix_status_t status = CELIX_SUCCESS;
+
+	hash_map_iterator_pt prpItr = hashMapIterator_create(inHashMap);
+	char *completeEncKeyValStr = "";
+
+	while((hashMapIterator_hasNext(prpItr) == true) && (status == CELIX_SUCCESS) )
+	{
+		hash_map_entry_pt prpEntry = hashMapIterator_nextEntry(prpItr);
+
+		char *key = hashMapEntry_getKey(prpEntry);
+		char *val = hashMapEntry_getValue(prpEntry);
+
+		if ((key == NULL) || (val == NULL) )
+		{
+			status = CELIX_ILLEGAL_ARGUMENT;
+		}
+		else
+		{
+			char *keyValStr = apr_pstrcat(pool, "(key:", key, "=value:", val, ")", NULL);
+			char *encKeyValStr = "";
+
+			if ((status = netstring_encode(pool, keyValStr, &encKeyValStr)) == CELIX_SUCCESS)
+			{
+				completeEncKeyValStr = apr_pstrcat(pool, completeEncKeyValStr, encKeyValStr, NULL);
+			}
+		}
+	}
+
+	hashMapIterator_destroy(prpItr);
+
+	*outNetStr = completeEncKeyValStr;
+
+	return status;
+}
+
+
+celix_status_t netstring_custEncodeFromHashMap(apr_pool_t *pool, hash_map_pt inHashMap, customEncoderCallback keyCallback, customEncoderCallback valCallback, char** outNetStr)
+{
+	celix_status_t status = CELIX_SUCCESS;
+
+	hash_map_iterator_pt prpItr = hashMapIterator_create(inHashMap);
+	char *completeEncKeyValStr = "";
+
+	while((hashMapIterator_hasNext(prpItr) == true) && (status == CELIX_SUCCESS) )
+	{
+		hash_map_entry_pt prpEntry = hashMapIterator_nextEntry(prpItr);
+
+		void *keyPtr = hashMapEntry_getKey(prpEntry);
+		char *key = keyPtr;
+		void *valPtr = hashMapEntry_getValue(prpEntry);
+		char *val = valPtr;
+
+		if (keyCallback != NULL)
+		{
+			status = keyCallback(pool, keyPtr, &key);
+		}
+
+		if  (valCallback != NULL && status == CELIX_SUCCESS)
+		{
+			status = valCallback(pool, valPtr, &val);
+		}
+
+		if ((key == NULL) || (val == NULL))
+		{
+			status = CELIX_ILLEGAL_ARGUMENT;
+		}
+		else if (status == CELIX_SUCCESS)
+		{
+			char *keyValStr = apr_pstrcat(pool, "(key:", key, "=value:", val, ")", NULL);
+			char *encKeyValStr = "";
+
+			if ((status = netstring_encode(pool, keyValStr, &encKeyValStr)) == CELIX_SUCCESS)
+			{
+				completeEncKeyValStr = apr_pstrcat(pool, completeEncKeyValStr, encKeyValStr, NULL);
+			}
+		}
+	}
+
+	hashMapIterator_destroy(prpItr);
+
+	*outNetStr = completeEncKeyValStr;
+
+	return status;
+}
+
+
+
+
+
+celix_status_t netstring_decodeToHashMap(apr_pool_t *pool, char* inNetStr, hash_map_pt outHashMap)
+{
+	celix_status_t status = CELIX_SUCCESS;
+
+	int netStrElementCnt = 0;
+	int netStrElementLen = 0;
+	int netStrTotalLen = 0;
+	int netStrNumOfDigits = 0;
+
+	if (inNetStr == NULL || outHashMap == NULL)
+	{
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+	else
+	{
+		for(; (netStrTotalLen < strlen(inNetStr)) && (status == CELIX_SUCCESS); netStrElementCnt++)
+		{
+			char *singleString;
+
+			netStrElementLen = netstring_getNetStringLength(inNetStr + netStrTotalLen); /* colon and comman */;
+			status = netstring_decode(pool, (inNetStr + netStrTotalLen), &singleString);
+
+			// contains key = value pair
+			if ( (strncmp("(key:", singleString, 4) != 0) || (strstr(singleString, "=value:") == NULL) || (singleString[strlen(singleString)-1] != ')') )
+			{
+				status = CELIX_ILLEGAL_ARGUMENT;
+			}
+			else
+			{
+				char* index = strstr(singleString, "=value:");
+
+				// copy from "(key:" to "=value:"
+				char* key = apr_pstrndup(pool, singleString + 5, index - singleString - 5);
+				char* val = apr_pstrndup(pool, index + 7, strlen(singleString) - strlen(key) - 13);
+
+				hashMap_put(outHashMap, key, val);
+			}
+
+			netStrNumOfDigits = ceil(log10( (double) netStrElementLen + 1 ));
+			netStrTotalLen += netStrElementLen + netStrNumOfDigits + 2;
+		}
+	}
+
+	return status;
+}
+
+
+
+
+celix_status_t netstring_custDecodeToHashMap(apr_pool_t *pool, char* inNetStr, customDecoderCallback keyCallback, customDecoderCallback valCallback,  hash_map_pt outHashMap)
+{
+	celix_status_t status = CELIX_SUCCESS;
+
+	int netStrElementCnt = 0;
+	int netStrElementLen = 0;
+	int netStrTotalLen = 0;
+	int netStrNumOfDigits = 0;
+
+	if (inNetStr == NULL || outHashMap == NULL)
+	{
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+	else
+	{
+		for(; (netStrTotalLen < strlen(inNetStr)) && (status == CELIX_SUCCESS); netStrElementCnt++)
+		{
+			char *singleString;
+
+			netStrElementLen = netstring_getNetStringLength(inNetStr + netStrTotalLen); /* colon and comman */;
+			status = netstring_decode(pool, (inNetStr + netStrTotalLen), &singleString);
+
+			// contains key = value pair
+			if ( (strncmp("(key:", singleString, 4) != 0) || (strstr(singleString, "=value:") == NULL) || (singleString[strlen(singleString)-1] != ')') )
+			{
+				status = CELIX_ILLEGAL_ARGUMENT;
+			}
+			else
+			{
+				char* index = strstr(singleString, "=value:");
+
+				// copy from "(key:" to "=value:"
+				char* key = apr_pstrndup(pool, singleString + 5, index - singleString - 5);
+				void* keyPtr = key;
+				char* val = apr_pstrndup(pool, index + 7, strlen(singleString) - strlen(key) - 13);
+				void* valPtr = val;
+
+				if (keyCallback != NULL)
+				{
+					status = keyCallback(pool, key, &keyPtr);
+				}
+
+				if ((valCallback != NULL) && (status == CELIX_SUCCESS))
+				{
+					status = valCallback(pool, val, &valPtr);
+				}
+
+				if (status == CELIX_SUCCESS)
+				{
+					hashMap_put(outHashMap, keyPtr, valPtr);
+				}
+			}
+
+			netStrNumOfDigits = ceil(log10( (double) netStrElementLen + 1 ));
+			netStrTotalLen += netStrElementLen + netStrNumOfDigits + 2;
+		}
+	}
+
+	return status;
+}
+
+
+
+celix_status_t netstring_encodeFromArrayList(apr_pool_t *pool, array_list_pt inList, char** outNetStr)
+{
+	return netstring_custEncodeFromArrayList(pool, inList, NULL, outNetStr);
+}
+
+
+
+celix_status_t netstring_custEncodeFromArrayList(apr_pool_t *pool, array_list_pt inList, customEncoderCallback encCallback, char** outNetStr)
+{
+	celix_status_t status = CELIX_SUCCESS;
+
+	array_list_iterator_pt listItr = arrayListIterator_create(inList);
+	char *completeEncListStr = "";
+
+	while((arrayListIterator_hasNext(listItr) == true) && (status == CELIX_SUCCESS) )
+	{
+		void* listEntryPtr = arrayListIterator_next(listItr);
+		char* listEntry = listEntryPtr;
+
+		if (encCallback != NULL)
+		{
+			status = encCallback(pool, listEntryPtr, &listEntry);
+		}
+
+		if (listEntry == NULL)
+		{
+			status = CELIX_ILLEGAL_ARGUMENT;
+		}
+		else if (status == CELIX_SUCCESS)
+		{
+			char *listEntryStr = apr_pstrcat(pool, "(", listEntry, ")", NULL);
+			char *encListEntryStr = NULL;
+
+			if ((status = netstring_encode(pool, listEntryStr, &encListEntryStr)) == CELIX_SUCCESS)
+			{
+				completeEncListStr = apr_pstrcat(pool, completeEncListStr, encListEntryStr, NULL);
+			}
+		}
+	}
+
+	arrayListIterator_destroy(listItr);
+
+	(*outNetStr) = completeEncListStr;
+
+	return status;
+}
+
+
+
+
+celix_status_t netstring_decodeToArrayList(apr_pool_t *pool, char* inNetStr, array_list_pt outArrayList)
+{
+	return netstring_custDecodeToArrayList(pool, inNetStr, NULL, outArrayList);
+}
+
+celix_status_t netstring_custDecodeToArrayList(apr_pool_t *pool, char* inNetStr, customDecoderCallback decCallback, array_list_pt outArrayList)
+{
+	celix_status_t status = CELIX_SUCCESS;
+
+	int netStrElementCnt = 0;
+	int netStrElementLen = 0;
+	int netStrTotalLen = 0;
+	int netStrNumOfDigits = 0;
+
+	if (inNetStr == NULL || outArrayList == NULL)
+	{
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+	else
+	{
+		for(; (netStrTotalLen < strlen(inNetStr)) && (status == CELIX_SUCCESS); netStrElementCnt++)
+		{
+			char *singleString;
+
+			netStrElementLen = netstring_getNetStringLength(inNetStr + netStrTotalLen); /* colon and comman */;
+			status = netstring_decode(pool, (inNetStr + netStrTotalLen), &singleString);
+
+			// check for braces
+			if ( (singleString[0] != '(') || (singleString[strlen(singleString)-1] != ')') )
+			{
+				status = CELIX_ILLEGAL_ARGUMENT;
+			}
+			else
+			{
+				// copy without braces
+				char* el = apr_pstrndup(pool, singleString + 1, strlen(singleString)-2);
+				void* elPtr = el;
+
+				if (decCallback != NULL)
+				{
+					status = decCallback(pool, el, &elPtr);
+				}
+
+				if (status == CELIX_SUCCESS)
+				{
+					arrayList_add(outArrayList, elPtr);
+				}
+			}
+
+			netStrNumOfDigits = ceil(log10( (double) netStrElementLen + 1 ));
+			netStrTotalLen += netStrElementLen + netStrNumOfDigits + 2;
+		}
+	}
+
+	return status;
+}

Added: incubator/celix/trunk/utils/private/test/netstring_test.c
URL: http://svn.apache.org/viewvc/incubator/celix/trunk/utils/private/test/netstring_test.c?rev=1556172&view=auto
==============================================================================
--- incubator/celix/trunk/utils/private/test/netstring_test.c (added)
+++ incubator/celix/trunk/utils/private/test/netstring_test.c Tue Jan  7 10:33:55 2014
@@ -0,0 +1,247 @@
+/**
+ *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.
+ */
+/*
+ * netstring_test.c
+ *
+ *  \date       Sep 13, 2013
+ *  \author    	<a href="mailto:celix-dev@incubator.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <CUnit/Automated.h>
+
+#include <apr_general.h>
+
+#include "celixbool.h"
+#include "hash_map.h"
+#include "utils.h"
+#include "netstring.h"
+
+
+
+apr_pool_t *pool;
+
+int setup(void)
+{
+	apr_initialize();
+	apr_pool_create(&pool, NULL);
+	return 0;
+}
+
+
+void test_netstring_encode(void)
+{
+	celix_status_t status;
+	char* inStr = "hello";
+	char* outNetStr = NULL;
+
+	status = netstring_encode(pool, inStr, &outNetStr);
+
+	CU_ASSERT_EQUAL(CELIX_SUCCESS, status);
+	CU_ASSERT_STRING_EQUAL("5:hello,", outNetStr);
+}
+
+
+
+void test_netstring_decode(void)
+{
+	celix_status_t status;
+	char* inNetStr = "5:hello,";
+	char* outStr = NULL;
+
+	status = netstring_decode(pool, inNetStr, &outStr);
+
+	CU_ASSERT_EQUAL(CELIX_SUCCESS, status);
+	CU_ASSERT_STRING_EQUAL("hello", outStr);
+
+	inNetStr = "26:celixnowsupportsnetstrings,33:netstringsareavailablewithincelix,";
+
+	status = netstring_decode(pool, inNetStr, &outStr);
+
+	CU_ASSERT_EQUAL(CELIX_SUCCESS, status);
+	CU_ASSERT_STRING_EQUAL("celixnowsupportsnetstrings", outStr);
+
+
+}
+
+
+
+void test_netstring_decodetoArray(void)
+{
+	celix_status_t status;
+	char* inNetStr = "5:hello,3:tom,";
+	char** outStrArr = NULL;
+	int size;
+
+	status = netstring_decodetoArray(pool, inNetStr, &outStrArr, &size);
+
+	CU_ASSERT_EQUAL(CELIX_SUCCESS, status);
+	CU_ASSERT_EQUAL(size, 2);
+	CU_ASSERT_STRING_EQUAL("hello", outStrArr[0]);
+	CU_ASSERT_STRING_EQUAL("tom", outStrArr[1]);
+
+	inNetStr = "26:celixnowsupportsnetstrings,33:netstringsareavailablewithincelix,";
+
+	status = netstring_decodetoArray(pool, inNetStr, &outStrArr, &size);
+
+	CU_ASSERT_EQUAL(CELIX_SUCCESS, status);
+	CU_ASSERT_EQUAL(size, 2);
+
+	CU_ASSERT_STRING_EQUAL("celixnowsupportsnetstrings", outStrArr[0]);
+	CU_ASSERT_STRING_EQUAL("netstringsareavailablewithincelix", outStrArr[1]);
+}
+
+
+void test_netstring_encodeFromArray(void)
+{
+	celix_status_t status;
+	char *inStrArr[4];
+	char *outStr;
+
+	inStrArr[0] = "celix";
+	inStrArr[1] = "-";
+	inStrArr[2] = "osgi";
+	inStrArr[3] = "in c";
+
+	status = netstring_encodeFromArray(pool, inStrArr, 4, &outStr);
+
+	CU_ASSERT_EQUAL(CELIX_SUCCESS, status);
+	CU_ASSERT_STRING_EQUAL("5:celix,1:-,4:osgi,4:in c,", outStr);
+}
+
+
+
+void test_netstring_decodetoHashMap(void)
+{
+	celix_status_t status;
+	char* inNetStr = "31:(key:helloKey=value:helloValue),27:(key:tomKey=value:tomValue),";
+	hash_map_pt outHashMap = hashMap_create(string_hash, string_hash, string_equals, string_equals);
+
+	status = netstring_decodeToHashMap(pool, inNetStr, outHashMap);
+
+	CU_ASSERT_EQUAL(CELIX_SUCCESS, status);
+	CU_ASSERT_EQUAL(hashMap_size(outHashMap), 2);
+
+	CU_ASSERT_STRING_EQUAL(hashMap_get(outHashMap, "helloKey"), "helloValue");
+	CU_ASSERT_STRING_EQUAL(hashMap_get(outHashMap, "tomKey"), "tomValue");
+
+	hashMap_destroy(outHashMap, false, false);
+}
+
+
+
+void test_netstring_encodeFromHashMap(void)
+{
+	celix_status_t status;
+	hash_map_pt inHashMap = hashMap_create(string_hash, string_hash, string_equals, string_equals);
+	char *outNetStr;
+
+	hashMap_put(inHashMap, "helloKey", "helloValue");
+	hashMap_put(inHashMap, "tomKey", "tomValue");
+
+	status = netstring_encodeFromHashMap(pool, inHashMap, &outNetStr);
+
+	CU_ASSERT_EQUAL(CELIX_SUCCESS, status);
+	CU_ASSERT_STRING_EQUAL("31:(key:helloKey=value:helloValue),27:(key:tomKey=value:tomValue),", outNetStr);
+
+	hashMap_destroy(inHashMap, false, false);
+}
+
+
+void test_netstring_decodetoArrayList(void)
+{
+	celix_status_t status;
+	char* inNetStr = "11:(misschien),11:(schrijven),";
+	array_list_pt outArrayList = NULL;
+
+	status = arrayList_create(pool, &outArrayList);
+	CU_ASSERT_EQUAL(CELIX_SUCCESS, status);
+
+	status = netstring_decodeToArrayList(pool, inNetStr, outArrayList);
+
+	CU_ASSERT_EQUAL(arrayList_size(outArrayList), 2);
+
+	CU_ASSERT_STRING_EQUAL(arrayList_get(outArrayList, 0), "misschien");
+	CU_ASSERT_STRING_EQUAL(arrayList_get(outArrayList, 1), "schrijven");
+
+	arrayList_destroy(outArrayList);
+}
+
+
+
+void test_netstring_encodeFromArrayList(void)
+{
+	celix_status_t status;
+	array_list_pt inArrayList = NULL;
+	char *outNetStr;
+
+	status = arrayList_create(pool, &inArrayList);
+	CU_ASSERT_EQUAL(CELIX_SUCCESS, status);
+
+	CU_ASSERT_TRUE(arrayList_add(inArrayList, "heel"));
+	CU_ASSERT_TRUE(arrayList_add(inArrayList, "bedankt"));
+
+	status = netstring_encodeFromArrayList(pool, inArrayList, &outNetStr);
+
+	CU_ASSERT_EQUAL(CELIX_SUCCESS, status);
+	CU_ASSERT_STRING_EQUAL("6:(heel),9:(bedankt),", outNetStr);
+
+	arrayList_destroy(inArrayList);
+}
+
+
+
+int main (int argc, char** argv) {
+	CU_pSuite pSuite = NULL;
+
+	/* initialize the CUnit test registry */
+	if (CUE_SUCCESS != CU_initialize_registry())
+	  return CU_get_error();
+
+	/* add a suite to the registry */
+	pSuite = CU_add_suite("Suite_1", setup, NULL);
+	if (NULL == pSuite) {
+	  CU_cleanup_registry();
+	  return CU_get_error();
+	}
+
+	/* add the tests to the suite */
+	if (NULL == CU_add_test(pSuite, "netstring encode test", test_netstring_encode)
+		|| NULL == CU_add_test(pSuite, "netstring decode test", test_netstring_decode)
+		|| NULL == CU_add_test(pSuite, "netstring decodeToArray test", test_netstring_decodetoArray)
+		|| NULL == CU_add_test(pSuite, "netstring encodeFromArray test", test_netstring_encodeFromArray)
+		|| NULL == CU_add_test(pSuite, "netstring decodeToHashMap test", test_netstring_decodetoHashMap)
+		|| NULL == CU_add_test(pSuite, "netstring encodeFromHashMap test", test_netstring_encodeFromHashMap)
+		|| NULL == CU_add_test(pSuite, "netstring decodeToArrayList test", test_netstring_decodetoArrayList)
+		|| NULL == CU_add_test(pSuite, "netstring encodeFromArrayList test", test_netstring_encodeFromArrayList)
+
+	)
+	{
+	  CU_cleanup_registry();
+	  return CU_get_error();
+	}
+
+	CU_set_output_filename(argv[1]);
+	CU_list_tests_to_file();
+	CU_automated_run_tests();
+	CU_cleanup_registry();
+	return CU_get_error();
+}
+

Added: incubator/celix/trunk/utils/public/include/netstring.h
URL: http://svn.apache.org/viewvc/incubator/celix/trunk/utils/public/include/netstring.h?rev=1556172&view=auto
==============================================================================
--- incubator/celix/trunk/utils/public/include/netstring.h (added)
+++ incubator/celix/trunk/utils/public/include/netstring.h Tue Jan  7 10:33:55 2014
@@ -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.
+ */
+/*
+ * netstring.h
+ *
+ *  \date       Sep 13, 2013
+ *  \author    	<a href="mailto:celix-dev@incubator.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef NETSTRING_H_
+#define NETSTRING_H_
+
+#include <apr_general.h>
+#include "array_list.h"
+#include "hash_map.h"
+#include "exports.h"
+#include "celix_errno.h"
+
+
+typedef celix_status_t (*customEncoderCallback) (apr_pool_t *pool, void* inPtr, char **outNetStr);
+typedef celix_status_t (*customDecoderCallback) (apr_pool_t *pool, char* inNetStr, void *outPtr);
+
+UTILS_EXPORT celix_status_t netstring_encode(apr_pool_t *pool, char* inStr, char **outNetStr);
+UTILS_EXPORT celix_status_t netstring_decode(apr_pool_t *pool, char* inNetStr, char **outStr);
+UTILS_EXPORT celix_status_t netstring_decodetoArray(apr_pool_t *pool, char* inNetStr, char **outStrArr[], int *outArrSize);
+UTILS_EXPORT celix_status_t netstring_encodeFromArray(apr_pool_t *pool, char *inStrArr[], int inArrLen, char** outNetStr);
+UTILS_EXPORT celix_status_t netstring_custDecodeFromArray(apr_pool_t *pool, char* inNetStr, customDecoderCallback inCallback, void **outStrArr[], int *outArrSize);
+UTILS_EXPORT celix_status_t netstring_custEncodeFromArray(apr_pool_t *pool, void *inStrArr[], customEncoderCallback inCallback, int inArrLen, char** outNetStr);
+UTILS_EXPORT celix_status_t netstring_decodeToHashMap(apr_pool_t *pool, char* inNetStr, hash_map_pt outHashMap);
+UTILS_EXPORT celix_status_t netstring_encodeFromHashMap(apr_pool_t *pool, hash_map_pt inHashMap, char** outNetStr);
+UTILS_EXPORT celix_status_t netstring_custDecodeToHashMap(apr_pool_t *pool, char* inNetStr, customDecoderCallback keyDecCallback, customDecoderCallback valueDecCallback, hash_map_pt outHashMap);
+UTILS_EXPORT celix_status_t netstring_custEncodeFromHashMap(apr_pool_t *pool, hash_map_pt inHashMap, customEncoderCallback keyEncCallback, customEncoderCallback valueEncCallback, char** outNetStr);
+UTILS_EXPORT celix_status_t netstring_encodeFromArrayList(apr_pool_t *pool, array_list_pt inList, char** outNetStr);
+UTILS_EXPORT celix_status_t netstring_decodeToArrayList(apr_pool_t *pool, char* inNetStr, array_list_pt outArrayList);
+UTILS_EXPORT celix_status_t netstring_custEncodeFromArrayList(apr_pool_t *pool, array_list_pt inList, customEncoderCallback elCallback, char** outNetStr);
+UTILS_EXPORT celix_status_t netstring_custDecodeToArrayList(apr_pool_t *pool, char* inNetStr, customDecoderCallback decCallback, array_list_pt outArrayList);
+
+
+
+#endif /* NETSTRING_H_ */