diff --git a/src/include/aes67/utils/mdns.h b/src/include/aes67/utils/mdns.h
index 30109acf20d74fd33f3848fc92d77cb0c35d6446..e7a0112a4844aaa6848b55ddeb8e122ed7a8ad34 100644
--- a/src/include/aes67/utils/mdns.h
+++ b/src/include/aes67/utils/mdns.h
@@ -75,7 +75,7 @@ aes67_mdns_register_start(aes67_mdns_context_t ctx, const char *fullname, u16_t
 void aes67_mdns_stop(aes67_mdns_resource_t res);
 
 
-void aes67_mdns_process(aes67_mdns_context_t ctx, struct timeval *timeout);
+void aes67_mdns_process(aes67_mdns_context_t ctx, int timeout_msec);
 
 void aes67_mdns_getsockfds(aes67_mdns_context_t ctx, int * fds[], size_t *count);
 
diff --git a/src/utils/mdns-avahi.c b/src/utils/mdns-avahi.c
index 1fb13c6d1bbeec034f7139ee5493d891bc85a8f3..ad1d5e9d01fc5a7b04e97086daebef7230a5841e 100644
--- a/src/utils/mdns-avahi.c
+++ b/src/utils/mdns-avahi.c
@@ -19,6 +19,7 @@
 #include "aes67/utils/mdns.h"
 
 #include <assert.h>
+#include <string.h>
 //#include <syslog.h>
 
 #include <avahi-client/client.h>
@@ -29,15 +30,123 @@
 
 //#error TODO see https://www.avahi.org/doxygen/html/client-browse-services_8c-example.html
 
-typedef struct {
-    AvahiServiceBrowser *sb;
-} browser_t;
+// forward decl
+struct context_st;
 
-typedef struct {
+enum restype {
+    restype_undefined,
+    restype_browse,
+    restype_resolve,
+    restype_resolve2_browse,
+    restype_resolve2_resolve,
+    restype_register_pending,
+    restype_register_done,
+    restype_publish_service_pending,
+    restype_publish_service_done,
+};
+
+typedef struct resource_st {
+    struct context_st * context;
+    void * res;
+    enum restype type;
+
+    void * callback;
+    void * user_data;
+
+    struct resource_st * next;
+} resource_t;
+
+
+typedef struct context_st {
     AvahiSimplePoll *simple_poll;
     AvahiClient *client;
-} avahi_context_t;
 
+    resource_t * first_resource;
+} context_t;
+
+static resource_t * resource_new(context_t * context, enum restype restype, void *callback, void * user_data)
+{
+
+    resource_t * r = calloc(1, sizeof(resource_t));
+
+    r->context = context;
+    r->type = restype;
+
+    r->callback = callback;
+    r->user_data = user_data;
+
+
+    return r;
+}
+
+static void resource_link(context_t * context, resource_t * res)
+{
+    res->next = context->first_resource;
+    context->first_resource = res;
+}
+
+static void resource_delete(context_t * context, resource_t * res)
+{
+    if (context->first_resource == res){
+        context->first_resource = res->next;
+    } else {
+        resource_t * prev = context->first_resource;
+
+        while(prev != NULL){
+
+            if (prev->next == res){
+                prev->next = res->next;
+                break;
+            }
+
+            prev = prev->next;
+        }
+    }
+
+    if (res->type == restype_browse && res->res){
+        avahi_service_browser_free(res->res);
+    }
+    else if (res->type == restype_resolve && res->res){
+        avahi_service_resolver_free(res->res);
+    }
+
+    free(res);
+}
+
+static char* avahi_string_list_to_raw(AvahiStringList *l, uint16_t * len) {
+    AvahiStringList *n;
+    size_t s = 0;
+    char *t, *e;
+
+    *len = 0;
+
+    for (n = l; n; n = n->next) {
+        s += 1 + n->size; /* +1 for the leading segment length byte */
+    }
+
+    if (!(t = e = malloc(s+1)))
+        return NULL;
+
+    l = avahi_string_list_reverse(l);
+
+    for (n = l; n; n = n->next) {
+        *(e++) = n->size;
+        for(int i = 0; i < n->size; i++){
+            *(e++) = n->text[i];
+        }
+
+        assert(e);
+    }
+
+    l = avahi_string_list_reverse(l);
+
+//    *e = 0; // actually, this is not needed, but let's play it safe.
+
+    // make sure to tell caller size of total txt
+    *len = s;
+
+    return t;
+}
 
 static void resolve_callback(
         AvahiServiceResolver *r,
@@ -53,37 +162,49 @@ static void resolve_callback(
         AvahiStringList *txt,
         AvahiLookupResultFlags flags,
         AVAHI_GCC_UNUSED void* userdata) {
+
+    resource_t * res = userdata;
+    assert(res);
+
     assert(r);
+
+    char * txtstr = NULL;
+    uint16_t txtlen = 0;
+
+    enum aes67_mdns_result result = aes67_mdns_result_error;
+
     /* Called whenever a service has been resolved successfully or timed out */
     switch (event) {
         case AVAHI_RESOLVER_FAILURE:
-            fprintf(stderr, "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r))));
+//            fprintf(stderr, "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r))));
+            result = aes67_mdns_result_error;
             break;
+
         case AVAHI_RESOLVER_FOUND: {
-            char a[AVAHI_ADDRESS_STR_MAX], *t;
-            fprintf(stderr, "Service '%s' of type '%s' in domain '%s':\n", name, type, domain);
-            avahi_address_snprint(a, sizeof(a), address);
-            t = avahi_string_list_to_string(txt);
-            fprintf(stderr,
-                    "\t%s:%u (%s)\n"
-                    "\tTXT=%s\n"
-                    "\tcookie is %u\n"
-                    "\tis_local: %i\n"
-                    "\tour_own: %i\n"
-                    "\twide_area: %i\n"
-                    "\tmulticast: %i\n"
-                    "\tcached: %i\n",
-                    host_name, port, a,
-                    t,
-                    avahi_string_list_get_service_cookie(txt),
-                    !!(flags & AVAHI_LOOKUP_RESULT_LOCAL),
-                    !!(flags & AVAHI_LOOKUP_RESULT_OUR_OWN),
-                    !!(flags & AVAHI_LOOKUP_RESULT_WIDE_AREA),
-                    !!(flags & AVAHI_LOOKUP_RESULT_MULTICAST),
-                    !!(flags & AVAHI_LOOKUP_RESULT_CACHED));
-            avahi_free(t);
+//            fprintf(stderr, "Service '%s' of type '%s' in domain '%s':\n", name, type, domain);
+            result = aes67_mdns_result_discovered;
+            txtstr = avahi_string_list_to_raw(txt, &txtlen);
         }
     }
+
+
+    enum aes67_net_ipver ipver = aes67_net_ipver_undefined;
+    const uint8_t * ip = NULL;
+    if (address->proto == AVAHI_PROTO_INET){
+        ipver = aes67_net_ipver_4;
+        ip = (uint8_t*)&address->data.ipv4.address;
+    } else if (address->proto == AVAHI_PROTO_INET6){
+        ipver = aes67_net_ipver_6;
+        ip = address->data.ipv6.address;
+    }
+
+    uint16_t ttl = 0;
+
+    ((aes67_mdns_resolve_callback) res->callback)(res, result, type, name, host_name,
+                                                  port, txtlen, (uint8_t*)txtstr, ipver, ip, ttl, res->user_data);
+    if (txtstr)
+        free(txtstr);
+
     avahi_service_resolver_free(r);
 }
 static void browse_callback(
@@ -96,45 +217,75 @@ static void browse_callback(
         const char *domain,
         AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
         void* userdata) {
-    AvahiClient *c = userdata;
-    assert(b);
+
+    resource_t * res = userdata;
+    assert(res);
+
+    enum aes67_mdns_result result;
+
     /* Called whenever a new services becomes available on the LAN or is removed from the LAN */
     switch (event) {
         case AVAHI_BROWSER_FAILURE:
-            fprintf(stderr, "(Browser) %s\n", avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b))));
-            avahi_simple_poll_quit(simple_poll);
+//            fprintf(stderr, "(Browser) %s\n", avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b))));
+//            avahi_simple_poll_quit(res->context->simple_poll);
+            result = aes67_mdns_result_error;
             return;
         case AVAHI_BROWSER_NEW:
-            fprintf(stderr, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
-            /* We ignore the returned resolver object. In the callback
-               function we free it. If the server is terminated before
-               the callback function is called the server will free
-               the resolver for us. */
-            if (!(avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, c)))
-                fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(c)));
+//            fprintf(stderr, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
+            result = aes67_mdns_result_discovered;
             break;
         case AVAHI_BROWSER_REMOVE:
-            fprintf(stderr, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
+//            fprintf(stderr, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
+            result = aes67_mdns_result_terminated;
             break;
+
         case AVAHI_BROWSER_ALL_FOR_NOW:
         case AVAHI_BROWSER_CACHE_EXHAUSTED:
-            fprintf(stderr, "(Browser) %s\n", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
-            break;
+//            fprintf(stderr, "(Browser) %s\n", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
+            return;
+
+        default:
+            // ignore
+            return;
+    }
+
+
+
+    if (res->type == restype_browse){
+        ((aes67_mdns_browse_callback)res->callback)(res, result, type, name, domain, res->user_data);
+    }
+    else if (res->type == restype_resolve2_browse){
+
+        if (result == aes67_mdns_result_error){
+            ((aes67_mdns_resolve_callback)res->callback)(res, aes67_mdns_result_error, NULL, NULL, NULL, 0, 0, NULL, aes67_net_ipver_undefined, NULL, 0, res->user_data);
+            return;
+        }
+
+        if (!(avahi_service_resolver_new(res->context->client, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, res))) {
+            fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
+                    avahi_strerror(avahi_client_errno(res->context->client)));
+        }
     }
 }
