Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 1256B200D49 for ; Fri, 24 Nov 2017 11:59:13 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 10F92160C11; Fri, 24 Nov 2017 10:59:13 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id B1EE3160BF2 for ; Fri, 24 Nov 2017 11:59:10 +0100 (CET) Received: (qmail 71517 invoked by uid 500); 24 Nov 2017 10:59:09 -0000 Mailing-List: contact commits-help@celix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@celix.apache.org Delivered-To: mailing list commits@celix.apache.org Received: (qmail 71508 invoked by uid 99); 24 Nov 2017 10:59:09 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 24 Nov 2017 10:59:09 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 9AFEADFDFB; Fri, 24 Nov 2017 10:59:09 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: pnoltes@apache.org To: commits@celix.apache.org Date: Fri, 24 Nov 2017 10:59:09 -0000 Message-Id: <5ab566a8835c440cb81e1275003d2e60@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [1/8] celix git commit: CELIX-417: Refactors CMake usage for the RSA bundles archived-at: Fri, 24 Nov 2017 10:59:13 -0000 Repository: celix Updated Branches: refs/heads/feature/CELIX-417-cmake-refactor 2a670f265 -> 486d4f0d5 http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c b/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c new file mode 100644 index 0000000..0b8dcf7 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c @@ -0,0 +1,402 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ + +#include +#include +#include +#include +#include "version.h" +#include "json_serializer.h" +#include "dyn_interface.h" +#include "import_registration.h" +#include "import_registration_dfi.h" + +struct import_registration { + bundle_context_pt context; + endpoint_description_pt endpoint; //TODO owner? -> free when destroyed + const char *classObject; //NOTE owned by endpoint + version_pt version; + + celix_thread_mutex_t mutex; //protects send & sendhandle + send_func_type send; + void *sendHandle; + + service_factory_pt factory; + service_registration_pt factoryReg; + + hash_map_pt proxies; //key -> bundle, value -> service_proxy + celix_thread_mutex_t proxiesMutex; //protects proxies +}; + +struct service_proxy { + dyn_interface_type *intf; + void *service; + size_t count; +}; + +static celix_status_t importRegistration_createProxy(import_registration_pt import, bundle_pt bundle, + struct service_proxy **proxy); +static void importRegistration_proxyFunc(void *userData, void *args[], void *returnVal); +static void importRegistration_destroyProxy(struct service_proxy *proxy); +static void importRegistration_clearProxies(import_registration_pt import); + +celix_status_t importRegistration_create(bundle_context_pt context, endpoint_description_pt endpoint, const char *classObject, const char* serviceVersion, + import_registration_pt *out) { + celix_status_t status = CELIX_SUCCESS; + import_registration_pt reg = calloc(1, sizeof(*reg)); + + if (reg != NULL) { + reg->factory = calloc(1, sizeof(*reg->factory)); + } + + if (reg != NULL && reg->factory != NULL) { + reg->context = context; + reg->endpoint = endpoint; + reg->classObject = classObject; + reg->proxies = hashMap_create(NULL, NULL, NULL, NULL); + + celixThreadMutex_create(®->mutex, NULL); + celixThreadMutex_create(®->proxiesMutex, NULL); + status = version_createVersionFromString((char*)serviceVersion,&(reg->version)); + + reg->factory->handle = reg; + reg->factory->getService = (void *)importRegistration_getService; + reg->factory->ungetService = (void *)importRegistration_ungetService; + } else { + status = CELIX_ENOMEM; + } + + if (status == CELIX_SUCCESS) { + //printf("IMPORT REGISTRATION IS %p\n", reg); + *out = reg; + } + else{ + importRegistration_destroy(reg); + } + + return status; +} + + +celix_status_t importRegistration_setSendFn(import_registration_pt reg, + send_func_type send, + void *handle) { + celixThreadMutex_lock(®->mutex); + reg->send = send; + reg->sendHandle = handle; + celixThreadMutex_unlock(®->mutex); + + return CELIX_SUCCESS; +} + +static void importRegistration_clearProxies(import_registration_pt import) { + if (import != NULL) { + pthread_mutex_lock(&import->proxiesMutex); + if (import->proxies != NULL) { + hash_map_iterator_pt iter = hashMapIterator_create(import->proxies); + while (hashMapIterator_hasNext(iter)) { + hash_map_entry_pt entry = hashMapIterator_nextEntry(iter); + struct service_proxy *proxy = hashMapEntry_getValue(entry); + importRegistration_destroyProxy(proxy); + } + hashMapIterator_destroy(iter); + } + pthread_mutex_unlock(&import->proxiesMutex); + } +} + +void importRegistration_destroy(import_registration_pt import) { + if (import != NULL) { + if (import->proxies != NULL) { + hashMap_destroy(import->proxies, false, false); + import->proxies = NULL; + } + + pthread_mutex_destroy(&import->mutex); + pthread_mutex_destroy(&import->proxiesMutex); + + if (import->factory != NULL) { + free(import->factory); + } + + if(import->version!=NULL){ + version_destroy(import->version); + } + free(import); + } +} + +celix_status_t importRegistration_start(import_registration_pt import) { + celix_status_t status = CELIX_SUCCESS; + if (import->factoryReg == NULL && import->factory != NULL) { + properties_pt props = NULL; + properties_copy(import->endpoint->properties, &props); + status = bundleContext_registerServiceFactory(import->context, (char *)import->classObject, import->factory, props, &import->factoryReg); + } else { + status = CELIX_ILLEGAL_STATE; + } + return status; +} + +celix_status_t importRegistration_stop(import_registration_pt import) { + celix_status_t status = CELIX_SUCCESS; + + if (import->factoryReg != NULL) { + serviceRegistration_unregister(import->factoryReg); + import->factoryReg = NULL; + } + + importRegistration_clearProxies(import); + + return status; +} + + +celix_status_t importRegistration_getService(import_registration_pt import, bundle_pt bundle, service_registration_pt registration, void **out) { + celix_status_t status = CELIX_SUCCESS; + + /* + module_pt module = NULL; + char *name = NULL; + bundle_getCurrentModule(bundle, &module); + module_getSymbolicName(module, &name); + printf("getting service for bundle '%s'\n", name); + */ + + + pthread_mutex_lock(&import->proxiesMutex); + struct service_proxy *proxy = hashMap_get(import->proxies, bundle); + if (proxy == NULL) { + status = importRegistration_createProxy(import, bundle, &proxy); + if (status == CELIX_SUCCESS) { + hashMap_put(import->proxies, bundle, proxy); + } + } + + if (status == CELIX_SUCCESS) { + proxy->count += 1; + *out = proxy->service; + } + pthread_mutex_unlock(&import->proxiesMutex); + + return status; +} + +static celix_status_t importRegistration_createProxy(import_registration_pt import, bundle_pt bundle, struct service_proxy **out) { + celix_status_t status; + dyn_interface_type* intf = NULL; + FILE *descriptor = NULL; + + status = dfi_findDescriptor(import->context, bundle, import->classObject, &descriptor); + + if (status != CELIX_SUCCESS || descriptor == NULL) { + //TODO use log helper logHelper_log(helper, OSGI_LOGSERVICE_ERROR, "Cannot find/open descriptor for '%s'", import->classObject); + fprintf(stderr, "RSA_DFI: Cannot find/open descriptor for '%s'", import->classObject); + return CELIX_BUNDLE_EXCEPTION; + } + + if (status == CELIX_SUCCESS) { + int rc = dynInterface_parse(descriptor, &intf); + fclose(descriptor); + if (rc != 0 || intf==NULL) { + return CELIX_BUNDLE_EXCEPTION; + } + } + + /* Check if the imported service version is compatible with the one in the consumer descriptor */ + version_pt consumerVersion = NULL; + bool isCompatible = false; + dynInterface_getVersion(intf,&consumerVersion); + version_isCompatible(consumerVersion,import->version,&isCompatible); + + if(!isCompatible){ + char* cVerString = NULL; + char* pVerString = NULL; + version_toString(consumerVersion,&cVerString); + version_toString(import->version,&pVerString); + printf("Service version mismatch: consumer has %s, provider has %s. NOT creating proxy.\n",cVerString,pVerString); + dynInterface_destroy(intf); + free(cVerString); + free(pVerString); + status = CELIX_SERVICE_EXCEPTION; + } + + struct service_proxy *proxy = NULL; + if (status == CELIX_SUCCESS) { + proxy = calloc(1, sizeof(*proxy)); + if (proxy == NULL) { + status = CELIX_ENOMEM; + } + } + + if (status == CELIX_SUCCESS) { + proxy->intf = intf; + size_t count = dynInterface_nrOfMethods(proxy->intf); + proxy->service = calloc(1 + count, sizeof(void *)); + if (proxy->service == NULL) { + status = CELIX_ENOMEM; + } + } + + if (status == CELIX_SUCCESS) { + void **serv = proxy->service; + serv[0] = import; + + struct methods_head *list = NULL; + dynInterface_methods(proxy->intf, &list); + struct method_entry *entry = NULL; + void (*fn)(void) = NULL; + int index = 0; + TAILQ_FOREACH(entry, list, entries) { + int rc = dynFunction_createClosure(entry->dynFunc, importRegistration_proxyFunc, entry, &fn); + serv[index + 1] = fn; + index += 1; + + if (rc != 0) { + status = CELIX_BUNDLE_EXCEPTION; + break; + } + } + } + + if (status == CELIX_SUCCESS) { + *out = proxy; + } else if (proxy != NULL) { + if (proxy->intf != NULL) { + dynInterface_destroy(proxy->intf); + proxy->intf = NULL; + } + free(proxy->service); + free(proxy); + } + + return status; +} + +static void importRegistration_proxyFunc(void *userData, void *args[], void *returnVal) { + int status = CELIX_SUCCESS; + struct method_entry *entry = userData; + import_registration_pt import = *((void **)args[0]); + + if (import == NULL || import->send == NULL) { + status = CELIX_ILLEGAL_ARGUMENT; + } + + + char *invokeRequest = NULL; + if (status == CELIX_SUCCESS) { + status = jsonRpc_prepareInvokeRequest(entry->dynFunc, entry->id, args, &invokeRequest); + //printf("Need to send following json '%s'\n", invokeRequest); + } + + + if (status == CELIX_SUCCESS) { + char *reply = NULL; + int rc = 0; + //printf("sending request\n"); + celixThreadMutex_lock(&import->mutex); + if (import->send != NULL) { + import->send(import->sendHandle, import->endpoint, invokeRequest, &reply, &rc); + } + celixThreadMutex_unlock(&import->mutex); + //printf("request sended. got reply '%s' with status %i\n", reply, rc); + + if (rc == 0) { + //fjprintf("Handling reply '%s'\n", reply); + status = jsonRpc_handleReply(entry->dynFunc, reply, args); + } + + *(int *) returnVal = rc; + + free(invokeRequest); //Allocated by json_dumps in jsonRpc_prepareInvokeRequest + free(reply); //Allocated by json_dumps in remoteServiceAdmin_send through curl call + } + + if (status != CELIX_SUCCESS) { + //TODO log error + } +} + +celix_status_t importRegistration_ungetService(import_registration_pt import, bundle_pt bundle, service_registration_pt registration, void **out) { + celix_status_t status = CELIX_SUCCESS; + + assert(import != NULL); + assert(import->proxies != NULL); + + pthread_mutex_lock(&import->proxiesMutex); + + struct service_proxy *proxy = hashMap_get(import->proxies, bundle); + if (proxy != NULL) { + if (*out == proxy->service) { + proxy->count -= 1; + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + + if (proxy->count == 0) { + hashMap_remove(import->proxies, bundle); + importRegistration_destroyProxy(proxy); + } + } + + pthread_mutex_unlock(&import->proxiesMutex); + + return status; +} + +static void importRegistration_destroyProxy(struct service_proxy *proxy) { + if (proxy != NULL) { + if (proxy->intf != NULL) { + dynInterface_destroy(proxy->intf); + } + if (proxy->service != NULL) { + free(proxy->service); + } + free(proxy); + } +} + + +celix_status_t importRegistration_close(import_registration_pt registration) { + celix_status_t status = CELIX_SUCCESS; + importRegistration_stop(registration); + return status; +} + +celix_status_t importRegistration_getException(import_registration_pt registration) { + celix_status_t status = CELIX_SUCCESS; + //TODO + return status; +} + +celix_status_t importRegistration_getImportReference(import_registration_pt registration, import_reference_pt *reference) { + celix_status_t status = CELIX_SUCCESS; + //TODO + return status; +} + +celix_status_t importReference_getImportedEndpoint(import_reference_pt reference) { + celix_status_t status = CELIX_SUCCESS; + return status; +} + +celix_status_t importReference_getImportedService(import_reference_pt reference) { + celix_status_t status = CELIX_SUCCESS; + return status; +} http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/src/import_registration_dfi.h ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/src/import_registration_dfi.h b/remote_services/remote_service_admin_dfi/src/import_registration_dfi.h new file mode 100644 index 0000000..aac4bc7 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/src/import_registration_dfi.h @@ -0,0 +1,44 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ + +#ifndef CELIX_IMPORT_REGISTRATION_DFI_H +#define CELIX_IMPORT_REGISTRATION_DFI_H + +#include "import_registration.h" +#include "dfi_utils.h" + +#include + +typedef void (*send_func_type)(void *handle, endpoint_description_pt endpointDescription, char *request, char **reply, int* replyStatus); + +celix_status_t importRegistration_create(bundle_context_pt context, endpoint_description_pt description, const char *classObject, const char* serviceVersion, + import_registration_pt *import); +celix_status_t importRegistration_close(import_registration_pt import); +void importRegistration_destroy(import_registration_pt import); + +celix_status_t importRegistration_setSendFn(import_registration_pt reg, + send_func_type, + void *handle); +celix_status_t importRegistration_start(import_registration_pt import); +celix_status_t importRegistration_stop(import_registration_pt import); + +celix_status_t importRegistration_getService(import_registration_pt import, bundle_pt bundle, service_registration_pt registration, void **service); +celix_status_t importRegistration_ungetService(import_registration_pt import, bundle_pt bundle, service_registration_pt registration, void **service); + +#endif //CELIX_IMPORT_REGISTRATION_DFI_H http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/src/remote_service_admin_activator.c ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/src/remote_service_admin_activator.c b/remote_services/remote_service_admin_dfi/src/remote_service_admin_activator.c new file mode 100644 index 0000000..d4cc765 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/src/remote_service_admin_activator.c @@ -0,0 +1,124 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * remote_service_admin_activator.c + * + * \date Sep 30, 2011 + * \author Apache Celix Project Team + * \copyright Apache License, Version 2.0 + */ +#include +#include + +#include "remote_service_admin_dfi.h" + +#include "bundle_activator.h" +#include "service_registration.h" + +#include "export_registration_dfi.h" +#include "import_registration_dfi.h" + +struct activator { + remote_service_admin_pt admin; + remote_service_admin_service_pt adminService; + service_registration_pt registration; +}; + +celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) { + celix_status_t status = CELIX_SUCCESS; + struct activator *activator; + + activator = calloc(1, sizeof(*activator)); + if (!activator) { + status = CELIX_ENOMEM; + } else { + activator->admin = NULL; + activator->registration = NULL; + + *userData = activator; + } + + return status; +} + +celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) { + celix_status_t status = CELIX_SUCCESS; + struct activator *activator = userData; + remote_service_admin_service_pt remoteServiceAdmin = NULL; + + status = remoteServiceAdmin_create(context, &activator->admin); + if (status == CELIX_SUCCESS) { + remoteServiceAdmin = calloc(1, sizeof(*remoteServiceAdmin)); + if (!remoteServiceAdmin) { + status = CELIX_ENOMEM; + } else { + remoteServiceAdmin->admin = activator->admin; + remoteServiceAdmin->exportService = remoteServiceAdmin_exportService; + + remoteServiceAdmin->getExportedServices = remoteServiceAdmin_getExportedServices; + remoteServiceAdmin->getImportedEndpoints = remoteServiceAdmin_getImportedEndpoints; + remoteServiceAdmin->importService = remoteServiceAdmin_importService; + + remoteServiceAdmin->exportReference_getExportedEndpoint = exportReference_getExportedEndpoint; + remoteServiceAdmin->exportReference_getExportedService = exportReference_getExportedService; + + remoteServiceAdmin->exportRegistration_close = remoteServiceAdmin_removeExportedService; + remoteServiceAdmin->exportRegistration_getException = exportRegistration_getException; + remoteServiceAdmin->exportRegistration_getExportReference = exportRegistration_getExportReference; + + remoteServiceAdmin->importReference_getImportedEndpoint = importReference_getImportedEndpoint; + remoteServiceAdmin->importReference_getImportedService = importReference_getImportedService; + + remoteServiceAdmin->importRegistration_close = remoteServiceAdmin_removeImportedService; + remoteServiceAdmin->importRegistration_getException = importRegistration_getException; + remoteServiceAdmin->importRegistration_getImportReference = importRegistration_getImportReference; + + status = bundleContext_registerService(context, OSGI_RSA_REMOTE_SERVICE_ADMIN, remoteServiceAdmin, NULL, &activator->registration); + activator->adminService = remoteServiceAdmin; + } + } + + return status; +} + +celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) { + celix_status_t status = CELIX_SUCCESS; + struct activator *activator = userData; + + serviceRegistration_unregister(activator->registration); + activator->registration = NULL; + + remoteServiceAdmin_stop(activator->admin); + remoteServiceAdmin_destroy(&activator->admin); + + free(activator->adminService); + + return status; +} + +celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) { + celix_status_t status = CELIX_SUCCESS; + struct activator *activator = userData; + + free(activator); + + return status; +} + + http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.c ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.c b/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.c new file mode 100644 index 0000000..6effc94 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.c @@ -0,0 +1,771 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * remote_service_admin_impl.c + * + * \date May 21, 2015 + * \author Apache Celix Project Team + * \copyright Apache License, Version 2.0 + */ +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include "json_serializer.h" +#include "remote_service_admin.h" + +#include "import_registration_dfi.h" +#include "export_registration_dfi.h" +#include "remote_service_admin_dfi.h" +#include "json_rpc.h" + +#include "remote_constants.h" +#include "constants.h" +#include "civetweb.h" + +// defines how often the webserver is restarted (with an increased port number) +#define MAX_NUMBER_OF_RESTARTS 5 + + +#define RSA_LOG_ERROR(admin, msg, ...) \ + logHelper_log((admin)->loghelper, OSGI_LOGSERVICE_ERROR, (msg), ##__VA_ARGS__) + +#define RSA_LOG_WARNING(admin, msg, ...) \ + logHelper_log((admin)->loghelper, OSGI_LOGSERVICE_ERROR, (msg), ##__VA_ARGS__) + +#define RSA_LOG_DEBUG(admin, msg, ...) \ + logHelper_log((admin)->loghelper, OSGI_LOGSERVICE_ERROR, (msg), ##__VA_ARGS__) + +struct remote_service_admin { + bundle_context_pt context; + log_helper_pt loghelper; + + celix_thread_mutex_t exportedServicesLock; + hash_map_pt exportedServices; + + celix_thread_mutex_t importedServicesLock; + array_list_pt importedServices; + + char *port; + char *ip; + + struct mg_context *ctx; +}; + +struct post { + const char *readptr; + int size; +}; + +struct get { + char *writeptr; + int size; +}; + +#define OSGI_RSA_REMOTE_PROXY_FACTORY "remote_proxy_factory" +#define OSGI_RSA_REMOTE_PROXY_TIMEOUT "remote_proxy_timeout" + +static const char *data_response_headers = + "HTTP/1.1 200 OK\r\n" + "Cache: no-cache\r\n" + "Content-Type: application/json\r\n" + "\r\n"; + +static const char *no_content_response_headers = + "HTTP/1.1 204 OK\r\n"; + +// TODO do we need to specify a non-Amdatu specific configuration type?! +static const char * const CONFIGURATION_TYPE = "org.amdatu.remote.admin.http"; +static const char * const ENDPOINT_URL = "org.amdatu.remote.admin.http.url"; + +static const char *DEFAULT_PORT = "8888"; +static const char *DEFAULT_IP = "127.0.0.1"; + +static const unsigned int DEFAULT_TIMEOUT = 0; + +static int remoteServiceAdmin_callback(struct mg_connection *conn); +static celix_status_t remoteServiceAdmin_createEndpointDescription(remote_service_admin_pt admin, service_reference_pt reference, properties_pt props, char *interface, endpoint_description_pt *description); +static celix_status_t remoteServiceAdmin_send(void *handle, endpoint_description_pt endpointDescription, char *request, char **reply, int* replyStatus); +static celix_status_t remoteServiceAdmin_getIpAdress(char* interface, char** ip); +static size_t remoteServiceAdmin_readCallback(void *ptr, size_t size, size_t nmemb, void *userp); +static size_t remoteServiceAdmin_write(void *contents, size_t size, size_t nmemb, void *userp); +static void remoteServiceAdmin_log(remote_service_admin_pt admin, int level, const char *file, int line, const char *msg, ...); + +celix_status_t remoteServiceAdmin_create(bundle_context_pt context, remote_service_admin_pt *admin) { + celix_status_t status = CELIX_SUCCESS; + + *admin = calloc(1, sizeof(**admin)); + + if (!*admin) { + status = CELIX_ENOMEM; + } else { + unsigned int port_counter = 0; + const char *port = NULL; + const char *ip = NULL; + char *detectedIp = NULL; + (*admin)->context = context; + (*admin)->exportedServices = hashMap_create(NULL, NULL, NULL, NULL); + arrayList_create(&(*admin)->importedServices); + + celixThreadMutex_create(&(*admin)->exportedServicesLock, NULL); + celixThreadMutex_create(&(*admin)->importedServicesLock, NULL); + + if (logHelper_create(context, &(*admin)->loghelper) == CELIX_SUCCESS) { + logHelper_start((*admin)->loghelper); + dynCommon_logSetup((void *)remoteServiceAdmin_log, *admin, 1); + dynType_logSetup((void *)remoteServiceAdmin_log, *admin, 1); + dynFunction_logSetup((void *)remoteServiceAdmin_log, *admin, 1); + dynInterface_logSetup((void *)remoteServiceAdmin_log, *admin, 1); + jsonSerializer_logSetup((void *)remoteServiceAdmin_log, *admin, 1); + jsonRpc_logSetup((void *)remoteServiceAdmin_log, *admin, 1); + } + + bundleContext_getProperty(context, "RSA_PORT", &port); + if (port == NULL) { + port = (char *)DEFAULT_PORT; + } + + bundleContext_getProperty(context, "RSA_IP", &ip); + if (ip == NULL) { + const char *interface = NULL; + + bundleContext_getProperty(context, "RSA_INTERFACE", &interface); + if ((interface != NULL) && (remoteServiceAdmin_getIpAdress((char*)interface, &detectedIp) != CELIX_SUCCESS)) { + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "RSA: Could not retrieve IP adress for interface %s", interface); + } + + if (ip == NULL) { + remoteServiceAdmin_getIpAdress(NULL, &detectedIp); + } + + ip = detectedIp; + } + + if (ip != NULL) { + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Using %s for service annunciation", ip); + (*admin)->ip = strdup(ip); + } + else { + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "RSA: No IP address for service annunciation set. Using %s", DEFAULT_IP); + (*admin)->ip = strdup((char*) DEFAULT_IP); + } + + if (detectedIp != NULL) { + free(detectedIp); + } + + // Prepare callbacks structure. We have only one callback, the rest are NULL. + struct mg_callbacks callbacks; + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.begin_request = remoteServiceAdmin_callback; + + char newPort[10]; + + do { + + const char *options[] = { "listening_ports", port, "num_threads", "5", NULL}; + + (*admin)->ctx = mg_start(&callbacks, (*admin), options); + + if ((*admin)->ctx != NULL) { + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Start webserver: %s", port); + (*admin)->port = strdup(port); + + } + else { + errno = 0; + char* endptr = (char*)port; + int currentPort = strtol(port, &endptr, 10); + + if (*endptr || errno != 0) { + currentPort = strtol(DEFAULT_PORT, NULL, 10); + } + + port_counter++; + snprintf(&newPort[0], 6, "%d", (currentPort+1)); + + logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_ERROR, "Error while starting rsa server on port %s - retrying on port %s...", port, newPort); + port = newPort; + } + } while(((*admin)->ctx == NULL) && (port_counter < MAX_NUMBER_OF_RESTARTS)); + + } + + return status; +} + + +celix_status_t remoteServiceAdmin_destroy(remote_service_admin_pt *admin) +{ + celix_status_t status = CELIX_SUCCESS; + + free((*admin)->ip); + free((*admin)->port); + free(*admin); + + //TODO destroy exports/imports + + *admin = NULL; + + return status; +} + + +celix_status_t remoteServiceAdmin_stop(remote_service_admin_pt admin) { + celix_status_t status = CELIX_SUCCESS; + + celixThreadMutex_lock(&admin->exportedServicesLock); + + hash_map_iterator_pt iter = hashMapIterator_create(admin->exportedServices); + while (hashMapIterator_hasNext(iter)) { + array_list_pt exports = hashMapIterator_nextValue(iter); + int i; + for (i = 0; i < arrayList_size(exports); i++) { + export_registration_pt export = arrayList_get(exports, i); + if (export != NULL) { + exportRegistration_stop(export); + exportRegistration_destroy(export); + } + } + arrayList_destroy(exports); + } + hashMapIterator_destroy(iter); + celixThreadMutex_unlock(&admin->exportedServicesLock); + + celixThreadMutex_lock(&admin->importedServicesLock); + int i; + int size = arrayList_size(admin->importedServices); + for (i = 0; i < size ; i += 1) { + import_registration_pt import = arrayList_get(admin->importedServices, i); + if (import != NULL) { + importRegistration_stop(import); + importRegistration_destroy(import); + } + } + celixThreadMutex_unlock(&admin->importedServicesLock); + + if (admin->ctx != NULL) { + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Stopping webserver..."); + mg_stop(admin->ctx); + admin->ctx = NULL; + } + + hashMap_destroy(admin->exportedServices, false, false); + arrayList_destroy(admin->importedServices); + + logHelper_stop(admin->loghelper); + logHelper_destroy(&admin->loghelper); + + return status; +} + +/** + * Request: http://host:port/services/{service}/{request} + */ +//void *remoteServiceAdmin_callback(enum mg_event event, struct mg_connection *conn, const struct mg_request_info *request_info) { + +celix_status_t importRegistration_getFactory(import_registration_pt import, service_factory_pt *factory); + +static int remoteServiceAdmin_callback(struct mg_connection *conn) { + int result = 1; // zero means: let civetweb handle it further, any non-zero value means it is handled by us... + + const struct mg_request_info *request_info = mg_get_request_info(conn); + if (request_info->uri != NULL) { + remote_service_admin_pt rsa = request_info->user_data; + + + if (strncmp(request_info->uri, "/service/", 9) == 0 && strcmp("POST", request_info->request_method) == 0) { + + // uri = /services/myservice/call + const char *uri = request_info->uri; + // rest = myservice/call + + const char *rest = uri+9; + char *interfaceStart = strchr(rest, '/'); + int pos = interfaceStart - rest; + char service[pos+1]; + strncpy(service, rest, pos); + service[pos] = '\0'; + unsigned long serviceId = strtoul(service,NULL,10); + + celixThreadMutex_lock(&rsa->exportedServicesLock); + + //find endpoint + export_registration_pt export = NULL; + hash_map_iterator_pt iter = hashMapIterator_create(rsa->exportedServices); + while (hashMapIterator_hasNext(iter)) { + hash_map_entry_pt entry = hashMapIterator_nextEntry(iter); + array_list_pt exports = hashMapEntry_getValue(entry); + int expIt = 0; + for (expIt = 0; expIt < arrayList_size(exports); expIt++) { + export_registration_pt check = arrayList_get(exports, expIt); + export_reference_pt ref = NULL; + exportRegistration_getExportReference(check, &ref); + endpoint_description_pt checkEndpoint = NULL; + exportReference_getExportedEndpoint(ref, &checkEndpoint); + if (serviceId == checkEndpoint->serviceId) { + export = check; + free(ref); + break; + } + free(ref); + } + } + hashMapIterator_destroy(iter); + + if (export != NULL) { + + uint64_t datalength = request_info->content_length; + char* data = malloc(datalength + 1); + mg_read(conn, data, datalength); + data[datalength] = '\0'; + + char *response = NULL; + int responceLength = 0; + int rc = exportRegistration_call(export, data, -1, &response, &responceLength); + if (rc != CELIX_SUCCESS) { + RSA_LOG_ERROR(rsa, "Error trying to invoke remove service, got error %i\n", rc); + } + + if (rc == CELIX_SUCCESS && response != NULL) { + mg_write(conn, data_response_headers, strlen(data_response_headers)); + mg_write(conn, response, strlen(response)); + free(response); + } else { + mg_write(conn, no_content_response_headers, strlen(no_content_response_headers)); + } + result = 1; + + free(data); + } else { + result = 0; + RSA_LOG_WARNING(rsa, "NO export registration found for service id %lu", serviceId); + } + + celixThreadMutex_unlock(&rsa->exportedServicesLock); + + } + } + + return result; +} + +celix_status_t remoteServiceAdmin_exportService(remote_service_admin_pt admin, char *serviceId, properties_pt properties, array_list_pt *registrations) { + celix_status_t status; + + arrayList_create(registrations); + array_list_pt references = NULL; + service_reference_pt reference = NULL; + char filter [256]; + + snprintf(filter, 256, "(%s=%s)", (char *)OSGI_FRAMEWORK_SERVICE_ID, serviceId); + + status = bundleContext_getServiceReferences(admin->context, NULL, filter, &references); + + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_DEBUG, "RSA: exportService called for serviceId %s", serviceId); + + int i; + int size = arrayList_size(references); + for (i = 0; i < size; i += 1) { + if (i == 0) { + reference = arrayList_get(references, i); + } else { + bundleContext_ungetServiceReference(admin->context, arrayList_get(references, i)); + } + } + arrayList_destroy(references); + + if (reference == NULL) { + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "ERROR: expected a reference for service id %s.", serviceId); + status = CELIX_ILLEGAL_STATE; + } + + const char *exports = NULL; + const char *provided = NULL; + if (status == CELIX_SUCCESS) { + serviceReference_getProperty(reference, (char *) OSGI_RSA_SERVICE_EXPORTED_INTERFACES, &exports); + serviceReference_getProperty(reference, (char *) OSGI_FRAMEWORK_OBJECTCLASS, &provided); + + if (exports == NULL || provided == NULL || strcmp(exports, provided) != 0) { + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_WARNING, "RSA: No Services to export."); + status = CELIX_ILLEGAL_STATE; + } else { + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Export service (%s)", provided); + } + } + + if (status == CELIX_SUCCESS) { + const char *interface = provided; + endpoint_description_pt endpoint = NULL; + export_registration_pt registration = NULL; + + remoteServiceAdmin_createEndpointDescription(admin, reference, properties, (char*)interface, &endpoint); + //TODO precheck if descriptor exists + status = exportRegistration_create(admin->loghelper, reference, endpoint, admin->context, ®istration); + if (status == CELIX_SUCCESS) { + status = exportRegistration_start(registration); + if (status == CELIX_SUCCESS) { + arrayList_add(*registrations, registration); + } + } + } + + + if (status == CELIX_SUCCESS) { + celixThreadMutex_lock(&admin->exportedServicesLock); + hashMap_put(admin->exportedServices, reference, *registrations); + celixThreadMutex_unlock(&admin->exportedServicesLock); + } + else{ + arrayList_destroy(*registrations); + *registrations = NULL; + } + + return status; +} + +celix_status_t remoteServiceAdmin_removeExportedService(remote_service_admin_pt admin, export_registration_pt registration) { + celix_status_t status; + + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA_DFI: Removing exported service"); + + export_reference_pt ref = NULL; + status = exportRegistration_getExportReference(registration, &ref); + + if (status == CELIX_SUCCESS && ref != NULL) { + service_reference_pt servRef; + celixThreadMutex_lock(&admin->exportedServicesLock); + exportReference_getExportedService(ref, &servRef); + + array_list_pt exports = (array_list_pt)hashMap_remove(admin->exportedServices, servRef); + if(exports!=NULL){ + arrayList_destroy(exports); + } + + exportRegistration_close(registration); + exportRegistration_destroy(registration); + + celixThreadMutex_unlock(&admin->exportedServicesLock); + + free(ref); + + } else { + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_ERROR, "Cannot find reference for registration"); + } + + return status; +} + +static celix_status_t remoteServiceAdmin_createEndpointDescription(remote_service_admin_pt admin, service_reference_pt reference, properties_pt props, char *interface, endpoint_description_pt *endpoint) { + + celix_status_t status = CELIX_SUCCESS; + properties_pt endpointProperties = properties_create(); + + + unsigned int size = 0; + char **keys; + + serviceReference_getPropertyKeys(reference, &keys, &size); + for (int i = 0; i < size; i++) { + char *key = keys[i]; + const char *value = NULL; + + if (serviceReference_getProperty(reference, key, &value) == CELIX_SUCCESS + && strcmp(key, (char*) OSGI_RSA_SERVICE_EXPORTED_INTERFACES) != 0 + && strcmp(key, (char*) OSGI_FRAMEWORK_OBJECTCLASS) != 0) { + properties_set(endpointProperties, key, value); + } + } + + hash_map_entry_pt entry = hashMap_getEntry(endpointProperties, (void *) OSGI_FRAMEWORK_SERVICE_ID); + + char* key = hashMapEntry_getKey(entry); + char *serviceId = (char *) hashMap_remove(endpointProperties, (void *) OSGI_FRAMEWORK_SERVICE_ID); + const char *uuid = NULL; + + char buf[512]; + snprintf(buf, 512, "/service/%s/%s", serviceId, interface); + + char url[1024]; + snprintf(url, 1024, "http://%s:%s%s", admin->ip, admin->port, buf); + + uuid_t endpoint_uid; + uuid_generate(endpoint_uid); + char endpoint_uuid[37]; + uuid_unparse_lower(endpoint_uid, endpoint_uuid); + + bundleContext_getProperty(admin->context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &uuid); + properties_set(endpointProperties, (char*) OSGI_RSA_ENDPOINT_FRAMEWORK_UUID, uuid); + properties_set(endpointProperties, (char*) OSGI_FRAMEWORK_OBJECTCLASS, interface); + properties_set(endpointProperties, (char*) OSGI_RSA_ENDPOINT_SERVICE_ID, serviceId); + properties_set(endpointProperties, (char*) OSGI_RSA_ENDPOINT_ID, endpoint_uuid); + properties_set(endpointProperties, (char*) OSGI_RSA_SERVICE_IMPORTED, "true"); + properties_set(endpointProperties, (char*) OSGI_RSA_SERVICE_IMPORTED_CONFIGS, (char*) CONFIGURATION_TYPE); + properties_set(endpointProperties, (char*) ENDPOINT_URL, url); + + if (props != NULL) { + hash_map_iterator_pt propIter = hashMapIterator_create(props); + while (hashMapIterator_hasNext(propIter)) { + hash_map_entry_pt entry = hashMapIterator_nextEntry(propIter); + properties_set(endpointProperties, (char*)hashMapEntry_getKey(entry), (char*)hashMapEntry_getValue(entry)); + } + hashMapIterator_destroy(propIter); + } + + *endpoint = calloc(1, sizeof(**endpoint)); + if (!*endpoint) { + status = CELIX_ENOMEM; + } else { + (*endpoint)->id = (char*)properties_get(endpointProperties, (char*) OSGI_RSA_ENDPOINT_ID); + const char *serviceId = NULL; + serviceReference_getProperty(reference, (char*) OSGI_FRAMEWORK_SERVICE_ID, &serviceId); + (*endpoint)->serviceId = strtoull(serviceId, NULL, 0); + (*endpoint)->frameworkUUID = (char*) properties_get(endpointProperties, (char*) OSGI_RSA_ENDPOINT_FRAMEWORK_UUID); + (*endpoint)->service = strndup(interface, 1024*10); + (*endpoint)->properties = endpointProperties; + } + + free(key); + free(serviceId); + free(keys); + + return status; +} + +static celix_status_t remoteServiceAdmin_getIpAdress(char* interface, char** ip) { + celix_status_t status = CELIX_BUNDLE_EXCEPTION; + + struct ifaddrs *ifaddr, *ifa; + char host[NI_MAXHOST]; + + if (getifaddrs(&ifaddr) != -1) + { + for (ifa = ifaddr; ifa != NULL && status != CELIX_SUCCESS; ifa = ifa->ifa_next) + { + if (ifa->ifa_addr == NULL) + continue; + + if ((getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0) && (ifa->ifa_addr->sa_family == AF_INET)) { + if (interface == NULL) { + *ip = strdup(host); + status = CELIX_SUCCESS; + } + else if (strcmp(ifa->ifa_name, interface) == 0) { + *ip = strdup(host); + status = CELIX_SUCCESS; + } + } + } + + freeifaddrs(ifaddr); + } + + return status; +} + + +celix_status_t remoteServiceAdmin_destroyEndpointDescription(endpoint_description_pt *description) +{ + celix_status_t status = CELIX_SUCCESS; + + properties_destroy((*description)->properties); + free((*description)->service); + free(*description); + + return status; +} + + +celix_status_t remoteServiceAdmin_getExportedServices(remote_service_admin_pt admin, array_list_pt *services) { + celix_status_t status = CELIX_SUCCESS; + return status; +} + +celix_status_t remoteServiceAdmin_getImportedEndpoints(remote_service_admin_pt admin, array_list_pt *services) { + celix_status_t status = CELIX_SUCCESS; + return status; +} + +celix_status_t remoteServiceAdmin_importService(remote_service_admin_pt admin, endpoint_description_pt endpointDescription, import_registration_pt *out) { + celix_status_t status = CELIX_SUCCESS; + import_registration_pt import = NULL; + + const char *objectClass = properties_get(endpointDescription->properties, "objectClass"); + const char *serviceVersion = properties_get(endpointDescription->properties, (char*) CELIX_FRAMEWORK_SERVICE_VERSION); + + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA: Import service %s", endpointDescription->service); + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "Registering service factory (proxy) for service '%s'\n", objectClass); + + if (objectClass != NULL) { + status = importRegistration_create(admin->context, endpointDescription, objectClass, serviceVersion, &import); + } + if (status == CELIX_SUCCESS && import != NULL) { + importRegistration_setSendFn(import, (send_func_type) remoteServiceAdmin_send, admin); + } + + if (status == CELIX_SUCCESS && import != NULL) { + status = importRegistration_start(import); + } + + celixThreadMutex_lock(&admin->importedServicesLock); + arrayList_add(admin->importedServices, import); + celixThreadMutex_unlock(&admin->importedServicesLock); + + if (status == CELIX_SUCCESS) { + *out = import; + } + + return status; +} + + +celix_status_t remoteServiceAdmin_removeImportedService(remote_service_admin_pt admin, import_registration_pt registration) { + celix_status_t status = CELIX_SUCCESS; + logHelper_log(admin->loghelper, OSGI_LOGSERVICE_INFO, "RSA_DFI: Removing imported service"); + + celixThreadMutex_lock(&admin->importedServicesLock); + int i; + int size = arrayList_size(admin->importedServices); + import_registration_pt current = NULL; + for (i = 0; i < size; i += 1) { + current = arrayList_get(admin->importedServices, i); + if (current == registration) { + arrayList_remove(admin->importedServices, i); + importRegistration_close(current); + importRegistration_destroy(current); + break; + } + } + celixThreadMutex_unlock(&admin->importedServicesLock); + + return status; +} + + +static celix_status_t remoteServiceAdmin_send(void *handle, endpoint_description_pt endpointDescription, char *request, char **reply, int* replyStatus) { + remote_service_admin_pt rsa = handle; + struct post post; + post.readptr = request; + post.size = strlen(request); + + struct get get; + get.size = 0; + get.writeptr = malloc(1); + + char *serviceUrl = (char*)properties_get(endpointDescription->properties, (char*) ENDPOINT_URL); + char url[256]; + snprintf(url, 256, "%s", serviceUrl); + + // assume the default timeout + int timeout = DEFAULT_TIMEOUT; + + const char *timeoutStr = NULL; + // Check if the endpoint has a timeout, if so, use it. + timeoutStr = (char*) properties_get(endpointDescription->properties, (char*) OSGI_RSA_REMOTE_PROXY_TIMEOUT); + if (timeoutStr == NULL) { + // If not, get the global variable and use that one. + bundleContext_getProperty(rsa->context, (char*) OSGI_RSA_REMOTE_PROXY_TIMEOUT, &timeoutStr); + } + + // Update timeout if a property is used to set it. + if (timeoutStr != NULL) { + timeout = atoi(timeoutStr); + } + + celix_status_t status = CELIX_SUCCESS; + CURL *curl; + CURLcode res; + + curl = curl_easy_init(); + if(!curl) { + status = CELIX_ILLEGAL_STATE; + } else { + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_POST, 1L); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, remoteServiceAdmin_readCallback); + curl_easy_setopt(curl, CURLOPT_READDATA, &post); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, remoteServiceAdmin_write); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&get); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (curl_off_t)post.size); + logHelper_log(rsa->loghelper, OSGI_LOGSERVICE_DEBUG, "RSA: Performing curl post\n"); + res = curl_easy_perform(curl); + + *reply = get.writeptr; + *replyStatus = res; + + curl_easy_cleanup(curl); + } + + return status; +} + +static size_t remoteServiceAdmin_readCallback(void *ptr, size_t size, size_t nmemb, void *userp) { + struct post *post = userp; + + if (post->size) { + *(char *) ptr = post->readptr[0]; + post->readptr++; + post->size--; + return 1; + } + + return 0; +} + +static size_t remoteServiceAdmin_write(void *contents, size_t size, size_t nmemb, void *userp) { + size_t realsize = size * nmemb; + struct get *mem = (struct get *)userp; + + mem->writeptr = realloc(mem->writeptr, mem->size + realsize + 1); + if (mem->writeptr == NULL) { + /* out of memory! */ + printf("not enough memory (realloc returned NULL)"); + exit(EXIT_FAILURE); + } + + memcpy(&(mem->writeptr[mem->size]), contents, realsize); + mem->size += realsize; + mem->writeptr[mem->size] = 0; + + return realsize; +} + + +static void remoteServiceAdmin_log(remote_service_admin_pt admin, int level, const char *file, int line, const char *msg, ...) { + va_list ap; + va_start(ap, msg); + int levels[5] = {0, OSGI_LOGSERVICE_ERROR, OSGI_LOGSERVICE_WARNING, OSGI_LOGSERVICE_INFO, OSGI_LOGSERVICE_DEBUG}; + + char buf1[256]; + snprintf(buf1, 256, "FILE:%s, LINE:%i, MSG:", file, line); + + char buf2[256]; + vsnprintf(buf2, 256, msg, ap); + logHelper_log(admin->loghelper, levels[level], "%s%s", buf1, buf2); + va_end(ap); +} http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.h ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.h b/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.h new file mode 100644 index 0000000..8b282f1 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.h @@ -0,0 +1,57 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * remote_service_admin_http_impl.h + * + * \date Sep 30, 2011 + * \author Apache Celix Project Team + * \copyright Apache License, Version 2.0 + */ + +#ifndef REMOTE_SERVICE_ADMIN_HTTP_IMPL_H_ +#define REMOTE_SERVICE_ADMIN_HTTP_IMPL_H_ + + +#include "bundle_context.h" +#include "endpoint_description.h" + +//typedef struct remote_service_admin *remote_service_admin_pt; + +celix_status_t remoteServiceAdmin_create(bundle_context_pt context, remote_service_admin_pt *admin); +celix_status_t remoteServiceAdmin_destroy(remote_service_admin_pt *admin); + +celix_status_t remoteServiceAdmin_stop(remote_service_admin_pt admin); + +celix_status_t remoteServiceAdmin_exportService(remote_service_admin_pt admin, char *serviceId, properties_pt properties, array_list_pt *registrations); +celix_status_t remoteServiceAdmin_removeExportedService(remote_service_admin_pt admin, export_registration_pt registration); +celix_status_t remoteServiceAdmin_getExportedServices(remote_service_admin_pt admin, array_list_pt *services); +celix_status_t remoteServiceAdmin_getImportedEndpoints(remote_service_admin_pt admin, array_list_pt *services); +celix_status_t remoteServiceAdmin_importService(remote_service_admin_pt admin, endpoint_description_pt endpoint, import_registration_pt *registration); +celix_status_t remoteServiceAdmin_removeImportedService(remote_service_admin_pt admin, import_registration_pt registration); + + +celix_status_t exportReference_getExportedEndpoint(export_reference_pt reference, endpoint_description_pt *endpoint); +celix_status_t exportReference_getExportedService(export_reference_pt reference, service_reference_pt *service); + +celix_status_t importReference_getImportedEndpoint(import_reference_pt reference); +celix_status_t importReference_getImportedService(import_reference_pt reference); + +celix_status_t remoteServiceAdmin_destroyEndpointDescription(endpoint_description_pt *description); + +#endif /* REMOTE_SERVICE_ADMIN_HTTP_IMPL_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/test/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/test/CMakeLists.txt b/remote_services/remote_service_admin_dfi/test/CMakeLists.txt new file mode 100644 index 0000000..a78a6d0 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/test/CMakeLists.txt @@ -0,0 +1,61 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +find_package(CppUTest REQUIRED) +include_directories(${CPPUTEST_INCLUDE_DIR}) + +add_bundle(rsa_dfi_tst_bundle + VERSION 0.0.1 + SOURCES + src/tst_activator.c +) +get_target_property(DESCR calculator_api INTERFACE_CALCULATOR_DESCRIPTOR) +bundle_files(rsa_dfi_tst_bundle ${DESCR} DESTINATION .) +target_link_libraries(rsa_dfi_tst_bundle PRIVATE ${CPPUTEST_LIBRARY} calculator_api) +target_include_directories(rsa_dfi_tst_bundle PRIVATE src) + +add_executable(test_rsa_dfi + src/run_tests.cpp + src/rsa_tests.cpp + src/rsa_client_server_tests.cpp +) +target_include_directories(test_rsa_dfi PRIVATE src) +target_link_libraries(test_rsa_dfi PRIVATE ${CURL_LIBRARIES} ${CPPUTEST_LIBRARY} + Celix::framework + Celix::remote_service_admin_api + Celix::remote_service_admin_common + calculator_api) + +get_property(rsa_bundle_file TARGET remote_service_admin_dfi PROPERTY BUNDLE_FILE) +get_property(calc_bundle_file TARGET calculator PROPERTY BUNDLE_FILE) +get_property(calculator_shell_bundle_file TARGET calculator_shell PROPERTY BUNDLE_FILE) +get_property(discovery_configured_bundle_file TARGET discovery_configured PROPERTY BUNDLE_FILE) +get_property(topology_manager_bundle_file TARGET topology_manager PROPERTY BUNDLE_FILE) +get_property(tst_bundle_file TARGET rsa_dfi_tst_bundle PROPERTY BUNDLE_FILE) + +configure_file(config.properties.in config.properties) +configure_file(client.properties.in client.properties) +configure_file(server.properties.in server.properties) + +add_dependencies(test_rsa_dfi + remote_service_admin_dfi_bundle #note depend on the target creating the bundle zip not the lib target + calculator_bundle +) + +add_test(NAME run_test_rsa_dfi COMMAND test_rsa_dfi) +SETUP_TARGET_FOR_COVERAGE(test_rsa_dfi_cov test_rsa_dfi ${CMAKE_BINARY_DIR}/coverage/test_rsa_dfi/test_rsa_dfi) + http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/test/client.properties.in ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/test/client.properties.in b/remote_services/remote_service_admin_dfi/test/client.properties.in new file mode 100644 index 0000000..a9a06fb --- /dev/null +++ b/remote_services/remote_service_admin_dfi/test/client.properties.in @@ -0,0 +1,8 @@ +cosgi.auto.start.1=@rsa_bundle_file@ @calculator_shell_bundle_file@ @discovery_configured_bundle_file@ @topology_manager_bundle_file@ @tst_bundle_file@ +LOGHELPER_ENABLE_STDOUT_FALLBACK=true +RSA_PORT=50881 +DISCOVERY_CFG_SERVER_PORT=50991 +DISCOVERY_CFG_POLL_ENDPOINTS=http://127.0.0.1:50992/org.apache.celix.discovery.configured +org.osgi.framework.storage.clean=onFirstInit +org.osgi.framework.storage=.cacheClient +DISCOVERY_CFG_POLL_INTERVAL=1 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/test/config.properties.in ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/test/config.properties.in b/remote_services/remote_service_admin_dfi/test/config.properties.in new file mode 100644 index 0000000..5776ad8 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/test/config.properties.in @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +cosgi.auto.start.1=@rsa_bundle_file@ @calc_bundle_file@ +LOGHELPER_ENABLE_STDOUT_FALLBACK=true +org.osgi.framework.storage.clean=onFirstInit \ No newline at end of file http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/test/server.properties.in ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/test/server.properties.in b/remote_services/remote_service_admin_dfi/test/server.properties.in new file mode 100644 index 0000000..707c7e6 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/test/server.properties.in @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +cosgi.auto.start.1=@rsa_bundle_file@ @calc_bundle_file@ @discovery_configured_bundle_file@ @topology_manager_bundle_file@ +LOGHELPER_ENABLE_STDOUT_FALLBACK=true +RSA_PORT=50882 +DISCOVERY_CFG_SERVER_PORT=50992 +org.osgi.framework.storage.clean=onFirstInit +org.osgi.framework.storage=.cacheServer +DISCOVERY_CFG_POLL_INTERVAL=1 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/test/src/rsa_client_server_tests.cpp ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/test/src/rsa_client_server_tests.cpp b/remote_services/remote_service_admin_dfi/test/src/rsa_client_server_tests.cpp new file mode 100644 index 0000000..528e6b7 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/test/src/rsa_client_server_tests.cpp @@ -0,0 +1,133 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ + +#include +#include +#include +#include +#include "CppUTest/CommandLineTestRunner.h" +#include "calculator_service.h" + +extern "C" { + +#include +#include +#include +#include +#include +#include + +#include "celix_launcher.h" +#include "framework.h" +#include "remote_service_admin.h" +#include "calculator_service.h" + + static framework_pt serverFramework = NULL; + static bundle_context_pt serverContext = NULL; + + static framework_pt clientFramework = NULL; + static bundle_context_pt clientContext = NULL; + + static void setupFm(void) { + int rc = 0; + bundle_pt bundle = NULL; + + //server + rc = celixLauncher_launch("server.properties", &serverFramework); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + bundle = NULL; + rc = framework_getFrameworkBundle(serverFramework, &bundle); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + rc = bundle_getContext(bundle, &serverContext); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + + //client + rc = celixLauncher_launch("client.properties", &clientFramework); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + bundle = NULL; + rc = framework_getFrameworkBundle(clientFramework, &bundle); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + rc = bundle_getContext(bundle, &clientContext); + CHECK_EQUAL(CELIX_SUCCESS, rc); + } + + static void teardownFm(void) { + celixLauncher_stop(serverFramework); + celixLauncher_waitForShutdown(serverFramework); + celixLauncher_destroy(serverFramework); + + celixLauncher_stop(clientFramework); + celixLauncher_waitForShutdown(clientFramework); + celixLauncher_destroy(clientFramework); + + serverContext = NULL; + serverFramework = NULL; + clientContext = NULL; + clientFramework = NULL; + } + + static void test1(void) { + celix_status_t rc; + service_reference_pt ref = NULL; + tst_service_pt tst = NULL; + int retries = 4; + + while (ref == NULL && retries > 0) { + printf("Waiting for service .. %d\n", retries); + rc = bundleContext_getServiceReference(clientContext, (char *) TST_SERVICE_NAME, &ref); + usleep(1000000); + --retries; + } + + CHECK_EQUAL(CELIX_SUCCESS, rc); + CHECK(ref != NULL); + + rc = bundleContext_getService(clientContext, ref, (void **)&tst); + CHECK_EQUAL(CELIX_SUCCESS, rc); + CHECK(tst != NULL); + + rc = tst->test(tst->handle); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + bool result; + bundleContext_ungetService(clientContext, ref, &result); + bundleContext_ungetServiceReference(clientContext, ref); + } + +} + + +TEST_GROUP(RsaDfiClientServerTests) { + void setup() { + setupFm(); + } + + void teardown() { + teardownFm(); + } +}; + +TEST(RsaDfiClientServerTests, Test1) { + test1(); +} http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/test/src/rsa_tests.cpp ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/test/src/rsa_tests.cpp b/remote_services/remote_service_admin_dfi/test/src/rsa_tests.cpp new file mode 100644 index 0000000..6026ac6 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/test/src/rsa_tests.cpp @@ -0,0 +1,234 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ + +#include +#include +#include +#include "CppUTest/CommandLineTestRunner.h" +#include "calculator_service.h" + +extern "C" { + +#include +#include +#include +#include +#include + +#include "celix_launcher.h" +#include "framework.h" +#include "remote_service_admin.h" +#include "calculator_service.h" + + + static framework_pt framework = NULL; + static bundle_context_pt context = NULL; + + static service_reference_pt rsaRef = NULL; + static remote_service_admin_service_pt rsa = NULL; + + static service_reference_pt calcRef = NULL; + static calculator_service_pt calc = NULL; + + static void setupFm(void) { + int rc = 0; + + rc = celixLauncher_launch("config.properties", &framework); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + bundle_pt bundle = NULL; + rc = framework_getFrameworkBundle(framework, &bundle); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + rc = bundle_getContext(bundle, &context); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + rc = bundleContext_getServiceReference(context, (char *)OSGI_RSA_REMOTE_SERVICE_ADMIN, &rsaRef); + CHECK_EQUAL(CELIX_SUCCESS, rc); + CHECK(rsaRef != NULL); + + rc = bundleContext_getService(context, rsaRef, (void **)&rsa); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + rc = bundleContext_getServiceReference(context, (char *)CALCULATOR2_SERVICE, &calcRef); + CHECK_EQUAL(CELIX_SUCCESS, rc); + CHECK(calcRef != NULL); + + rc = bundleContext_getService(context, calcRef, (void **)&calc); + CHECK_EQUAL(CELIX_SUCCESS, rc); + } + + static void teardownFm(void) { + int rc = 0; + rc = bundleContext_ungetService(context, rsaRef, NULL); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + rc = bundleContext_ungetServiceReference(context, rsaRef); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + rc = bundleContext_ungetService(context, calcRef, NULL); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + rc = bundleContext_ungetServiceReference(context, calcRef); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + celixLauncher_stop(framework); + celixLauncher_waitForShutdown(framework); + celixLauncher_destroy(framework); + + rsaRef = NULL; + rsa = NULL; + calcRef = NULL; + calc = NULL; + context = NULL; + framework = NULL; + } + + static void testServices(void) { + int rc = 0; + array_list_pt exported = NULL; + array_list_pt imported = NULL; + arrayList_create(&exported); + arrayList_create(&imported); + + rc = rsa->getExportedServices(rsa->admin, &exported); + CHECK_EQUAL(CELIX_SUCCESS, rc); + CHECK_EQUAL(0, arrayList_size(exported)); + + rc = rsa->getImportedEndpoints(rsa->admin, &imported); + CHECK_EQUAL(CELIX_SUCCESS, rc); + CHECK_EQUAL(0, arrayList_size(imported)); + + double result = 0; + rc = calc->add(calc->calculator, 2.0, 5.0, &result); + CHECK_EQUAL(CELIX_SUCCESS, rc); + CHECK_EQUAL(7.0, result); + + arrayList_destroy(imported); + arrayList_destroy(exported); + } + + static void testExportService(void) { + int rc = 0; + const char *calcId = NULL; + array_list_pt regs = NULL; + + rc = serviceReference_getProperty(calcRef, (char *)"service.id", &calcId); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + rc = rsa->exportService(rsa->admin, (char*)calcId, NULL, ®s); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + CHECK_EQUAL(1, arrayList_size(regs)); + + rc = rsa->exportRegistration_close(rsa->admin,(export_registration_pt)(arrayList_get(regs,0))); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + } + + static void testImportService(void) { + int rc = 0; + import_registration_pt reg = NULL; + endpoint_description_pt endpoint = NULL; + + properties_pt props = properties_create(); + properties_set(props, (char *)OSGI_RSA_ENDPOINT_SERVICE_ID, (char *)"42"); + properties_set(props, (char *)OSGI_RSA_ENDPOINT_FRAMEWORK_UUID, (char *)"eec5404d-51d0-47ef-8d86-c825a8beda42"); + properties_set(props, (char *)OSGI_RSA_ENDPOINT_ID, (char *)"eec5404d-51d0-47ef-8d86-c825a8beda42-42"); + properties_set(props, (char *)OSGI_FRAMEWORK_OBJECTCLASS,(char *)"org.apache.celix.Example"); + properties_set(props, (char *)"service.version",(char *)"1.0.0"); //TODO find out standard in osgi spec + + rc = endpointDescription_create(props, &endpoint); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + rc = rsa->importService(rsa->admin, endpoint, ®); + CHECK_EQUAL(CELIX_SUCCESS, rc); + CHECK(reg != NULL); + + service_reference_pt ref = NULL; + rc = bundleContext_getServiceReference(context, (char *)"org.apache.celix.Example", &ref); + CHECK_EQUAL(CELIX_SUCCESS, rc); + CHECK(ref != NULL); + + rc = bundleContext_ungetServiceReference(context, ref); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + rc = endpointDescription_destroy(endpoint); + CHECK_EQUAL(CELIX_SUCCESS, rc); + + /* Cannot test. uses requesting bundles descriptor + void *service = NULL; + rc = bundleContext_getService(context, ref, &service); + CHECK_EQUAL(CELIX_SUCCESS, rc); + CHECK(service != NULL); + */ + } + + static void testBundles(void) { + array_list_pt bundles = NULL; + + int rc = bundleContext_getBundles(context, &bundles); + CHECK_EQUAL(0, rc); + CHECK_EQUAL(3, arrayList_size(bundles)); //framework, rsa_dfi & calc + + /* + int size = arrayList_size(bundles); + int i; + for (i = 0; i < size; i += 1) { + bundle_pt bundle = NULL; + module_pt module = NULL; + char *name = NULL; + + bundle = (bundle_pt) arrayList_get(bundles, i); + bundle_getCurrentModule(bundle, &module); + module_getSymbolicName(module, &name); + printf("got bundle with symbolic name '%s'", name); + }*/ + + arrayList_destroy(bundles); + } + +} + + +TEST_GROUP(RsaDfiTests) { + void setup() { + setupFm(); + } + + void teardown() { + teardownFm(); + } +}; + +TEST(RsaDfiTests, InfoTest) { + testServices(); +} + +TEST(RsaDfiTests, ExportService) { + testExportService(); +} + +TEST(RsaDfiTests, ImportService) { + testImportService(); +} + +TEST(RsaDfiTests, TestBundles) { + testBundles(); +} http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/test/src/run_tests.cpp ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/test/src/run_tests.cpp b/remote_services/remote_service_admin_dfi/test/src/run_tests.cpp new file mode 100644 index 0000000..b5fd502 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/test/src/run_tests.cpp @@ -0,0 +1,25 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ + +#include +#include "CppUTest/CommandLineTestRunner.h" + +int main(int argc, char** argv) { + return RUN_ALL_TESTS(argc, argv); +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/test/src/tst_activator.c ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/test/src/tst_activator.c b/remote_services/remote_service_admin_dfi/test/src/tst_activator.c new file mode 100644 index 0000000..3db38fb --- /dev/null +++ b/remote_services/remote_service_admin_dfi/test/src/tst_activator.c @@ -0,0 +1,162 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ + +#include +#include +#include +#include +#include + +#include "bundle_activator.h" +#include "bundle_context.h" +#include "service_registration.h" +#include "service_reference.h" +#include "celix_errno.h" + +#include "tst_service.h" +#include "calculator_service.h" +#include + + +struct activator { + bundle_context_pt context; + struct tst_service serv; + service_registration_pt reg; + + service_tracker_customizer_pt cust; + service_tracker_pt tracker; + calculator_service_pt calc; +}; + +static celix_status_t addCalc(void * handle, service_reference_pt reference, void * service); +static celix_status_t removeCalc(void * handle, service_reference_pt reference, void * service); +static int test(void *handle); + +celix_status_t bundleActivator_create(bundle_context_pt context, void **out) { + celix_status_t status = CELIX_SUCCESS; + struct activator *act = calloc(1, sizeof(*act)); + if (act != NULL) { + act->context = context; + act->serv.handle = act; + act->serv.test = test; + + status = serviceTrackerCustomizer_create(act, NULL, addCalc, NULL, removeCalc, &act->cust); + status = CELIX_DO_IF(status, serviceTracker_create(context, CALCULATOR2_SERVICE, act->cust, &act->tracker)); + + } else { + status = CELIX_ENOMEM; + } + + if (status == CELIX_SUCCESS) { + *out = act; + } else if (act != NULL) { + if (act->cust != NULL) { + free(act->cust); + act->cust = NULL; + } + if (act->tracker != NULL) { + serviceTracker_destroy(act->tracker); + act->tracker = NULL; + } + free(act); + } + + return CELIX_SUCCESS; +} + +static celix_status_t addCalc(void * handle, service_reference_pt reference, void * service) { + celix_status_t status = CELIX_SUCCESS; + struct activator * act = handle; + act->calc = service; + return status; +} + +static celix_status_t removeCalc(void * handle, service_reference_pt reference, void * service) { + celix_status_t status = CELIX_SUCCESS; + struct activator * act = handle; + if (act->calc == service) { + act->calc = NULL; + } + return status; + +} + +celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) { + celix_status_t status = CELIX_SUCCESS; + struct activator * act = userData; + + act->reg = NULL; + status = bundleContext_registerService(context, (char *)TST_SERVICE_NAME, &act->serv, NULL, &act->reg); + + status = CELIX_DO_IF(status, serviceTracker_open(act->tracker)); + + + return status; +} + + +celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) { + celix_status_t status = CELIX_SUCCESS; + struct activator * act = userData; + + status = serviceRegistration_unregister(act->reg); + status = CELIX_DO_IF(status, serviceTracker_close(act->tracker)); + + return status; +} + +celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) { + struct activator *act = userData; + if (act != NULL) { + if (act->tracker != NULL) { + serviceTracker_destroy(act->tracker); + act->tracker = NULL; + } + free(act); + } + return CELIX_SUCCESS; +} + +static int test(void *handle) { + int status = 0; + struct activator *act = handle; + + double result = -1.0; + + int retries = 40; + + while (act->calc == NULL) { + printf("Waiting for calc service .. %d\n", retries); + usleep(100000); + --retries; + } + + int rc = 1; + if (act->calc != NULL) { + rc = act->calc->sqrt(act->calc->calculator, 4, &result); + printf("calc result is %f\n", result); + } else { + printf("calc not ready\n"); + } + + if (rc != 0 || result != 2.0) { + status = 1; + } + return status; +} http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/remote_service_admin_dfi/test/src/tst_service.h ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/test/src/tst_service.h b/remote_services/remote_service_admin_dfi/test/src/tst_service.h new file mode 100644 index 0000000..c8ca2e7 --- /dev/null +++ b/remote_services/remote_service_admin_dfi/test/src/tst_service.h @@ -0,0 +1,32 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ + +#ifndef CELIX_TST_SERVICE_H +#define CELIX_TST_SERVICE_H + +#define TST_SERVICE_NAME "tst_service" + +struct tst_service { + void *handle; + int (*test)(void *handle); +}; + +typedef struct tst_service *tst_service_pt; + +#endif //CELIX_TST_SERVICE_H http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/topology_manager/src/topology_manager.h ---------------------------------------------------------------------- diff --git a/remote_services/topology_manager/src/topology_manager.h b/remote_services/topology_manager/src/topology_manager.h index 7e5e917..b6ee064 100644 --- a/remote_services/topology_manager/src/topology_manager.h +++ b/remote_services/topology_manager/src/topology_manager.h @@ -35,6 +35,7 @@ #define OSGI_RSA_REMOTE_SERVICE_ADMIN "remote_service_admin" +typedef struct topology_manager topology_manager_t; typedef struct topology_manager *topology_manager_pt; celix_status_t topologyManager_create(bundle_context_pt context, log_helper_pt logHelper, topology_manager_pt *manager, void **scope); http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/topology_manager/tms_tst/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/remote_services/topology_manager/tms_tst/CMakeLists.txt b/remote_services/topology_manager/tms_tst/CMakeLists.txt index 6d0713c..5e27139 100644 --- a/remote_services/topology_manager/tms_tst/CMakeLists.txt +++ b/remote_services/topology_manager/tms_tst/CMakeLists.txt @@ -37,9 +37,18 @@ add_executable(test_tm_scoped run_tests.cpp tms_tests.cpp ) -target_link_libraries(test_tm_scoped Celix::framework ${CPPUTEST_LIBRARY} ${JANSSON_LIBRARY} Celix::log_helper remote_service_admin_common) +target_include_directories(test_tm_scoped PRIVATE ../src ../include) +target_link_libraries(test_tm_scoped PRIVATE + Celix::framework + ${CPPUTEST_LIBRARY} + ${JANSSON_LIBRARY} + Celix::log_helper + calculator_api + Celix::remote_service_admin_api + Celix::remote_service_admin_common +) -add_dependencies(test_tm_scoped remote_service_admin_dfi topology_manager calculator) +add_dependencies(test_tm_scoped remote_service_admin_dfi_bundle topology_manager_bundle) file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/config.properties" @@ -57,13 +66,6 @@ LOGHELPER_ENABLE_STDOUT_FALLBACK=true org.osgi.framework.storage.clean=onFirstInit ") - -#TODO improve copy commands, for now using configure_file as copy -#add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scope.json" COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURE_DIR}/scope.json" "${CMAKE_CURRENT_BINARY_DIR}/scope.json") -#add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scope2.json" COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURE_DIR}/scope2.json" "${CMAKE_CURRENT_BINARY_DIR}/scope2.json") -#add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scope3.json" COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURE_DIR}/scope3.json" "${CMAKE_CURRENT_BINARY_DIR}/scope3.json") -#add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scope4.json" COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURE_DIR}/scope4.json" "${CMAKE_CURRENT_BINARY_DIR}/scope4.json") - configure_file("scope.json" "scope.json") configure_file("scope2.json" "scope2.json") configure_file("scope3.json" "scope3.json") http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt b/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt index fc9d9bf..551995b 100644 --- a/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt +++ b/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt @@ -32,4 +32,4 @@ bundle_files(topology_manager_test_bundle DESTINATION . ) -target_link_libraries(topology_manager_test_bundle PRIVATE ${CPPUTEST_LIBRARY} remote_service_admin calculator_api) +target_link_libraries(topology_manager_test_bundle PRIVATE ${CPPUTEST_LIBRARY} Celix::remote_service_admin_api calculator_api) http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/topology_manager/tms_tst/disc_mock/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/remote_services/topology_manager/tms_tst/disc_mock/CMakeLists.txt b/remote_services/topology_manager/tms_tst/disc_mock/CMakeLists.txt index bfd7fc1..653b69c 100644 --- a/remote_services/topology_manager/tms_tst/disc_mock/CMakeLists.txt +++ b/remote_services/topology_manager/tms_tst/disc_mock/CMakeLists.txt @@ -20,7 +20,9 @@ add_bundle(topology_manager_disc_mock_bundle SOURCES disc_mock_activator.c disc_mock_service.c - ) -target_include_directories(topology_manager_disc_mock_bundle PRIVATE ${CPPUTEST_INCLUDE_DIR}) -target_link_libraries(topology_manager_disc_mock_bundle PRIVATE ${CPPUTEST_LIBRARY} Celix::framework discovery_common) +target_include_directories(topology_manager_disc_mock_bundle PRIVATE + ${CPPUTEST_INCLUDE_DIR} + $ +) +target_link_libraries(topology_manager_disc_mock_bundle PRIVATE ${CPPUTEST_LIBRARY} Celix::framework) http://git-wip-us.apache.org/repos/asf/celix/blob/27a2aa75/remote_services/topology_manager/tms_tst/disc_mock/disc_mock_activator.c ---------------------------------------------------------------------- diff --git a/remote_services/topology_manager/tms_tst/disc_mock/disc_mock_activator.c b/remote_services/topology_manager/tms_tst/disc_mock/disc_mock_activator.c index 53fccd7..d07ce02 100644 --- a/remote_services/topology_manager/tms_tst/disc_mock/disc_mock_activator.c +++ b/remote_services/topology_manager/tms_tst/disc_mock/disc_mock_activator.c @@ -29,7 +29,6 @@ #include "celix_errno.h" #include "disc_mock_service.h" -#include "discovery.h" #include "constants.h" #include "remote_constants.h"