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;