+
 static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
     assert(c);
+
+    context_t * context = userdata;
+
     /* Called whenever the client or server state changes */
     if (state == AVAHI_CLIENT_FAILURE) {
-        fprintf(stderr, "Server connection failure: %s\n", avahi_strerror(avahi_client_errno(c)));
-        avahi_simple_poll_quit(simple_poll);
+        fprintf(stderr, "Server connection failure: %s\n", avahi_strerror(avahi_client_errno(context->client)));
+        avahi_simple_poll_quit(context->simple_poll);
     }
 }
 
 
 aes67_mdns_context_t  aes67_mdns_new(void)
 {
-    avahi_context_t * context = calloc(1, sizeof(avahi_context_t);
+    int error;
+
+    context_t * context = calloc(1, sizeof(context_t));
 
     /* Allocate main loop object */
     if (!(context->simple_poll = avahi_simple_poll_new())) {
@@ -144,7 +295,7 @@ aes67_mdns_context_t  aes67_mdns_new(void)
     }
 
     /* Allocate a new client */
-    context->client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0, client_callback, NULL, &error);
+    context->client = avahi_client_new(avahi_simple_poll_get(context->simple_poll), 0, client_callback, context, &error);
 
     /* Check wether creating the client object succeeded */
     if (!context->client) {
@@ -160,9 +311,11 @@ void aes67_mdns_delete(aes67_mdns_context_t ctx)
 {
     assert(ctx != NULL);
 
-    avahi_context_t * context = ctx;
-
+    context_t * context = ctx;
 
+    if (context->client){
+        avahi_client_free(context->client);
+    }
 
     if (context->simple_poll){
         avahi_simple_poll_free(context->simple_poll);
@@ -170,3 +323,132 @@ void aes67_mdns_delete(aes67_mdns_context_t ctx)
 
     free(context);
 }
+
+
+aes67_mdns_resource_t
+aes67_mdns_browse_start(aes67_mdns_context_t ctx, const char *type, const char *domain,
+                        aes67_mdns_browse_callback callback, void *user_data)
+{
+    assert(ctx);
+
+    context_t * context = ctx;
+
+    AvahiIfIndex interface = AVAHI_IF_UNSPEC;
+    AvahiProtocol protocol = AVAHI_PROTO_UNSPEC;
+
+    AvahiLookupFlags flags = 0;
+
+    resource_t * res = resource_new(context, restype_browse, callback, user_data);
+
+    AvahiServiceBrowser * sb = res->res = avahi_service_browser_new(context->client, interface, protocol, type, domain, flags, browse_callback, res);
+
+    if (!sb){
+        free(res);
+        return NULL;
+    }
+
+    resource_link(context, res);
+
+    return res;
+}
+
+aes67_mdns_resource_t
+aes67_mdns_resolve_start(aes67_mdns_context_t ctx, const char *type, const char *name, const char *domain,
+                         aes67_mdns_resolve_callback callback, void *user_data)
+{
+    assert(ctx);
+
+    context_t * context = ctx;
+
+    AvahiIfIndex interface = AVAHI_IF_UNSPEC;
+    AvahiProtocol protocol = AVAHI_PROTO_UNSPEC;
+
+    AvahiLookupFlags flags = 0;
+
+    resource_t * res = resource_new(context, restype_resolve, callback, user_data);
+
+    AvahiServiceResolver * sr = res->res = avahi_service_resolver_new(res->context->client, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, flags, resolve_callback, res);
+
+    if (!sr) {
+        fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
+                avahi_strerror(avahi_client_errno(res->context->client)));
+        free(res);
+        return NULL;
+    }
+
+    resource_link(context, res);
+
+    return res;
+}
+
+aes67_mdns_resource_t
+aes67_mdns_resolve2_start(aes67_mdns_context_t ctx, const char *type, const char *domain,
+                          aes67_mdns_resolve_callback callback, void *user_data)
+{
+    assert(ctx);
+
+    context_t * context = ctx;
+
+    AvahiIfIndex interface = AVAHI_IF_UNSPEC;
+    AvahiProtocol protocol = AVAHI_PROTO_UNSPEC;
+
+    AvahiLookupFlags flags = 0;
+
+    resource_t * res = resource_new(context, restype_resolve2_browse, callback, user_data);
+
+    AvahiServiceBrowser * sb = res->res = avahi_service_browser_new(context->client, interface, protocol, type, domain, flags, browse_callback, res);
+
+    if (!sb){
+        free(res);
+        return NULL;
+    }
+
+    resource_link(context, res);
+
+    return res;
+}
+
+aes67_mdns_resource_t
+aes67_mdns_service_start(aes67_mdns_context_t ctx, const char *type, const char *name, const char *domain,
+                         const char * host, u16_t port, u16_t txtlen, const u8_t * txt, aes67_mdns_service_callback callback, void *user_data)
+{
+    return NULL;
+}
+
+aes67_mdns_resource_t
+aes67_mdns_service_addrecord(aes67_mdns_context_t ctx, aes67_mdns_resource_t service, u16_t rrtype, u16_t rdlen, const u8_t * rdata, u32_t ttl)
+{
+    return NULL;
+}
+
+aes67_mdns_resource_t
+aes67_mdns_register_start(aes67_mdns_context_t ctx, const char *fullname, u16_t rrtype, u16_t rrclass, u16_t rdlen, const u8_t * rdata, u32_t ttl, aes67_mdns_register_callback callback, void *user_data)
+{
+    return NULL;
+}
+
+
+void aes67_mdns_stop(aes67_mdns_resource_t res)
+{
+    assert(res);
+
+    resource_t * r = res;
+
+
+    resource_delete(r->context, r);
+}
+
+
+void aes67_mdns_process(aes67_mdns_context_t ctx, int timeout_msec)
+{
+    assert(ctx != NULL);
+
+    context_t * context = ctx;
+
+    avahi_simple_poll_iterate(context->simple_poll, timeout_msec);
+}
+
+int aes67_mdns_geterrcode(aes67_mdns_resource_t res)
+{
+    return 0;
+}
\ No newline at end of file
diff --git a/src/utils/mdns-dnssd.c b/src/utils/mdns-dnssd.c
index 92643d445b06708b698b91f4e13ea9deb1c49bb3..97c2e2c510532574d0029430a1ca1607a7c981c6 100644
--- a/src/utils/mdns-dnssd.c
+++ b/src/utils/mdns-dnssd.c
@@ -403,11 +403,12 @@ static void resolve_callback(DNSServiceRef ref, DNSServiceFlags flags, u32_t int
         if (hosttarget != NULL){
             res2->hostTarget = calloc(1, strlen(hosttarget)+1);
             strcpy(res2->hostTarget, hosttarget);
+            res2->hostTarget[strlen(hosttarget)-1] = '\0';
         }
         res2->port = ntohs(port);
-        res2->txtlen = txtlen;
 
-        if (txtlen > 0){
+        if (txtlen > 1){
+            res2->txtlen = txtlen;
             res2->txt = calloc(1, txtlen);
             memcpy(res2->txt, txt, txtlen);
         }
@@ -681,7 +682,7 @@ void aes67_mdns_stop(aes67_mdns_resource_t res)
 
 
 
-void aes67_mdns_process(aes67_mdns_context_t ctx, struct timeval *timeout)
+void aes67_mdns_process(aes67_mdns_context_t ctx, int timeout_msec)
 {
     assert(ctx != NULL);
 
@@ -693,7 +694,7 @@ void aes67_mdns_process(aes67_mdns_context_t ctx, struct timeval *timeout)
     FD_ZERO(&fds);
     FD_SET(__ctx->sockfd, &fds);
 
-    int retval = select(nfds, &fds, NULL, &fds, timeout);
+    int retval = select(nfds, &fds, NULL, &fds, NULL);
     if (retval > 0){
         DNSServiceProcessResult(__ctx->sharedRef);
     }
diff --git a/src/utils/rav-lookup/rav-lookup.c b/src/utils/rav-lookup/rav-lookup.c
index f18894303d8f7169839d3e65d00b0145588e3241..4f59ab17b8ffd5b01e2dc24ef429b4ffc323aea5 100644
--- a/src/utils/rav-lookup/rav-lookup.c
+++ b/src/utils/rav-lookup/rav-lookup.c
@@ -96,11 +96,11 @@ void session_lookup_callback(aes67_mdns_resource_t res, enum aes67_mdns_result r
 
             fprintf(stderr, "%s %s._session_ravenna._sub._rtsp._tcp @ %s:%hu (%s) [%d](", result == aes67_mdns_result_discovered ? "DISCOVERED" : "TERMINATED", name, hosttarget, port, ipstr, txtlen);
 
-            for (int i = 0; i < txtlen-1; i++){
+            for (int i = 0; i < txtlen; i++){
                 if (isprint(txt[i])){
                     fprintf(stderr, "%c", txt[i]);
                 } else {
-                    fprintf(stderr, " ");
+                    fprintf(stderr, " [%d]", txt[i]);
                 }
             }
             fprintf(stderr, ")\n");
@@ -110,7 +110,7 @@ void session_lookup_callback(aes67_mdns_resource_t res, enum aes67_mdns_result r
         if (result == opts.result_filter){
 
             char host[256];
-            size_t hostlen = strlen((char*)hosttarget) - 1;
+            size_t hostlen = strlen((char*)hosttarget);
 
             assert( hostlen < sizeof(host) - 1);
 
@@ -160,11 +160,11 @@ void receiver_lookup_callback(aes67_mdns_resource_t res, enum aes67_mdns_result
 
             fprintf(stderr, "DISCOVERED %s._ravenna._http._tcp @ %s:%hu (%s) [%d](", name, hosttarget, port, ipstr, txtlen);
 
-            for (int i = 0; i < txtlen-1; i++){
+            for (int i = 0; i < txtlen; i++){
                 if (isprint(txt[i])){
                     fprintf(stderr, "%c", txt[i]);
                 } else {
-                    fprintf(stderr, " ");
+                    fprintf(stderr, " [%d]", txt[i]);
                 }
             }
             fprintf(stderr, ")\n");
@@ -173,9 +173,9 @@ void receiver_lookup_callback(aes67_mdns_resource_t res, enum aes67_mdns_result
         }
         if (result == opts.result_filter){
             char host[256];
-            size_t hostlen = strlen((char*)hosttarget) - 1;
+            size_t hostlen = strlen((char*)hosttarget);
 
-            assert( hostlen < sizeof(host) - 1);
+            assert( hostlen < sizeof(host)-1);
 
             memcpy(host, hosttarget, hostlen);
             host[hostlen] = '\0';
@@ -200,11 +200,11 @@ void sender_lookup_callback(aes67_mdns_resource_t res, enum aes67_mdns_result re
 
             fprintf(stderr, "DISCOVERED %s._ravenna._rtsp._tcp @ %s:%hu (%s) [%d](", name, hosttarget, port, ipstr, txtlen);
 
-            for (int i = 0; i < txtlen-1; i++){
+            for (int i = 0; i < txtlen; i++){
                 if (isprint(txt[i])){
                     fprintf(stderr, "%c", txt[i]);
                 } else {
-                    fprintf(stderr, " ");
+                    fprintf(stderr, " [%d]", txt[i]);
                 }
             }
             fprintf(stderr, ")\n");
@@ -214,9 +214,9 @@ void sender_lookup_callback(aes67_mdns_resource_t res, enum aes67_mdns_result re
         if (result == opts.result_filter){
 
             char host[256];
-            size_t hostlen = strlen((char*)hosttarget) - 1;
+            size_t hostlen = strlen((char*)hosttarget);
 
-            assert( hostlen < sizeof(host) - 1);
+            assert( hostlen < sizeof(host)-1);
 
             memcpy(host, hosttarget, hostlen);
             host[hostlen] = '\0';
@@ -341,7 +341,7 @@ int main(int argc, char * argv[])
     signal(SIGINT, sig_int);
     keep_running = true;
     while(keep_running){
-        aes67_mdns_process(ctx, NULL);
+        aes67_mdns_process(ctx, 0);
     }
 
     aes67_mdns_delete(ctx);