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, ®istration);
+ 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, ®istration);
+
+ 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_ */