You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2020/01/26 18:29:40 UTC
[celix] branch feature/gh-142-rsa-issues updated: gh-142: Extends
remote services test for string, const string,
enums and complex types and fixes several issues in remote services
This is an automated email from the ASF dual-hosted git repository.
pnoltes pushed a commit to branch feature/gh-142-rsa-issues
in repository https://gitbox.apache.org/repos/asf/celix.git
The following commit(s) were added to refs/heads/feature/gh-142-rsa-issues by this push:
new d1a18d9 gh-142: Extends remote services test for string, const string, enums and complex types and fixes several issues in remote services
d1a18d9 is described below
commit d1a18d9065b1f61052f941755f48088ac2cafbc1
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Sun Jan 26 19:28:36 2020 +0100
gh-142: Extends remote services test for string, const string, enums and complex types and fixes several issues in remote services
---
.../remote_example_api/include/remote_example.h | 30 +++--
.../org.apache.celix.RemoteExample.avdl | 20 ---
.../org.apache.celix.RemoteExample.avpr | 60 ---------
.../org.apache.celix.RemoteExample.descriptor | 8 +-
.../src/remote_example_activator.c | 4 +-
.../src/remote_example_impl.c | 52 +++++++-
.../src/remote_example_impl.h | 4 +
.../src/import_registration_dfi.c | 2 +-
.../test/src/rsa_client_server_tests.cpp | 25 +++-
.../test/src/run_tests.cpp | 1 +
.../test/src/tst_activator.c | 140 +++++++++++++++++----
.../test/src/tst_service.h | 9 +-
libs/dfi/include/dyn_function.h | 8 ++
libs/dfi/src/avrobin_serializer.c | 6 +
libs/dfi/src/dyn_function.c | 5 +
libs/dfi/src/dyn_type.c | 32 ++---
libs/dfi/src/json_rpc.c | 54 ++++++--
libs/dfi/src/json_serializer.c | 7 ++
18 files changed, 319 insertions(+), 148 deletions(-)
diff --git a/bundles/remote_services/examples/remote_example_api/include/remote_example.h b/bundles/remote_services/examples/remote_example_api/include/remote_example.h
index da60648..85a6821 100644
--- a/bundles/remote_services/examples/remote_example_api/include/remote_example.h
+++ b/bundles/remote_services/examples/remote_example_api/include/remote_example.h
@@ -22,14 +22,26 @@
#include <stdint.h>
-struct complex {
+enum enum_example {
+ ENUM_EXAMPLE_VAL1 = 2,
+ ENUM_EXAMPLE_VAL2 = 4,
+ ENUM_EXAMPLE_VAL3 = 8
+};
+
+
+struct complex_input_example {
double a;
double b;
- struct {
- int32_t len;
- int32_t cap;
- char** buf;
- };
+ int32_t n;
+ char *name;
+ enum enum_example e;
+};
+
+struct complex_output_example {
+ double pow;
+ int32_t fib;
+ char *name;
+ enum enum_example e;
};
#define REMOTE_EXAMPLE_NAME "org.apache.celix.RemoteExample"
@@ -43,7 +55,11 @@ typedef struct remote_example {
int (*setName1)(void *handle, char *n, char **out);
int (*setName2)(void *handle, const char *n, char **out);
- //TODO int (*updateComplex)(void *handle, struct complex *c, struct complex **out);
+ int (*setEnum)(void *handle, enum enum_example e, enum enum_example *out);
+
+ int (*action)(void *handle);
+
+ int (*setComplex)(void *handle, struct complex_input_example *exmpl, struct complex_output_example **out);
} remote_example_t;
diff --git a/bundles/remote_services/examples/remote_example_api/org.apache.celix.RemoteExample.avdl b/bundles/remote_services/examples/remote_example_api/org.apache.celix.RemoteExample.avdl
deleted file mode 100644
index abdcf82..0000000
--- a/bundles/remote_services/examples/remote_example_api/org.apache.celix.RemoteExample.avdl
+++ /dev/null
@@ -1,20 +0,0 @@
-@namespace("org.apache.celix")
-@version("1.0.0")
-protocol RemoteExample {
-
- //simple input
- @index(0) double pow(double a, double b);
- @index(1) int fib(int n);
-
- //string input
- @index(2) string setName1(string n); //callee takes ownership of string n
- @index(3) string setName2(string @const(true) n); //caller keeps ownership of string n
-
- record Complex {
- double a;
- double b;
- array<string> names;
- }
-
- //@index(4) Complex updateComplex(Complex c);
-}
\ No newline at end of file
diff --git a/bundles/remote_services/examples/remote_example_api/org.apache.celix.RemoteExample.avpr b/bundles/remote_services/examples/remote_example_api/org.apache.celix.RemoteExample.avpr
deleted file mode 100644
index 2d5887b..0000000
--- a/bundles/remote_services/examples/remote_example_api/org.apache.celix.RemoteExample.avpr
+++ /dev/null
@@ -1,60 +0,0 @@
-{
- "protocol" : "RemoteExample",
- "namespace" : "org.apache.celix",
- "version" : "1.0.0",
- "types" : [ {
- "type" : "record",
- "name" : "Complex",
- "fields" : [ {
- "name" : "a",
- "type" : "double"
- }, {
- "name" : "b",
- "type" : "double"
- }, {
- "name" : "names",
- "type" : {
- "type" : "array",
- "items" : "string"
- }
- } ]
- } ],
- "messages" : {
- "pow" : {
- "index" : 0,
- "request" : [ {
- "name" : "a",
- "type" : "double"
- }, {
- "name" : "b",
- "type" : "double"
- } ],
- "response" : "double"
- },
- "fib" : {
- "index" : 1,
- "request" : [ {
- "name" : "n",
- "type" : "int"
- } ],
- "response" : "int"
- },
- "setName1" : {
- "index" : 2,
- "request" : [ {
- "name" : "n",
- "type" : "string"
- } ],
- "response" : "string"
- },
- "setName2" : {
- "index" : 3,
- "request" : [ {
- "name" : "n",
- "type" : "string",
- "const" : true
- } ],
- "response" : "string"
- }
- }
-}
\ No newline at end of file
diff --git a/bundles/remote_services/examples/remote_example_api/org.apache.celix.RemoteExample.descriptor b/bundles/remote_services/examples/remote_example_api/org.apache.celix.RemoteExample.descriptor
index b6d7981..7c43bff 100644
--- a/bundles/remote_services/examples/remote_example_api/org.apache.celix.RemoteExample.descriptor
+++ b/bundles/remote_services/examples/remote_example_api/org.apache.celix.RemoteExample.descriptor
@@ -5,8 +5,14 @@ version=1.3.0
:annotations
classname=org.apache.celix.RemoteExample
:types
+enum_example=#ENUM_EXAMPLE_VAL1=2;#ENUM_EXAMPLE_VAL2=4;#ENUM_EXAMPLE_VAL3=8;E
+complex_input={DDItlenum_example; a b n name e}
+complex_output={DItlenum_example; pow fib name e}
:methods
pow(DD)D=pow(#am=handle;PDD#am=pre;*D)N
fib(I)I=fib(#am=handle;PI#am=pre;*I)N
setName1=setName1(#am=handle;Pt#am=out;*t)N
-setName2=setName2(#am=handle;Pt#am=out;*t)N
+setName2=setName2(#am=handle;P#const=true;t#am=out;*t)N
+setEnum=setEnum(#am=handle;Plenum_example;#am=pre;Lenum_example;)N
+action=action(#am=handle;P)N
+setComplex=setComplex(#am=handle;PLcomplex_input;#am=out;*Lcomplex_output;)N
diff --git a/bundles/remote_services/examples/remote_example_service/src/remote_example_activator.c b/bundles/remote_services/examples/remote_example_service/src/remote_example_activator.c
index 6f2bec3..09da9b4 100644
--- a/bundles/remote_services/examples/remote_example_service/src/remote_example_activator.c
+++ b/bundles/remote_services/examples/remote_example_service/src/remote_example_activator.c
@@ -40,7 +40,9 @@ celix_status_t remoteExampleBndStart(struct activator *act, celix_bundle_context
act->service.fib = (void*)remoteExample_fib;
act->service.setName1 = (void*)remoteExample_setName1;
act->service.setName2 = (void*)remoteExample_setName2;
- //TODO update complex
+ act->service.setEnum = (void*)remoteExample_setEnum;
+ act->service.action = (void*)remoteExample_action;
+ act->service.setComplex = (void*)remoteExample_setComplex;
celix_properties_t *properties = celix_properties_create();
celix_properties_set(properties, OSGI_RSA_SERVICE_EXPORTED_INTERFACES, REMOTE_EXAMPLE_NAME);
diff --git a/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.c b/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.c
index 600f9dd..2eb3eaa 100644
--- a/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.c
+++ b/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.c
@@ -18,19 +18,28 @@
*/
#include <math.h>
+#include <stdio.h>
#include <string.h>
+#include <pthread.h>
+#include "remote_example.h"
#include "remote_example_impl.h"
struct remote_example_impl {
+ pthread_mutex_t mutex; //protects below
char *name;
+ enum enum_example e;
};
remote_example_impl_t* remoteExample_create(void) {
- return calloc(1, sizeof(remote_example_impl_t));
+ remote_example_impl_t* impl = calloc(1, sizeof(remote_example_impl_t));
+ impl->e = ENUM_EXAMPLE_VAL1;
+ pthread_mutex_init(&impl->mutex, NULL);
+ return impl;
}
void remoteExample_destroy(remote_example_impl_t* impl) {
if (impl != NULL) {
+ pthread_mutex_destroy(&impl->mutex);
free(impl->name);
}
free(impl);
@@ -59,21 +68,62 @@ int remoteExample_fib(remote_example_impl_t* impl, int32_t a, int32_t *out) {
}
int remoteExample_setName1(remote_example_impl_t* impl, char *n, char **out) {
+ pthread_mutex_lock(&impl->mutex);
//note taking ownership of n;
if (impl->name != NULL) {
free(impl->name);
}
impl->name = n;
*out = strndup(impl->name, 1024 * 1024);
+ pthread_mutex_unlock(&impl->mutex);
return 0;
}
int remoteExample_setName2(remote_example_impl_t* impl, const char *n, char **out) {
+ pthread_mutex_lock(&impl->mutex);
//note _not_ taking ownership of n;
if (impl->name != NULL) {
free(impl->name);
}
impl->name = strndup(n, 1024 * 1024);
*out = strndup(impl->name, 1024 * 1024);
+ pthread_mutex_unlock(&impl->mutex);
return 0;
+}
+
+int remoteExample_setEnum(remote_example_impl_t* impl, enum enum_example e, enum enum_example *out) {
+ pthread_mutex_lock(&impl->mutex);
+ impl->e = e;
+ *out = e;
+ pthread_mutex_unlock(&impl->mutex);
+ return 0;
+}
+
+int remoteExample_action(remote_example_impl_t* impl) {
+ pthread_mutex_lock(&impl->mutex);
+ const char *n = impl->name;
+ printf("action called, name is %s\n", n);
+ pthread_mutex_unlock(&impl->mutex);
+ return 0;
+}
+
+int remoteExample_setComplex(remote_example_impl_t *impl, struct complex_input_example *exmpl, struct complex_output_example **out) {
+ struct complex_output_example *result = calloc(1, sizeof(*result));
+ int rc = remoteExample_pow(impl, exmpl->a, exmpl->b, &result->pow);
+ if (rc == 0) {
+ rc = remoteExample_fib(impl, exmpl->n, &result->fib);
+ }
+ if (rc == 0) {
+ rc = remoteExample_setName2(impl, exmpl->name, &result->name);
+ }
+ if (rc == 0) {
+ rc = remoteExample_setEnum(impl, exmpl->e, &result->e);
+ }
+ if (rc == 0 && out != NULL) {
+ *out = result;
+ } else {
+ free(result);
+ }
+
+ return rc;
}
\ No newline at end of file
diff --git a/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.h b/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.h
index 3bd2f70..fe23f73 100644
--- a/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.h
+++ b/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.h
@@ -24,13 +24,17 @@
typedef struct remote_example_impl remote_example_impl_t;
+
remote_example_impl_t* remoteExample_create(void);
void remoteExample_destroy(remote_example_impl_t* impl);
int remoteExample_pow(remote_example_impl_t* impl, double a, double b, double *out);
int remoteExample_fib(remote_example_impl_t* impl, int32_t a, int32_t *out);
+int remoteExample_setEnum(remote_example_impl_t* impl, enum enum_example e, enum enum_example *out);
int remoteExample_setName1(remote_example_impl_t* impl, char *n, char **out);
int remoteExample_setName2(remote_example_impl_t* impl, const char *n, char **out);
+int remoteExample_action(remote_example_impl_t* impl);
+int remoteExample_setComplex(remote_example_impl_t *impl, struct complex_input_example *exmpl, struct complex_output_example **out);
//TODO complex
#endif //CELIX_REMOTE_EXAMPLE_IMPL_H
diff --git a/bundles/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c b/bundles/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c
index fc01587..55a3810 100644
--- a/bundles/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c
+++ b/bundles/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c
@@ -340,7 +340,7 @@ static void importRegistration_proxyFunc(void *userData, void *args[], void *ret
celixThreadMutex_unlock(&import->mutex);
//printf("request sended. got reply '%s' with status %i\n", reply, rc);
- if (rc == 0) {
+ if (rc == 0 && dynFunction_hasReturn(entry->dynFunc)) {
//fjprintf("Handling reply '%s'\n", reply);
status = jsonRpc_handleReply(entry->dynFunc, reply, args);
}
diff --git a/bundles/remote_services/remote_service_admin_dfi/test/src/rsa_client_server_tests.cpp b/bundles/remote_services/remote_service_admin_dfi/test/src/rsa_client_server_tests.cpp
index 9333f2e..60a9277 100644
--- a/bundles/remote_services/remote_service_admin_dfi/test/src/rsa_client_server_tests.cpp
+++ b/bundles/remote_services/remote_service_admin_dfi/test/src/rsa_client_server_tests.cpp
@@ -88,7 +88,7 @@ extern "C" {
static void test(void) {
//TODO refactor to use celix_bundleContext_useService calls
- celix_status_t rc;
+ celix_status_t rc = 0;
service_reference_pt ref = NULL;
tst_service_t *tst = NULL;
int retries = 4;
@@ -110,14 +110,29 @@ extern "C" {
bool discovered = tst->isCalcDiscovered(tst->handle);
CHECK_TRUE(discovered);
- rc = tst->testCalculator(tst->handle);
- CHECK_EQUAL(CELIX_SUCCESS, rc);
+ bool ok = tst->testCalculator(tst->handle);
+ CHECK_TRUE(ok);
discovered = tst->isRemoteExampleDiscovered(tst->handle);
CHECK_TRUE(discovered);
- rc = tst->testRemoteExample(tst->handle);
- CHECK_EQUAL(CELIX_SUCCESS, rc);
+ ok = tst->testRemoteString(tst->handle);
+ CHECK_TRUE(ok);
+
+ ok = tst->testRemoteConstString(tst->handle);
+ CHECK_TRUE(ok);
+
+ ok = tst->testRemoteNumbers(tst->handle);
+ CHECK_TRUE(ok);
+
+ ok = tst->testRemoteEnum(tst->handle);
+ CHECK_TRUE(ok);
+
+ ok = tst->testRemoteAction(tst->handle);
+ CHECK_TRUE(ok);
+
+ ok = tst->testRemoteComplex(tst->handle);
+ CHECK_TRUE(ok);
bool result;
bundleContext_ungetService(clientContext, ref, &result);
diff --git a/bundles/remote_services/remote_service_admin_dfi/test/src/run_tests.cpp b/bundles/remote_services/remote_service_admin_dfi/test/src/run_tests.cpp
index c0d52be..efaee82 100644
--- a/bundles/remote_services/remote_service_admin_dfi/test/src/run_tests.cpp
+++ b/bundles/remote_services/remote_service_admin_dfi/test/src/run_tests.cpp
@@ -21,5 +21,6 @@
#include "CppUTest/CommandLineTestRunner.h"
int main(int argc, char** argv) {
+ MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
return RUN_ALL_TESTS(argc, argv);
}
\ No newline at end of file
diff --git a/bundles/remote_services/remote_service_admin_dfi/test/src/tst_activator.c b/bundles/remote_services/remote_service_admin_dfi/test/src/tst_activator.c
index 5e8d0ae..5894c73 100644
--- a/bundles/remote_services/remote_service_admin_dfi/test/src/tst_activator.c
+++ b/bundles/remote_services/remote_service_admin_dfi/test/src/tst_activator.c
@@ -97,8 +97,7 @@ static bool bndIsRemoteExampleDiscovered(void *handle) {
return discovered;
}
-static int bndTestCalculator(void *handle) {
- int status = 0;
+static bool bndTestCalculator(void *handle) {
struct activator *act = handle;
double result = -1.0;
@@ -113,14 +112,53 @@ static int bndTestCalculator(void *handle) {
}
pthread_mutex_unlock(&act->mutex);
+ return rc == 0 && result == 2.0;
+}
+
+static bool bndTestRemoteString(void *handle) {
+ bool ok;
+ struct activator *act = handle;
- if (rc != 0 || result != 2.0) {
- status = 1;
+ pthread_mutex_lock(&act->mutex);
+ if (act->remoteExample != NULL) {
+ //test string call with taking ownership
+ char *tmp = strndup("test1", 1024);
+ char *result = NULL;
+ act->remoteExample->setName1(act->remoteExample->handle, tmp, &result);
+ //note setName1 should take ownership of tmp, so no free(tmp) needed.
+ ok = strncmp("test1", result, 1024) == 0;
+ free(result);
+ } else {
+ fprintf(stderr, "remote example service not available");
+ ok = false;
}
- return status;
+ pthread_mutex_unlock(&act->mutex);
+
+ return ok;
}
-static int bndTestRemoteExample(void *handle) {
+static bool bndTestRemoteConstString(void *handle) {
+ bool ok;
+ struct activator *act = handle;
+
+ pthread_mutex_lock(&act->mutex);
+ if (act->remoteExample != NULL) {
+ //test pow
+ const char *name = "name2";
+ char *result = NULL;
+ act->remoteExample->setName2(act->remoteExample->handle, name, &result);
+ ok = strncmp(result, "name2", 1024) == 0;
+ free(result);
+ } else {
+ fprintf(stderr, "remote example service not available");
+ ok = false;
+ }
+ pthread_mutex_unlock(&act->mutex);
+
+ return ok;
+}
+
+static bool bndTestRemoteNumbers(void *handle) {
bool ok = true;
struct activator *act = handle;
@@ -140,33 +178,77 @@ static int bndTestRemoteExample(void *handle) {
act->remoteExample->fib(act->remoteExample->handle, 4, &f);
ok = (f == 3);
}
+ } else {
+ fprintf(stderr, "remote example service not available");
+ ok = false;
+ }
+ pthread_mutex_unlock(&act->mutex);
- if (ok) {
- //test string call with taking ownership
- char *tmp = strndup("test1", 1024);
- char *result = NULL;
- act->remoteExample->setName1(act->remoteExample->handle, tmp, &result);
- //note setName1 should take ownership of tmp, so no free(tmp) needed.
- ok = strncmp("test1", result, 1024) == 0;
- free(result);
- }
+ return ok;
+}
- if (ok) {
- //test string call with keeping ownership
- const char *tmp = "test2";
- char *result = NULL;
- act->remoteExample->setName2(act->remoteExample->handle, tmp, &result);
- ok = strncmp("test2", result, 1024) == 0;
- free(result); //TODO should fail on double free.
- }
+static bool bndTestRemoteEnum(void *handle) {
+ bool ok;
+ struct activator *act = handle;
+ pthread_mutex_lock(&act->mutex);
+ if (act->remoteExample != NULL) {
+ enum enum_example e = ENUM_EXAMPLE_VAL2;
+ enum enum_example result = ENUM_EXAMPLE_VAL3;
+ int rc = act->remoteExample->setEnum(act->remoteExample->handle, e, &result);
+ ok = rc == 0 && result == ENUM_EXAMPLE_VAL2;
} else {
fprintf(stderr, "remote example service not available");
- ok = false;
+ ok = false;
+ }
+ pthread_mutex_unlock(&act->mutex);
+
+ return ok;
+}
+
+static bool bndTestRemoteAction(void *handle) {
+ bool ok;
+ struct activator *act = handle;
+
+ pthread_mutex_lock(&act->mutex);
+ if (act->remoteExample != NULL) {
+ int rc = act->remoteExample->action(act->remoteExample->handle);
+ ok = rc == 0;
+ } else {
+ fprintf(stderr, "remote example service not available");
+ ok = false;
+ }
+ pthread_mutex_unlock(&act->mutex);
+
+ return ok;
+}
+
+static bool bndTestRemoteComplex(void *handle) {
+ bool ok;
+ struct activator *act = handle;
+
+ pthread_mutex_lock(&act->mutex);
+ if (act->remoteExample != NULL) {
+ struct complex_input_example exmpl;
+ exmpl.a = 2;
+ exmpl.b = 3;
+ exmpl.n = 5;
+ exmpl.name = "name";
+ exmpl.e = ENUM_EXAMPLE_VAL3;
+ struct complex_output_example* result = NULL;
+ int rc = act->remoteExample->setComplex(act->remoteExample->handle, &exmpl, &result);
+ ok = rc == 0 && result->pow == 8 && result->fib == 5 && strncmp("name", result->name, 64) == 0;
+ if (rc == 0) {
+ free(result->name);
+ free(result);
+ }
+ } else {
+ fprintf(stderr, "remote example service not available");
+ ok = false;
}
pthread_mutex_unlock(&act->mutex);
- return ok ? 0 : 1;
+ return ok;
}
static celix_status_t bndStart(struct activator *act, celix_bundle_context_t* ctx) {
@@ -175,7 +257,13 @@ static celix_status_t bndStart(struct activator *act, celix_bundle_context_t* ct
act->testSvc.isCalcDiscovered = bndIsCalculatorDiscovered;
act->testSvc.isRemoteExampleDiscovered = bndIsRemoteExampleDiscovered;
act->testSvc.testCalculator = bndTestCalculator;
- act->testSvc.testRemoteExample = bndTestRemoteExample;
+ act->testSvc.testRemoteString = bndTestRemoteString;
+ act->testSvc.testRemoteConstString = bndTestRemoteConstString;
+ act->testSvc.testRemoteNumbers = bndTestRemoteNumbers;
+ act->testSvc.testRemoteEnum = bndTestRemoteEnum;
+ act->testSvc.testRemoteAction = bndTestRemoteAction;
+ act->testSvc.testRemoteComplex = bndTestRemoteComplex;
+
//create mutex
pthread_mutex_init(&act->mutex, NULL);
diff --git a/bundles/remote_services/remote_service_admin_dfi/test/src/tst_service.h b/bundles/remote_services/remote_service_admin_dfi/test/src/tst_service.h
index 132b779..596ab63 100644
--- a/bundles/remote_services/remote_service_admin_dfi/test/src/tst_service.h
+++ b/bundles/remote_services/remote_service_admin_dfi/test/src/tst_service.h
@@ -26,8 +26,13 @@ struct tst_service {
void *handle;
bool (*isCalcDiscovered)(void *handle);
bool (*isRemoteExampleDiscovered)(void *handle);
- int (*testCalculator)(void *handle);
- int (*testRemoteExample)(void *handle);
+ bool (*testCalculator)(void *handle);
+ bool (*testRemoteString)(void *handle);
+ bool (*testRemoteConstString)(void *handle);
+ bool (*testRemoteNumbers)(void *handle);
+ bool (*testRemoteEnum)(void *handle);
+ bool (*testRemoteAction)(void *handle);
+ bool (*testRemoteComplex)(void *handle);
};
typedef struct tst_service tst_service_t;
diff --git a/libs/dfi/include/dyn_function.h b/libs/dfi/include/dyn_function.h
index 6a54622..16c0fd1 100644
--- a/libs/dfi/include/dyn_function.h
+++ b/libs/dfi/include/dyn_function.h
@@ -59,8 +59,16 @@ int dynFunction_call(dyn_function_type *dynFunc, void(*fn)(void), void *returnVa
int dynFunction_createClosure(dyn_function_type *func, void (*bind)(void *, void **, void*), void *userData, void(**fn)(void));
int dynFunction_getFnPointer(dyn_function_type *func, void (**fn)(void));
+/**
+ * Returns whether the function has a return type.
+ * Will return false if return is void.
+ */
+bool dynFunction_hasReturn(dyn_function_type *dynFunction);
+
// Avpr parsing
dyn_function_type * dynFunction_parseAvprWithStr(const char * avpr, const char * fqn);
dyn_function_type * dynFunction_parseAvpr(FILE * avprStream, const char * fqn);
+
+
#endif
diff --git a/libs/dfi/src/avrobin_serializer.c b/libs/dfi/src/avrobin_serializer.c
index 838a204..a7ed37c 100644
--- a/libs/dfi/src/avrobin_serializer.c
+++ b/libs/dfi/src/avrobin_serializer.c
@@ -380,6 +380,9 @@ static int avrobinSerializer_parseAny(dyn_type *type, void *loc, FILE *stream) {
status = avrobinSerializer_parseEnum(type, loc, stream);
}
break;
+ case 'l':
+ status = avrobinSerializer_parseAny(type->ref.ref, loc, stream);
+ break;
case 'P' :
status = ERROR;
LOG_WARNING("Untyped pointers are not supported for serialization.");
@@ -637,6 +640,9 @@ static int avrobinSerializer_writeAny(dyn_type *type, void *loc, FILE *stream) {
case 'E' :
status = avrobinSerializer_writeEnum(type, loc, stream);
break;
+ case 'l':
+ status = avrobinSerializer_writeAny(type->ref.ref, loc, stream);
+ break;
case 'P' :
status = ERROR;
LOG_WARNING("Untyped pointers are not supported for serialization.");
diff --git a/libs/dfi/src/dyn_function.c b/libs/dfi/src/dyn_function.c
index 802a8d4..56da893 100644
--- a/libs/dfi/src/dyn_function.c
+++ b/libs/dfi/src/dyn_function.c
@@ -23,6 +23,7 @@
#include <strings.h>
#include <stdlib.h>
#include <ffi.h>
+#include <dyn_type_common.h>
static const int OK = 0;
static const int MEM_ERROR = 1;
@@ -305,3 +306,7 @@ dyn_type * dynFunction_returnType(dyn_function_type *dynFunction) {
return dynFunction->funcReturn;
}
+bool dynFunction_hasReturn(dyn_function_type *dynFunction) {
+ dyn_type *t = dynFunction_returnType(dynFunction);
+ return t->descriptor != 'V';
+}
\ No newline at end of file
diff --git a/libs/dfi/src/dyn_type.c b/libs/dfi/src/dyn_type.c
index 89a1fa9..d227bbd 100644
--- a/libs/dfi/src/dyn_type.c
+++ b/libs/dfi/src/dyn_type.c
@@ -571,27 +571,29 @@ static void dynType_clearTypedPointer(dyn_type *type) {
}
int dynType_alloc(dyn_type *type, void **bufLoc) {
- assert(type->type != DYN_TYPE_REF);
- assert(type->ffiType->size != 0);
int status = OK;
- void *inst = calloc(1, type->ffiType->size);
- if (inst != NULL) {
- if (type->type == DYN_TYPE_TYPED_POINTER) {
- void *ptr = NULL;
- dyn_type *sub = NULL;
- status = dynType_typedPointer_getTypedType(type, &sub);
- if (status == OK) {
- status = dynType_alloc(sub, &ptr);
+ if (dynType_descriptorType(type) == 'l' /*reference*/) {
+ status = dynType_alloc(type->ref.ref, bufLoc);
+ } else {
+ void *inst = calloc(1, type->ffiType->size);
+ if (inst != NULL) {
+ if (type->type == DYN_TYPE_TYPED_POINTER) {
+ void *ptr = NULL;
+ dyn_type *sub = NULL;
+ status = dynType_typedPointer_getTypedType(type, &sub);
if (status == OK) {
- *(void **)inst = ptr;
+ status = dynType_alloc(sub, &ptr);
+ if (status == OK) {
+ *(void **) inst = ptr;
+ }
}
}
+ *bufLoc = inst;
+ } else {
+ status = MEM_ERROR;
+ LOG_ERROR("Error allocating memory for type '%c'", type->descriptor);
}
- *bufLoc = inst;
- } else {
- status = MEM_ERROR;
- LOG_ERROR("Error allocating memory for type '%c'", type->descriptor);
}
return status;
diff --git a/libs/dfi/src/json_rpc.c b/libs/dfi/src/json_rpc.c
index 912e23d..e683e2e 100644
--- a/libs/dfi/src/json_rpc.c
+++ b/libs/dfi/src/json_rpc.c
@@ -26,6 +26,7 @@
#include <stdint.h>
#include <string.h>
#include <ffi.h>
+#include <dyn_type_common.h>
static int OK = 0;
static int ERROR = 1;
@@ -150,7 +151,18 @@ int jsonRpc_call(dyn_interface_type *intf, void *service, const char *request, c
dyn_type *argType = dynFunction_argumentTypeForIndex(func, i);
enum dyn_function_argument_meta meta = dynFunction_argumentMetaForIndex(func, i);
if (meta == DYN_FUNCTION_ARGUMENT_META__STD) {
- dynType_free(argType, args[i]);
+ if (dynType_descriptorType(argType) == 't') {
+ const char* isConst = dynType_getMetaInfo(argType, "const");
+ if (isConst != NULL && strncmp("true", isConst, 5) == 0) {
+ dynType_free(argType, args[i]);
+ } else {
+ //char* -> callee is now owner, no free for char seq needed
+ //will free the actual pointer
+ free(args[i]);
+ }
+ } else {
+ dynType_free(argType, args[i]);
+ }
}
}
@@ -247,6 +259,17 @@ int jsonRpc_prepareInvokeRequest(dyn_function_type *func, const char *id, void *
json_t *val = NULL;
int rc = jsonSerializer_serializeJson(type, args[i], &val);
+
+ if (dynType_descriptorType(type) == 't') {
+ const char *metaArgument = dynType_getMetaInfo(type, "const");
+ if (metaArgument != NULL && strncmp("true", metaArgument, 5) == 0) {
+ //const char * as input -> nop
+ } else {
+ char **str = args[i];
+ free(*str); //char * as input -> got ownership -> free it.
+ }
+ }
+
if (rc == 0) {
json_array_append_new(arguments, val);
} else {
@@ -279,14 +302,15 @@ int jsonRpc_handleReply(dyn_function_type *func, const char *reply, void *args[]
}
json_t *result = NULL;
+ bool replyHasResult = false;
if (status == OK) {
- result = json_object_get(replyJson, "r"); //TODO check
- if (result == NULL) {
- status = ERROR;
- LOG_ERROR("Cannot find r entry in json reply '%s'", reply);
+ result = json_object_get(replyJson, "r");
+ if (result != NULL) {
+ replyHasResult = true;
}
}
+ bool replyHandled = false;
if (status == OK) {
int nrOfArgs = dynFunction_nrOfArguments(func);
int i;
@@ -299,19 +323,23 @@ int jsonRpc_handleReply(dyn_function_type *func, const char *reply, void *args[]
size_t size = 0;
- if (dynType_descriptorType(argType) == 't') {
+ if (result == NULL) {
+ LOG_WARNING("Expected result in reply. got '%s'", reply);
+ } else if (dynType_descriptorType(argType) == 't') {
status = jsonSerializer_deserializeJson(argType, result, &tmp);
- if(tmp!=NULL){
+ if (tmp != NULL) {
size = strnlen(((char *) *(char**) tmp), 1024 * 1024);
memcpy(*out, *(void**) tmp, size);
}
+ replyHandled = true;
} else {
dynType_typedPointer_getTypedType(argType, &argType);
status = jsonSerializer_deserializeJson(argType, result, &tmp);
- if(tmp!=NULL){
+ if (tmp != NULL) {
size = dynType_size(argType);
memcpy(*out, tmp, size);
}
+ replyHandled = true;
}
dynType_free(argType, tmp);
@@ -320,18 +348,22 @@ int jsonRpc_handleReply(dyn_function_type *func, const char *reply, void *args[]
dynType_typedPointer_getTypedType(argType, &subType);
- if (dynType_descriptorType(subType) == 't') {
+ if (result == NULL) {
+ LOG_WARNING("Expected result in reply. got '%s'", reply);
+ } else if (dynType_descriptorType(subType) == 't') {
char ***out = (char ***) args[i];
char **ptrToString = NULL;
status = jsonSerializer_deserializeJson(subType, result, (void**)&ptrToString);
char *s __attribute__((unused)) = *ptrToString; //note for debug
free(ptrToString);
**out = (void*)s;
+ replyHandled = true;
} else {
dyn_type *subSubType = NULL;
dynType_typedPointer_getTypedType(subType, &subSubType);
void ***out = (void ***) args[i];
status = jsonSerializer_deserializeJson(subSubType, result, *out);
+ replyHandled = true;
}
} else {
//skip
@@ -339,6 +371,10 @@ int jsonRpc_handleReply(dyn_function_type *func, const char *reply, void *args[]
}
}
+ if (replyHasResult && !replyHandled) {
+ LOG_WARNING("Reply has a result output, but this is not handled by the remote function!. Reply: '%s'", reply);
+ }
+
json_decref(replyJson);
return status;
diff --git a/libs/dfi/src/json_serializer.c b/libs/dfi/src/json_serializer.c
index 78f7e9b..4af5523 100644
--- a/libs/dfi/src/json_serializer.c
+++ b/libs/dfi/src/json_serializer.c
@@ -98,6 +98,7 @@ static int jsonSerializer_createType(dyn_type *type, json_t *val, void **result)
if (status == OK) {
*result = inst;
} else {
+ *result = NULL;
dynType_free(type, inst);
}
@@ -265,6 +266,9 @@ static int jsonSerializer_parseAny(dyn_type *type, void *loc, json_t *val) {
status = ERROR;
LOG_WARNING("Untyped pointer are not supported for serialization");
break;
+ case 'l':
+ status = jsonSerializer_parseAny(type->ref.ref, loc, val);
+ break;
default :
status = ERROR;
LOG_ERROR("Error provided type '%c' not supported for JSON\n", dynType_descriptorType(type));
@@ -427,6 +431,9 @@ static int jsonSerializer_writeAny(dyn_type *type, void* input, json_t **out) {
case 'P' :
LOG_WARNING("Untyped pointer not supported for serialization. ignoring");
break;
+ case 'l':
+ status = jsonSerializer_writeAny(type->ref.ref, input, out);
+ break;
default :
LOG_ERROR("Unsupported descriptor '%c'", descriptor);
status = ERROR;