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 2021/10/07 18:47:04 UTC

[celix] 01/02: Removes pubsub admin _v1 versions

This is an automated email from the ASF dual-hosted git repository.

pnoltes pushed a commit to branch feature/remove_psa_versions_v1
in repository https://gitbox.apache.org/repos/asf/celix.git

commit 99865c01c99f26b39f47f90c9fcbafb103bf5def
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Thu Oct 7 20:32:21 2021 +0200

    Removes pubsub admin _v1 versions
---
 bundles/pubsub/CMakeLists.txt                      |   14 +-
 bundles/pubsub/examples/CMakeLists.txt             |   24 +-
 .../pubsub_admin_tcp/{v2 => }/CMakeLists.txt       |    0
 .../pubsub_admin_tcp/{v2 => }/src/psa_activator.c  |    0
 .../{v2 => }/src/pubsub_psa_tcp_constants.h        |    0
 .../{v2 => }/src/pubsub_tcp_admin.c                |    0
 .../{v2 => }/src/pubsub_tcp_admin.h                |    0
 .../{v2 => }/src/pubsub_tcp_common.c               |    0
 .../{v2 => }/src/pubsub_tcp_common.h               |    0
 .../{v2 => }/src/pubsub_tcp_handler.c              |    0
 .../{v2 => }/src/pubsub_tcp_handler.h              |    0
 .../{v2 => }/src/pubsub_tcp_topic_receiver.c       |    0
 .../{v2 => }/src/pubsub_tcp_topic_receiver.h       |    0
 .../{v2 => }/src/pubsub_tcp_topic_sender.c         |    0
 .../{v2 => }/src/pubsub_tcp_topic_sender.h         |    0
 bundles/pubsub/pubsub_admin_tcp/v1/CMakeLists.txt  |   46 -
 .../pubsub/pubsub_admin_tcp/v1/src/psa_activator.c |  144 --
 .../v1/src/pubsub_psa_tcp_constants.h              |  140 --
 .../pubsub_admin_tcp/v1/src/pubsub_tcp_admin.c     |  785 -----------
 .../pubsub_admin_tcp/v1/src/pubsub_tcp_admin.h     |   80 --
 .../pubsub_admin_tcp/v1/src/pubsub_tcp_common.c    |   38 -
 .../pubsub_admin_tcp/v1/src/pubsub_tcp_common.h    |   33 -
 .../pubsub_admin_tcp/v1/src/pubsub_tcp_handler.c   | 1448 --------------------
 .../pubsub_admin_tcp/v1/src/pubsub_tcp_handler.h   |   92 --
 .../v1/src/pubsub_tcp_topic_receiver.c             |  804 -----------
 .../v1/src/pubsub_tcp_topic_receiver.h             |   57 -
 .../v1/src/pubsub_tcp_topic_sender.c               |  613 ---------
 .../v1/src/pubsub_tcp_topic_sender.h               |   60 -
 .../pubsub_admin_websocket/{v2 => }/CMakeLists.txt |    0
 .../{v2 => }/src/psa_activator.c                   |    0
 .../{v2 => }/src/pubsub_psa_websocket_constants.h  |    0
 .../{v2 => }/src/pubsub_websocket_admin.c          |    0
 .../{v2 => }/src/pubsub_websocket_admin.h          |    0
 .../{v2 => }/src/pubsub_websocket_common.c         |    0
 .../{v2 => }/src/pubsub_websocket_common.h         |    0
 .../{v2 => }/src/pubsub_websocket_topic_receiver.c |    0
 .../{v2 => }/src/pubsub_websocket_topic_receiver.h |    0
 .../{v2 => }/src/pubsub_websocket_topic_sender.c   |    0
 .../{v2 => }/src/pubsub_websocket_topic_sender.h   |    0
 .../pubsub_admin_websocket/v1/CMakeLists.txt       |   47 -
 .../pubsub_admin_websocket/v1/src/psa_activator.c  |  112 --
 .../v1/src/pubsub_psa_websocket_constants.h        |   54 -
 .../v1/src/pubsub_websocket_admin.c                |  605 --------
 .../v1/src/pubsub_websocket_admin.h                |   52 -
 .../v1/src/pubsub_websocket_common.c               |   68 -
 .../v1/src/pubsub_websocket_common.h               |   43 -
 .../v1/src/pubsub_websocket_topic_receiver.c       |  774 -----------
 .../v1/src/pubsub_websocket_topic_receiver.h       |   47 -
 .../v1/src/pubsub_websocket_topic_sender.c         |  381 -----
 .../v1/src/pubsub_websocket_topic_sender.h         |   43 -
 .../pubsub_admin_zmq/{v2 => }/CMakeLists.txt       |    0
 .../pubsub_admin_zmq/{v2 => }/src/psa_activator.c  |    0
 .../{v2 => }/src/pubsub_psa_zmq_constants.h        |    0
 .../{v2 => }/src/pubsub_zmq_admin.c                |    0
 .../{v2 => }/src/pubsub_zmq_admin.h                |    0
 .../{v2 => }/src/pubsub_zmq_topic_receiver.c       |    0
 .../{v2 => }/src/pubsub_zmq_topic_receiver.h       |    0
 .../{v2 => }/src/pubsub_zmq_topic_sender.c         |    0
 .../{v2 => }/src/pubsub_zmq_topic_sender.h         |    0
 .../pubsub_admin_zmq/{v2 => }/src/zmq_crypto.c     |    0
 .../pubsub_admin_zmq/{v2 => }/src/zmq_crypto.h     |    0
 bundles/pubsub/pubsub_admin_zmq/v1/CMakeLists.txt  |   61 -
 .../pubsub/pubsub_admin_zmq/v1/src/psa_activator.c |  141 --
 .../v1/src/pubsub_psa_zmq_constants.h              |  112 --
 .../pubsub_admin_zmq/v1/src/pubsub_zmq_admin.c     |  885 ------------
 .../pubsub_admin_zmq/v1/src/pubsub_zmq_admin.h     |   57 -
 .../v1/src/pubsub_zmq_topic_receiver.c             |  855 ------------
 .../v1/src/pubsub_zmq_topic_receiver.h             |   53 -
 .../v1/src/pubsub_zmq_topic_sender.c               |  748 ----------
 .../v1/src/pubsub_zmq_topic_sender.h               |   60 -
 .../pubsub/pubsub_admin_zmq/v1/src/zmq_crypto.c    |  278 ----
 .../pubsub/pubsub_admin_zmq/v1/src/zmq_crypto.h    |   41 -
 cmake/CelixConfig.cmake                            |    2 +-
 73 files changed, 17 insertions(+), 9880 deletions(-)

diff --git a/bundles/pubsub/CMakeLists.txt b/bundles/pubsub/CMakeLists.txt
index 39c04b2..39275c5 100644
--- a/bundles/pubsub/CMakeLists.txt
+++ b/bundles/pubsub/CMakeLists.txt
@@ -21,16 +21,12 @@ if (PUBSUB)
     option(BUILD_PUBSUB_PSA_ZMQ "Build ZeroMQ PubSub Admin (LGPL License)" ON)
     if (BUILD_PUBSUB_PSA_ZMQ)
         option(BUILD_ZMQ_SECURITY "Build with security for ZeroMQ." OFF)
-        add_subdirectory(pubsub_admin_zmq/v1)
-        add_subdirectory(pubsub_admin_zmq/v2)
-        add_library(Celix::celix_pubsub_admin_zmq ALIAS celix_pubsub_admin_zmq)
+        add_subdirectory(pubsub_admin_zmq)
     endif (BUILD_PUBSUB_PSA_ZMQ)
 
     option(BUILD_PUBSUB_PSA_TCP "Build TCP PubSub Admin" ON)
     if (BUILD_PUBSUB_PSA_TCP)
-        add_subdirectory(pubsub_admin_tcp/v1)
-        add_subdirectory(pubsub_admin_tcp/v2)
-        add_library(Celix::celix_pubsub_admin_tcp ALIAS celix_pubsub_admin_tcp)
+        add_subdirectory(pubsub_admin_tcp)
     endif (BUILD_PUBSUB_PSA_TCP)
 
     option(BUILD_PUBSUB_PSA_UDP_MC "Build UDP MC PubSub Admin" ON)
@@ -40,9 +36,7 @@ if (PUBSUB)
 
     option(BUILD_PUBSUB_PSA_WS "Build WebSocket PubSub Admin" ON)
     if (BUILD_PUBSUB_PSA_WS)
-        add_subdirectory(pubsub_admin_websocket/v1)
-        add_subdirectory(pubsub_admin_websocket/v2)
-        add_library(Celix::celix_pubsub_admin_websocket ALIAS celix_pubsub_admin_websocket)
+        add_subdirectory(pubsub_admin_websocket)
     endif (BUILD_PUBSUB_PSA_WS)
 
     add_subdirectory(pubsub_api)
@@ -58,7 +52,7 @@ if (PUBSUB)
     add_subdirectory(examples)
 
     if (ENABLE_TESTING)
-        add_subdirectory(integration)
+         add_subdirectory(integration)
     endif()
 
 endif(PUBSUB)
diff --git a/bundles/pubsub/examples/CMakeLists.txt b/bundles/pubsub/examples/CMakeLists.txt
index a34a28b..6b17310 100644
--- a/bundles/pubsub/examples/CMakeLists.txt
+++ b/bundles/pubsub/examples/CMakeLists.txt
@@ -108,7 +108,7 @@ if (BUILD_PUBSUB_PSA_TCP)
                 Celix::celix_pubsub_serializer_json
                 Celix::celix_pubsub_discovery_etcd
                 Celix::celix_pubsub_topology_manager
-                Celix::celix_pubsub_admin_tcp
+                Celix::celix_pubsub_admin_tcp_v2
                 Celix::celix_pubsub_protocol_wire_v2
                 celix_pubsub_poi_publisher
                 celix_pubsub_poi_publisher2
@@ -128,7 +128,7 @@ if (BUILD_PUBSUB_PSA_TCP)
                 Celix::celix_pubsub_serializer_json
                 Celix::celix_pubsub_discovery_etcd
                 Celix::celix_pubsub_topology_manager
-                Celix::celix_pubsub_admin_tcp
+                Celix::celix_pubsub_admin_tcp_v2
                 Celix::celix_pubsub_protocol_wire_v2
                 celix_pubsub_poi_subscriber
             PROPERTIES
@@ -147,7 +147,7 @@ if (BUILD_PUBSUB_PSA_TCP)
                 Celix::celix_pubsub_serializer_json
                 Celix::celix_pubsub_discovery_etcd
                 Celix::celix_pubsub_topology_manager
-                Celix::celix_pubsub_admin_tcp
+                Celix::celix_pubsub_admin_tcp_v2
                 Celix::celix_pubsub_protocol_wire_v2
                 celix_pubsub_poi_subscriber
             PROPERTIES
@@ -189,9 +189,9 @@ if (BUILD_PUBSUB_PSA_ZMQ)
                 Celix::celix_pubsub_serializer_json
                 Celix::celix_pubsub_discovery_etcd
                 Celix::celix_pubsub_topology_manager
-                Celix::celix_pubsub_admin_zmq
+                Celix::celix_pubsub_admin_zmq_v2
                 Celix::celix_pubsub_admin_udp_multicast
-                Celix::celix_pubsub_admin_tcp
+                Celix::celix_pubsub_admin_tcp_v2
                 Celix::celix_pubsub_protocol_wire_v1
                 celix_pubsub_poi_publisher
                 celix_pubsub_poi_publisher2
@@ -206,9 +206,9 @@ if (BUILD_PUBSUB_PSA_ZMQ)
                 Celix::celix_pubsub_serializer_json
                 Celix::celix_pubsub_discovery_etcd
                 Celix::celix_pubsub_topology_manager
-                Celix::celix_pubsub_admin_zmq
+                Celix::celix_pubsub_admin_zmq_v2
                 Celix::celix_pubsub_admin_udp_multicast
-                Celix::celix_pubsub_admin_tcp
+                Celix::celix_pubsub_admin_tcp_v2
                 Celix::celix_pubsub_protocol_wire_v1
                 celix_pubsub_poi_subscriber
         )
@@ -224,7 +224,7 @@ if (BUILD_PUBSUB_PSA_ZMQ)
             Celix::celix_pubsub_serializer_json
             Celix::celix_pubsub_discovery_etcd
             Celix::celix_pubsub_topology_manager
-            Celix::celix_pubsub_admin_zmq
+            Celix::celix_pubsub_admin_zmq_v2
             celix_pubsub_poi_publisher
             celix_pubsub_poi_subscriber
         PROPERTIES
@@ -241,7 +241,7 @@ if (BUILD_PUBSUB_PSA_ZMQ)
             Celix::celix_pubsub_protocol_wire_v1
             Celix::celix_pubsub_discovery_etcd
             Celix::celix_pubsub_topology_manager
-            Celix::celix_pubsub_admin_zmq
+            Celix::celix_pubsub_admin_zmq_v2
             celix_pubsub_poi_publisher
             celix_pubsub_poi_publisher2
             celix_pubsub_interceptors_example
@@ -262,7 +262,7 @@ if (BUILD_PUBSUB_PSA_ZMQ)
             Celix::celix_pubsub_protocol_wire_v1
             Celix::celix_pubsub_discovery_etcd
             Celix::celix_pubsub_topology_manager
-            Celix::celix_pubsub_admin_zmq
+            Celix::celix_pubsub_admin_zmq_v2
             celix_pubsub_poi_subscriber
             celix_pubsub_interceptors_example
         PROPERTIES
@@ -280,7 +280,7 @@ if (BUILD_PUBSUB_PSA_ZMQ)
             Celix::celix_pubsub_serializer_json
             Celix::celix_pubsub_discovery_etcd
             Celix::celix_pubsub_topology_manager
-            Celix::celix_pubsub_admin_zmq
+            Celix::celix_pubsub_admin_zmq_v2
             celix_pubsub_poi_subscriber
         PROPERTIES
             PSA_ZMQ_VERBOSE=true
@@ -417,7 +417,7 @@ if (BUILD_PUBSUB_PSA_WS)
             Celix::http_admin
             Celix::celix_pubsub_serializer_json
             Celix::celix_pubsub_topology_manager
-            Celix::celix_pubsub_admin_websocket
+            Celix::celix_pubsub_admin_websocket_v2
             celix_pubsub_websocket_example
         PROPERTIES
             PSA_TCP_VERBOSE=true
diff --git a/bundles/pubsub/pubsub_admin_tcp/v2/CMakeLists.txt b/bundles/pubsub/pubsub_admin_tcp/CMakeLists.txt
similarity index 100%
rename from bundles/pubsub/pubsub_admin_tcp/v2/CMakeLists.txt
rename to bundles/pubsub/pubsub_admin_tcp/CMakeLists.txt
diff --git a/bundles/pubsub/pubsub_admin_tcp/v2/src/psa_activator.c b/bundles/pubsub/pubsub_admin_tcp/src/psa_activator.c
similarity index 100%
rename from bundles/pubsub/pubsub_admin_tcp/v2/src/psa_activator.c
rename to bundles/pubsub/pubsub_admin_tcp/src/psa_activator.c
diff --git a/bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_psa_tcp_constants.h b/bundles/pubsub/pubsub_admin_tcp/src/pubsub_psa_tcp_constants.h
similarity index 100%
rename from bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_psa_tcp_constants.h
rename to bundles/pubsub/pubsub_admin_tcp/src/pubsub_psa_tcp_constants.h
diff --git a/bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_admin.c b/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_admin.c
similarity index 100%
rename from bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_admin.c
rename to bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_admin.c
diff --git a/bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_admin.h b/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_admin.h
similarity index 100%
rename from bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_admin.h
rename to bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_admin.h
diff --git a/bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_common.c b/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_common.c
similarity index 100%
rename from bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_common.c
rename to bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_common.c
diff --git a/bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_common.h b/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_common.h
similarity index 100%
rename from bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_common.h
rename to bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_common.h
diff --git a/bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_handler.c b/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_handler.c
similarity index 100%
rename from bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_handler.c
rename to bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_handler.c
diff --git a/bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_handler.h b/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_handler.h
similarity index 100%
rename from bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_handler.h
rename to bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_handler.h
diff --git a/bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_topic_receiver.c b/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_topic_receiver.c
similarity index 100%
rename from bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_topic_receiver.c
rename to bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_topic_receiver.c
diff --git a/bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_topic_receiver.h b/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_topic_receiver.h
similarity index 100%
rename from bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_topic_receiver.h
rename to bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_topic_receiver.h
diff --git a/bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_topic_sender.c b/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_topic_sender.c
similarity index 100%
rename from bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_topic_sender.c
rename to bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_topic_sender.c
diff --git a/bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_topic_sender.h b/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_topic_sender.h
similarity index 100%
rename from bundles/pubsub/pubsub_admin_tcp/v2/src/pubsub_tcp_topic_sender.h
rename to bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_topic_sender.h
diff --git a/bundles/pubsub/pubsub_admin_tcp/v1/CMakeLists.txt b/bundles/pubsub/pubsub_admin_tcp/v1/CMakeLists.txt
deleted file mode 100644
index 9a181eb..0000000
--- a/bundles/pubsub/pubsub_admin_tcp/v1/CMakeLists.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-# 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.
-
-message(STATUS "PubSub TCP Admin V1 is deprecated, and will eventually be replaced with PubSub TCP Admin v2")
-
-find_package(UUID REQUIRED)
-
-add_celix_bundle(celix_pubsub_admin_tcp
-    BUNDLE_SYMBOLICNAME "apache_celix_pubsub_admin_tcp"
-    VERSION "1.0.0"
-    GROUP "Celix/PubSub"
-    SOURCES
-        src/psa_activator.c
-        src/pubsub_tcp_admin.c
-        src/pubsub_tcp_topic_sender.c
-        src/pubsub_tcp_topic_receiver.c
-        src/pubsub_tcp_handler.c
-        src/pubsub_tcp_common.c
-)
-
-set_target_properties(celix_pubsub_admin_tcp PROPERTIES INSTALL_RPATH "$ORIGIN")
-target_link_libraries(celix_pubsub_admin_tcp PRIVATE Celix::pubsub_spi Celix::pubsub_utils)
-target_link_libraries(celix_pubsub_admin_tcp PRIVATE Celix::framework Celix::dfi Celix::log_helper)
-target_include_directories(celix_pubsub_admin_tcp PRIVATE src)
-# cmake find package UUID set the wrong include dir for OSX
-if (NOT APPLE)
-    target_link_libraries(celix_pubsub_admin_tcp PRIVATE UUID::lib)
-endif()
-
-install_celix_bundle(celix_pubsub_admin_tcp EXPORT celix COMPONENT pubsub)
-target_link_libraries(celix_pubsub_admin_tcp PRIVATE Celix::shell_api)
-add_library(Celix::celix_pubsub_admin_tcp ALIAS celix_pubsub_admin_tcp)
diff --git a/bundles/pubsub/pubsub_admin_tcp/v1/src/psa_activator.c b/bundles/pubsub/pubsub_admin_tcp/v1/src/psa_activator.c
deleted file mode 100644
index d93c478..0000000
--- a/bundles/pubsub/pubsub_admin_tcp/v1/src/psa_activator.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * 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 <stdlib.h>
-
-#include "celix_api.h"
-#include "pubsub_serializer.h"
-#include "pubsub_protocol.h"
-#include "celix_log_helper.h"
-
-#include "pubsub_admin.h"
-#include "pubsub_admin_metrics.h"
-#include "pubsub_tcp_admin.h"
-#include "celix_shell_command.h"
-
-typedef struct psa_tcp_activator {
-    celix_log_helper_t *logHelper;
-
-    pubsub_tcp_admin_t *admin;
-
-    long serializersTrackerId;
-    long protocolsTrackerId;
-
-    pubsub_admin_service_t adminService;
-    long adminSvcId;
-
-    pubsub_admin_metrics_service_t adminMetricsService;
-    long adminMetricsSvcId;
-
-    celix_shell_command_t cmdSvc;
-    long cmdSvcId;
-} psa_tcp_activator_t;
-
-int psa_tcp_start(psa_tcp_activator_t *act, celix_bundle_context_t *ctx) {
-    act->adminSvcId = -1L;
-    act->cmdSvcId = -1L;
-    act->serializersTrackerId = -1L;
-    act->protocolsTrackerId = -1L;
-
-    act->logHelper = celix_logHelper_create(ctx, "celix_psa_admin_tcp");
-
-    act->admin = pubsub_tcpAdmin_create(ctx, act->logHelper);
-    celix_status_t status = act->admin != NULL ? CELIX_SUCCESS : CELIX_BUNDLE_EXCEPTION;
-
-    //track serializers
-    if (status == CELIX_SUCCESS) {
-        celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
-        opts.filter.serviceName = PUBSUB_SERIALIZER_SERVICE_NAME;
-        opts.filter.ignoreServiceLanguage = true;
-        opts.callbackHandle = act->admin;
-        opts.addWithProperties = pubsub_tcpAdmin_addSerializerSvc;
-        opts.removeWithProperties = pubsub_tcpAdmin_removeSerializerSvc;
-        act->serializersTrackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts);
-    }
-
-    //track protocols
-    if (status == CELIX_SUCCESS) {
-        celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
-        opts.filter.serviceName = PUBSUB_PROTOCOL_SERVICE_NAME;
-        opts.filter.ignoreServiceLanguage = true;
-        opts.callbackHandle = act->admin;
-        opts.addWithProperties = pubsub_tcpAdmin_addProtocolSvc;
-        opts.removeWithProperties = pubsub_tcpAdmin_removeProtocolSvc;
-        act->protocolsTrackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts);
-    }
-
-    //register pubsub admin service
-    if (status == CELIX_SUCCESS) {
-        pubsub_admin_service_t *psaSvc = &act->adminService;
-        psaSvc->handle = act->admin;
-        psaSvc->matchPublisher = pubsub_tcpAdmin_matchPublisher;
-        psaSvc->matchSubscriber = pubsub_tcpAdmin_matchSubscriber;
-        psaSvc->matchDiscoveredEndpoint = pubsub_tcpAdmin_matchDiscoveredEndpoint;
-        psaSvc->setupTopicSender = pubsub_tcpAdmin_setupTopicSender;
-        psaSvc->teardownTopicSender = pubsub_tcpAdmin_teardownTopicSender;
-        psaSvc->setupTopicReceiver = pubsub_tcpAdmin_setupTopicReceiver;
-        psaSvc->teardownTopicReceiver = pubsub_tcpAdmin_teardownTopicReceiver;
-        psaSvc->addDiscoveredEndpoint = pubsub_tcpAdmin_addDiscoveredEndpoint;
-        psaSvc->removeDiscoveredEndpoint = pubsub_tcpAdmin_removeDiscoveredEndpoint;
-
-        celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, PUBSUB_ADMIN_SERVICE_TYPE, PUBSUB_TCP_ADMIN_TYPE);
-
-        act->adminSvcId = celix_bundleContext_registerService(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props);
-    }
-
-    if (status == CELIX_SUCCESS) {
-        act->adminMetricsService.handle = act->admin;
-        act->adminMetricsService.metrics = pubsub_tcpAdmin_metrics;
-
-        celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, PUBSUB_ADMIN_SERVICE_TYPE, PUBSUB_TCP_ADMIN_TYPE);
-
-        act->adminMetricsSvcId =
-            celix_bundleContext_registerService(ctx,
-                                                &act->adminMetricsService,
-                                                PUBSUB_ADMIN_METRICS_SERVICE_NAME,
-                                                props);
-    }
-
-    //register shell command service
-    {
-        act->cmdSvc.handle = act->admin;
-        act->cmdSvc.executeCommand = pubsub_tcpAdmin_executeCommand;
-        celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psa_tcp");
-        celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psa_tcp");
-        celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the TCP PSA");
-        act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props);
-    }
-
-    return status;
-}
-
-int psa_tcp_stop(psa_tcp_activator_t *act, celix_bundle_context_t *ctx) {
-    celix_bundleContext_unregisterService(ctx, act->adminSvcId);
-    celix_bundleContext_unregisterService(ctx, act->cmdSvcId);
-    celix_bundleContext_unregisterService(ctx, act->adminMetricsSvcId);
-    celix_bundleContext_stopTracker(ctx, act->serializersTrackerId);
-    celix_bundleContext_stopTracker(ctx, act->protocolsTrackerId);
-    pubsub_tcpAdmin_destroy(act->admin);
-
-    celix_logHelper_destroy(act->logHelper);
-
-    return CELIX_SUCCESS;
-}
-
-CELIX_GEN_BUNDLE_ACTIVATOR(psa_tcp_activator_t, psa_tcp_start, psa_tcp_stop);
diff --git a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_psa_tcp_constants.h b/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_psa_tcp_constants.h
deleted file mode 100644
index d493eaa..0000000
--- a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_psa_tcp_constants.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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 PUBSUB_PSA_TCP_CONSTANTS_H_
-#define PUBSUB_PSA_TCP_CONSTANTS_H_
-
-#define PSA_TCP_BASE_PORT                       "PSA_TCP_BASE_PORT"
-#define PSA_TCP_MAX_PORT                        "PSA_TCP_MAX_PORT"
-
-#define PSA_TCP_MAX_MESSAGE_SIZE                "PSA_TCP_MAX_MESSAGE_SIZE"
-#define PSA_TCP_RECV_BUFFER_SIZE                "PSA_TCP_RECV_BUFFER_SIZE"
-#define PSA_TCP_TIMEOUT                         "PSA_TCP_TIMEOUT"
-#define PSA_TCP_SUBSCRIBER_CONNECTION_TIMEOUT   "PSA_TCP_SUBSCRIBER_CONNECTION_TIMEOUT"
-
-#define PSA_TCP_DEFAULT_BASE_PORT               5501
-#define PSA_TCP_DEFAULT_MAX_PORT                6000
-
-#define PSA_TCP_DEFAULT_MAX_MESSAGE_SIZE        UINT32_MAX
-#define PSA_TCP_DEFAULT_RECV_BUFFER_SIZE        65 * 1024
-#define PSA_TCP_DEFAULT_TIMEOUT                 2000 // 2 seconds
-#define PSA_TCP_SUBSCRIBER_CONNECTION_DEFAULT_TIMEOUT 250 // 250 ms
-
-#define PSA_TCP_DEFAULT_QOS_SAMPLE_SCORE        30
-#define PSA_TCP_DEFAULT_QOS_CONTROL_SCORE       70
-#define PSA_TCP_DEFAULT_SCORE                   30
-
-#define PSA_TCP_QOS_SAMPLE_SCORE_KEY            "PSA_TCP_QOS_SAMPLE_SCORE"
-#define PSA_TCP_QOS_CONTROL_SCORE_KEY           "PSA_TCP_QOS_CONTROL_SCORE"
-#define PSA_TCP_DEFAULT_SCORE_KEY               "PSA_TCP_DEFAULT_SCORE"
-
-#define PSA_TCP_METRICS_ENABLED                 "PSA_TCP_METRICS_ENABLED"
-#define PSA_TCP_DEFAULT_METRICS_ENABLED         false
-
-#define PUBSUB_TCP_VERBOSE_KEY                  "PSA_TCP_VERBOSE"
-#define PUBSUB_TCP_VERBOSE_DEFAULT              false
-
-#define PUBSUB_TCP_PUBLISHER_RETRY_CNT_KEY      "PUBSUB_TCP_PUBLISHER_RETRY_COUNT"
-#define PUBSUB_TCP_PUBLISHER_RETRY_CNT_DEFAULT  5
-
-#define PUBSUB_TCP_SUBSCRIBER_RETRY_CNT_KEY     "PUBSUB_TCP_SUBSCRIBER_RETRY_COUNT"
-#define PUBSUB_TCP_SUBSCRIBER_RETRY_CNT_DEFAULT 5
-
-
-//Time-out settings are only for BLOCKING connections
-#define PUBSUB_TCP_PUBLISHER_SNDTIMEO_KEY       "PUBSUB_TCP_PUBLISHER_SEND_TIMEOUT"
-#define PUBSUB_TCP_PUBLISHER_SNDTIMEO_DEFAULT   5.0
-#define PUBSUB_TCP_PUBLISHER_SNDTIMEO_ENDPOINT_DEFAULT   0.0
-
-#define PUBSUB_TCP_SUBSCRIBER_RCVTIMEO_KEY      "PUBSUB_TCP_SUBSCRIBER_RCV_TIMEOUT"
-#define PUBSUB_TCP_SUBSCRIBER_RCVTIMEO_DEFAULT  5.0
-
-#define PUBSUB_TCP_PSA_IP_KEY                   "PSA_IP"
-#define PUBSUB_TCP_ADMIN_TYPE                   "tcp"
-
-/**
- * The TCP url key for the topic sender endpoints
- */
-#define PUBSUB_TCP_URL_KEY                      "tcp.url"
-
-/**
- * Can be set in the topic properties to fix a static bind url
- */
-#define PUBSUB_TCP_STATIC_BIND_URL              "tcp.static.bind.url"
-
-/**
- * Name of environment variable with ip/url to bind to
- * e.g. PSA_TCP_STATIC_BIND_FOR_topic_scope="tcp://0.0.0.0:4444"
- */
-#define PUBSUB_TCP_STATIC_BIND_URL_FOR          "PSA_TCP_STATIC_BIND_URL_FOR_"
-
-/**
- * Can be set in the topic properties to fix a static url used for discovery
- */
-#define PUBSUB_TCP_STATIC_DISCOVER_URL          "tcp.static.bind.url"
-
-/**
- * If set true on the endpoint, the tcp TopicSender bind and/or discovery url is statically configured.
- */
-#define PUBSUB_TCP_STATIC_CONFIGURED            "tcp.static.configured"
-
-/**
- * The static url which a subscriber should try to connect to.
- * The urls are space separated.
- * Can be set in the topic properties.
- */
-#define PUBSUB_TCP_STATIC_CONNECT_URLS          "tcp.static.connect.urls"
-
-
-/**
- * Defines if the publisher / subscriber is a passive endpoint and shares
- * the connection with publisher / subscriber endpoint with the matching (passive) key
- * e.g. tcp.passive.configured="true" means that a publisher / subscriber is passive,
- * when a publisher / subscriber is found with a matching key (for example tcp.passive.key="localhost").
- * This creates full-duplex connection using a single socket.
- */
-#define PUBSUB_TCP_PASSIVE_CONFIGURED            "tcp.passive.configured"
-#define PUBSUB_TCP_PASSIVE_KEY                   "tcp.passive.key"
-
-/**
- * Name of environment variable to indicate that passive endpoint is configured
- * e.g. PSA_TCP_PASSIVE_CONFIGURED_topic_scope="true"
- */
-#define PUBSUB_TCP_PASSIVE_ENABLED               "PSA_TCP_PASSIVE_CONFIGURED_"
-/**
- * Name of environment variable to configure the passive key (see PUBSUB_TCP_PASSIVE_KEY )
- * e.g. PSA_TCP_PASSIVE_KEY__topic_scope="tcp://localhost:4444"
- */
-#define PUBSUB_TCP_PASSIVE_SELECTION_KEY         "PSA_TCP_PASSIVE_KEY_"
-
-/**
- * Name of environment variable with space-separated list of ips/urls to connect to
- * e.g. PSA_TCP_STATIC_CONNECT_FOR_topic_scope="tcp://127.0.0.1:4444 tcp://127.0.0.2:4444"
- */
-#define PUBSUB_TCP_STATIC_CONNECT_URLS_FOR       "PSA_TCP_STATIC_CONNECT_URL_FOR_"
-
-/**
- * Realtime thread prio and scheduling information. This is used to setup the thread prio/sched of the
- * internal TCP threads.
- * Can be set in the topic properties.
- */
-#define PUBSUB_TCP_THREAD_REALTIME_PRIO         "thread.realtime.prio"
-#define PUBSUB_TCP_THREAD_REALTIME_SCHED        "thread.realtime.sched"
-
-#endif /* PUBSUB_PSA_TCP_CONSTANTS_H_ */
diff --git a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_admin.c b/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_admin.c
deleted file mode 100644
index ba3bdb8..0000000
--- a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_admin.c
+++ /dev/null
@@ -1,785 +0,0 @@
-/*
- * 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 <memory.h>
-#include <pubsub_endpoint.h>
-#include <pubsub_serializer.h>
-#include <ip_utils.h>
-
-#include "pubsub_utils.h"
-#include "pubsub_tcp_admin.h"
-#include "pubsub_tcp_handler.h"
-#include "pubsub_psa_tcp_constants.h"
-#include "pubsub_tcp_topic_sender.h"
-#include "pubsub_tcp_topic_receiver.h"
-
-#define L_DEBUG(...) \
-    celix_logHelper_log(psa->log, CELIX_LOG_LEVEL_DEBUG, __VA_ARGS__)
-#define L_INFO(...) \
-    celix_logHelper_log(psa->log, CELIX_LOG_LEVEL_INFO, __VA_ARGS__)
-#define L_WARN(...) \
-    celix_logHelper_log(psa->log, CELIX_LOG_LEVEL_WARNING, __VA_ARGS__)
-#define L_ERROR(...) \
-    celix_logHelper_log(psa->log, CELIX_LOG_LEVEL_ERROR, __VA_ARGS__)
-
-struct pubsub_tcp_admin {
-    celix_bundle_context_t *ctx;
-    celix_log_helper_t *log;
-    const char *fwUUID;
-
-    char *ipAddress;
-
-    unsigned int basePort;
-
-    double qosSampleScore;
-    double qosControlScore;
-    double defaultScore;
-
-    bool verbose;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = svcId, value = psa_tcp_serializer_entry_t*
-    } serializers;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = svcId, value = psa_tcp_protocol_entry_t*
-    } protocols;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = scope:topic key, value = pubsub_tcp_topic_sender_t*
-    } topicSenders;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = scope:topic key, value = pubsub_tcp_topic_sender_t*
-    } topicReceivers;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = endpoint uuid, value = celix_properties_t* (endpoint)
-    } discoveredEndpoints;
-
-    pubsub_tcp_endPointStore_t endpointStore;
-};
-
-typedef struct psa_tcp_serializer_entry {
-    const char *serType;
-    long svcId;
-    pubsub_serializer_service_t *svc;
-} psa_tcp_serializer_entry_t;
-
-typedef struct psa_tcp_protocol_entry {
-    const char *protType;
-    long svcId;
-    pubsub_protocol_service_t *svc;
-} psa_tcp_protocol_entry_t;
-
-static celix_status_t
-pubsub_tcpAdmin_connectEndpointToReceiver(pubsub_tcp_admin_t *psa, pubsub_tcp_topic_receiver_t *receiver,
-                                          const celix_properties_t *endpoint);
-
-static celix_status_t
-pubsub_tcpAdmin_disconnectEndpointFromReceiver(pubsub_tcp_admin_t *psa, pubsub_tcp_topic_receiver_t *receiver,
-                                               const celix_properties_t *endpoint);
-
-static bool pubsub_tcpAdmin_endpointIsPublisher(const celix_properties_t *endpoint) {
-    const char *type = celix_properties_get(endpoint, PUBSUB_ENDPOINT_TYPE, NULL);
-    return type != NULL && strncmp(PUBSUB_PUBLISHER_ENDPOINT_TYPE, type, strlen(PUBSUB_PUBLISHER_ENDPOINT_TYPE)) == 0;
-}
-
-pubsub_tcp_admin_t *pubsub_tcpAdmin_create(celix_bundle_context_t *ctx, celix_log_helper_t *logHelper) {
-    pubsub_tcp_admin_t *psa = calloc(1, sizeof(*psa));
-    psa->ctx = ctx;
-    psa->log = logHelper;
-    psa->verbose = celix_bundleContext_getPropertyAsBool(ctx, PUBSUB_TCP_VERBOSE_KEY, PUBSUB_TCP_VERBOSE_DEFAULT);
-    psa->fwUUID = celix_bundleContext_getProperty(ctx, OSGI_FRAMEWORK_FRAMEWORK_UUID, NULL);
-    long basePort = celix_bundleContext_getPropertyAsLong(ctx, PSA_TCP_BASE_PORT, PSA_TCP_DEFAULT_BASE_PORT);
-    psa->basePort = (unsigned int) basePort;
-    psa->defaultScore = celix_bundleContext_getPropertyAsDouble(ctx, PSA_TCP_DEFAULT_SCORE_KEY, PSA_TCP_DEFAULT_SCORE);
-    psa->qosSampleScore = celix_bundleContext_getPropertyAsDouble(ctx, PSA_TCP_QOS_SAMPLE_SCORE_KEY,
-                                                                  PSA_TCP_DEFAULT_QOS_SAMPLE_SCORE);
-    psa->qosControlScore = celix_bundleContext_getPropertyAsDouble(ctx, PSA_TCP_QOS_CONTROL_SCORE_KEY,
-                                                                   PSA_TCP_DEFAULT_QOS_CONTROL_SCORE);
-
-    celixThreadMutex_create(&psa->serializers.mutex, NULL);
-    psa->serializers.map = hashMap_create(NULL, NULL, NULL, NULL);
-
-    celixThreadMutex_create(&psa->protocols.mutex, NULL);
-    psa->protocols.map = hashMap_create(NULL, NULL, NULL, NULL);
-    celixThreadMutex_create(&psa->topicSenders.mutex, NULL);
-    psa->topicSenders.map = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-
-    celixThreadMutex_create(&psa->topicReceivers.mutex, NULL);
-    psa->topicReceivers.map = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-
-    celixThreadMutex_create(&psa->discoveredEndpoints.mutex, NULL);
-    psa->discoveredEndpoints.map = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-
-    celixThreadMutex_create(&psa->endpointStore.mutex, NULL);
-    psa->endpointStore.map = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-
-    return psa;
-}
-
-void pubsub_tcpAdmin_destroy(pubsub_tcp_admin_t *psa) {
-    if (psa == NULL) {
-        return;
-    }
-
-    celixThreadMutex_lock(&psa->endpointStore.mutex);
-    hash_map_iterator_t iter = hashMapIterator_construct(psa->endpointStore.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        pubsub_tcpHandler_t *tcpHandler = hashMapIterator_nextValue(&iter);
-        pubsub_tcpHandler_destroy(tcpHandler);
-    }
-    celixThreadMutex_unlock(&psa->endpointStore.mutex);
-
-    celixThreadMutex_lock(&psa->topicSenders.mutex);
-    iter = hashMapIterator_construct(psa->topicSenders.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        pubsub_tcp_topic_sender_t *sender = hashMapIterator_nextValue(&iter);
-        pubsub_tcpTopicSender_destroy(sender);
-    }
-    celixThreadMutex_unlock(&psa->topicSenders.mutex);
-
-    celixThreadMutex_lock(&psa->topicReceivers.mutex);
-    iter = hashMapIterator_construct(psa->topicReceivers.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        pubsub_tcp_topic_receiver_t *recv = hashMapIterator_nextValue(&iter);
-        pubsub_tcpTopicReceiver_destroy(recv);
-    }
-    celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-
-    celixThreadMutex_lock(&psa->discoveredEndpoints.mutex);
-    iter = hashMapIterator_construct(psa->discoveredEndpoints.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        celix_properties_t *ep = hashMapIterator_nextValue(&iter);
-        celix_properties_destroy(ep);
-    }
-    celixThreadMutex_unlock(&psa->discoveredEndpoints.mutex);
-
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    iter = hashMapIterator_construct(psa->serializers.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_tcp_serializer_entry_t *entry = hashMapIterator_nextValue(&iter);
-        free(entry);
-    }
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-
-    celixThreadMutex_lock(&psa->protocols.mutex);
-    iter = hashMapIterator_construct(psa->protocols.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_tcp_protocol_entry_t *entry = hashMapIterator_nextValue(&iter);
-        free(entry);
-    }
-    celixThreadMutex_unlock(&psa->protocols.mutex);
-    //note assuming al psa register services and service tracker are removed.
-    celixThreadMutex_destroy(&psa->endpointStore.mutex);
-    hashMap_destroy(psa->endpointStore.map, false, false);
-
-    celixThreadMutex_destroy(&psa->topicSenders.mutex);
-    hashMap_destroy(psa->topicSenders.map, true, false);
-
-    celixThreadMutex_destroy(&psa->topicReceivers.mutex);
-    hashMap_destroy(psa->topicReceivers.map, true, false);
-
-    celixThreadMutex_destroy(&psa->discoveredEndpoints.mutex);
-    hashMap_destroy(psa->discoveredEndpoints.map, false, false);
-
-    celixThreadMutex_destroy(&psa->serializers.mutex);
-    hashMap_destroy(psa->serializers.map, false, false);
-    celixThreadMutex_destroy(&psa->protocols.mutex);
-    hashMap_destroy(psa->protocols.map, false, false);
-
-    free(psa->ipAddress);
-
-    free(psa);
-}
-
-void pubsub_tcpAdmin_addSerializerSvc(void *handle, void *svc, const celix_properties_t *props) {
-    pubsub_tcp_admin_t *psa = handle;
-
-    const char *serType = celix_properties_get(props, PUBSUB_SERIALIZER_TYPE_KEY, NULL);
-    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L);
-
-    if (serType == NULL) {
-        L_INFO("[PSA_TCP] Ignoring serializer service without %s property", PUBSUB_SERIALIZER_TYPE_KEY);
-        return;
-    }
-
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    psa_tcp_serializer_entry_t *entry = hashMap_get(psa->serializers.map, (void *) svcId);
-    if (entry == NULL) {
-        entry = calloc(1, sizeof(*entry));
-        entry->serType = serType;
-        entry->svcId = svcId;
-        entry->svc = svc;
-        hashMap_put(psa->serializers.map, (void *) svcId, entry);
-    }
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-}
-
-void pubsub_tcpAdmin_removeSerializerSvc(void *handle, void *svc, const celix_properties_t *props) {
-    pubsub_tcp_admin_t *psa = handle;
-    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L);
-
-    //remove serializer
-    // 1) First find entry and
-    // 2) loop and destroy all topic sender using the serializer and
-    // 3) loop and destroy all topic receivers using the serializer
-    // Note that it is the responsibility of the topology manager to create new topic senders/receivers
-
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    psa_tcp_serializer_entry_t *entry = hashMap_remove(psa->serializers.map, (void *) svcId);
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-
-    if (entry != NULL) {
-        celixThreadMutex_lock(&psa->topicSenders.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(psa->topicSenders.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            hash_map_entry_t *senderEntry = hashMapIterator_nextEntry(&iter);
-            pubsub_tcp_topic_sender_t *sender = hashMapEntry_getValue(senderEntry);
-            if (sender != NULL && entry->svcId == pubsub_tcpTopicSender_serializerSvcId(sender)) {
-                char *key = hashMapEntry_getKey(senderEntry);
-                hashMapIterator_remove(&iter);
-                pubsub_tcpTopicSender_destroy(sender);
-                free(key);
-            }
-        }
-        celixThreadMutex_unlock(&psa->topicSenders.mutex);
-
-        celixThreadMutex_lock(&psa->topicReceivers.mutex);
-        iter = hashMapIterator_construct(psa->topicReceivers.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            hash_map_entry_t *senderEntry = hashMapIterator_nextEntry(&iter);
-            pubsub_tcp_topic_receiver_t *receiver = hashMapEntry_getValue(senderEntry);
-            if (receiver != NULL && entry->svcId == pubsub_tcpTopicReceiver_serializerSvcId(receiver)) {
-                char *key = hashMapEntry_getKey(senderEntry);
-                hashMapIterator_remove(&iter);
-                pubsub_tcpTopicReceiver_destroy(receiver);
-                free(key);
-            }
-        }
-        celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-
-        free(entry);
-    }
-}
-
-void pubsub_tcpAdmin_addProtocolSvc(void *handle, void *svc, const celix_properties_t *props) {
-    pubsub_tcp_admin_t *psa = handle;
-
-    const char *protType = celix_properties_get(props, PUBSUB_PROTOCOL_TYPE_KEY, NULL);
-    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L);
-
-    if (protType == NULL) {
-        L_INFO("[PSA_ZMQ] Ignoring protocol service without %s property", PUBSUB_PROTOCOL_TYPE_KEY);
-        return;
-    }
-
-    celixThreadMutex_lock(&psa->protocols.mutex);
-    psa_tcp_protocol_entry_t *entry = hashMap_get(psa->protocols.map, (void *) svcId);
-    if (entry == NULL) {
-        entry = calloc(1, sizeof(*entry));
-        entry->protType = protType;
-        entry->svcId = svcId;
-        entry->svc = svc;
-        hashMap_put(psa->protocols.map, (void *) svcId, entry);
-    }
-    celixThreadMutex_unlock(&psa->protocols.mutex);
-}
-
-void pubsub_tcpAdmin_removeProtocolSvc(void *handle, void *svc, const celix_properties_t *props) {
-    pubsub_tcp_admin_t *psa = handle;
-    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L);
-
-    //remove protocol
-    // 1) First find entry and
-    // 2) loop and destroy all topic sender using the protocol and
-    // 3) loop and destroy all topic receivers using the protocol
-    // Note that it is the responsibility of the topology manager to create new topic senders/receivers
-
-    celixThreadMutex_lock(&psa->protocols.mutex);
-    psa_tcp_protocol_entry_t *entry = hashMap_remove(psa->protocols.map, (void *) svcId);
-    celixThreadMutex_unlock(&psa->protocols.mutex);
-
-    if (entry != NULL) {
-        celixThreadMutex_lock(&psa->topicSenders.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(psa->topicSenders.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            hash_map_entry_t *senderEntry = hashMapIterator_nextEntry(&iter);
-            pubsub_tcp_topic_sender_t *sender = hashMapEntry_getValue(senderEntry);
-            if (sender != NULL && entry->svcId == pubsub_tcpTopicSender_protocolSvcId(sender)) {
-                char *key = hashMapEntry_getKey(senderEntry);
-                hashMapIterator_remove(&iter);
-                pubsub_tcpTopicSender_destroy(sender);
-                free(key);
-            }
-        }
-        celixThreadMutex_unlock(&psa->topicSenders.mutex);
-
-        celixThreadMutex_lock(&psa->topicReceivers.mutex);
-        iter = hashMapIterator_construct(psa->topicReceivers.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            hash_map_entry_t *senderEntry = hashMapIterator_nextEntry(&iter);
-            pubsub_tcp_topic_receiver_t *receiver = hashMapEntry_getValue(senderEntry);
-            if (receiver != NULL && entry->svcId == pubsub_tcpTopicReceiver_protocolSvcId(receiver)) {
-                char *key = hashMapEntry_getKey(senderEntry);
-                hashMapIterator_remove(&iter);
-                pubsub_tcpTopicReceiver_destroy(receiver);
-                free(key);
-            }
-        }
-        celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-
-        free(entry);
-    }
-}
-
-celix_status_t pubsub_tcpAdmin_matchPublisher(void *handle, long svcRequesterBndId, const celix_filter_t *svcFilter,
-                                              celix_properties_t **topicProperties, double *outScore,
-                                              long *outSerializerSvcId, long *outProtocolSvcId) {
-    pubsub_tcp_admin_t *psa = handle;
-    L_DEBUG("[PSA_TCP] pubsub_tcpAdmin_matchPublisher");
-    celix_status_t status = CELIX_SUCCESS;
-    double score = pubsubEndpoint_matchPublisher(psa->ctx, svcRequesterBndId, svcFilter->filterStr, PUBSUB_TCP_ADMIN_TYPE,
-                                               psa->qosSampleScore, psa->qosControlScore, psa->defaultScore, true,
-                                               topicProperties, outSerializerSvcId, outProtocolSvcId);
-    *outScore = score;
-
-    return status;
-}
-
-celix_status_t
-pubsub_tcpAdmin_matchSubscriber(void *handle, long svcProviderBndId, const celix_properties_t *svcProperties,
-                                celix_properties_t **topicProperties, double *outScore, long *outSerializerSvcId,
-                                long *outProtocolSvcId) {
-    pubsub_tcp_admin_t *psa = handle;
-    L_DEBUG("[PSA_TCP] pubsub_tcpAdmin_matchSubscriber");
-    celix_status_t status = CELIX_SUCCESS;
-    double score = pubsubEndpoint_matchSubscriber(psa->ctx, svcProviderBndId, svcProperties, PUBSUB_TCP_ADMIN_TYPE,
-                                                psa->qosSampleScore, psa->qosControlScore, psa->defaultScore, true,
-                                                topicProperties, outSerializerSvcId, outProtocolSvcId);
-    if (outScore != NULL) {
-        *outScore = score;
-    }
-    return status;
-}
-
-celix_status_t
-pubsub_tcpAdmin_matchDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint, bool *outMatch) {
-    pubsub_tcp_admin_t *psa = handle;
-    L_DEBUG("[PSA_TCP] pubsub_tcpAdmin_matchEndpoint");
-    celix_status_t status = CELIX_SUCCESS;
-    bool match = pubsubEndpoint_match(psa->ctx, psa->log, endpoint, PUBSUB_TCP_ADMIN_TYPE, true, NULL, NULL);
-    if (outMatch != NULL) {
-        *outMatch = match;
-    }
-    return status;
-}
-
-celix_status_t pubsub_tcpAdmin_setupTopicSender(void *handle, const char *scope, const char *topic,
-                                                const celix_properties_t *topicProperties, long serializerSvcId,
-                                                long protocolSvcId, celix_properties_t **outPublisherEndpoint) {
-    pubsub_tcp_admin_t *psa = handle;
-    celix_status_t status = CELIX_SUCCESS;
-
-    //1) Create TopicSender
-    //2) Store TopicSender
-    //3) Connect existing endpoints
-    //4) set outPublisherEndpoint
-
-    celix_properties_t *newEndpoint = NULL;
-    char *key = pubsubEndpoint_createScopeTopicKey(scope, topic);
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    celixThreadMutex_lock(&psa->protocols.mutex);
-    celixThreadMutex_lock(&psa->topicSenders.mutex);
-    pubsub_tcp_topic_sender_t *sender = hashMap_get(psa->topicSenders.map, key);
-    if (sender == NULL) {
-        psa_tcp_serializer_entry_t *serEntry = hashMap_get(psa->serializers.map, (void *) serializerSvcId);
-        psa_tcp_protocol_entry_t *protEntry = hashMap_get(psa->protocols.map, (void *) protocolSvcId);
-        if (serEntry != NULL && protEntry != NULL) {
-            sender = pubsub_tcpTopicSender_create(psa->ctx, psa->log, scope, topic, topicProperties,
-                                                  &psa->endpointStore, serializerSvcId, serEntry->svc, protocolSvcId,
-                                                  protEntry->svc);
-        }
-        if (sender != NULL) {
-            const char *psaType = PUBSUB_TCP_ADMIN_TYPE;
-            const char *serType = serEntry->serType;
-            const char *protType = protEntry->protType;
-            newEndpoint = pubsubEndpoint_create(psa->fwUUID, scope, topic, PUBSUB_PUBLISHER_ENDPOINT_TYPE, psaType, serType, protType, NULL);
-            celix_properties_set(newEndpoint, PUBSUB_TCP_URL_KEY, pubsub_tcpTopicSender_url(sender));
-
-            celix_properties_setBool(newEndpoint, PUBSUB_TCP_STATIC_CONFIGURED, pubsub_tcpTopicSender_isStatic(sender));
-            if (pubsub_tcpTopicSender_isPassive(sender)) {
-                celix_properties_set(newEndpoint, PUBSUB_ENDPOINT_VISIBILITY, PUBSUB_ENDPOINT_LOCAL_VISIBILITY);
-            } else {
-                celix_properties_set(newEndpoint, PUBSUB_ENDPOINT_VISIBILITY, PUBSUB_ENDPOINT_SYSTEM_VISIBILITY);
-            }
-            //if available also set container name
-            const char *cn = celix_bundleContext_getProperty(psa->ctx, "CELIX_CONTAINER_NAME", NULL);
-            if (cn != NULL)
-              celix_properties_set(newEndpoint, "container_name", cn);
-            hashMap_put(psa->topicSenders.map, key, sender);
-        } else {
-            L_ERROR("[PSA TCP] Error creating a TopicSender");
-            free(key);
-        }
-    } else {
-        free(key);
-        L_ERROR("[PSA_TCP] Cannot setup already existing TopicSender for scope/topic %s/%s!", scope, topic);
-    }
-    celixThreadMutex_unlock(&psa->topicSenders.mutex);
-    celixThreadMutex_unlock(&psa->protocols.mutex);
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-
-    if (newEndpoint != NULL && outPublisherEndpoint != NULL) {
-        *outPublisherEndpoint = newEndpoint;
-    }
-
-    return status;
-}
-
-celix_status_t pubsub_tcpAdmin_teardownTopicSender(void *handle, const char *scope, const char *topic) {
-    pubsub_tcp_admin_t *psa = handle;
-    celix_status_t status = CELIX_SUCCESS;
-
-    //1) Find and remove TopicSender from map
-    //2) destroy topic sender
-
-    char *key = pubsubEndpoint_createScopeTopicKey(scope, topic);
-    celixThreadMutex_lock(&psa->topicSenders.mutex);
-    hash_map_entry_t *entry = hashMap_getEntry(psa->topicSenders.map, key);
-    if (entry != NULL) {
-        char *mapKey = hashMapEntry_getKey(entry);
-        pubsub_tcp_topic_sender_t *sender = hashMap_remove(psa->topicSenders.map, key);
-        free(mapKey);
-        pubsub_tcpTopicSender_destroy(sender);
-    } else {
-        L_ERROR("[PSA TCP] Cannot teardown TopicSender with scope/topic %s/%s. Does not exists",
-                scope == NULL ? "(null)" : scope,
-                topic);
-    }
-    celixThreadMutex_unlock(&psa->topicSenders.mutex);
-    free(key);
-
-    return status;
-}
-
-celix_status_t pubsub_tcpAdmin_setupTopicReceiver(void *handle, const char *scope, const char *topic,
-                                                  const celix_properties_t *topicProperties, long serializerSvcId,
-                                                  long protocolSvcId, celix_properties_t **outSubscriberEndpoint) {
-    pubsub_tcp_admin_t *psa = handle;
-
-    celix_properties_t *newEndpoint = NULL;
-
-    char *key = pubsubEndpoint_createScopeTopicKey(scope, topic);
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    celixThreadMutex_lock(&psa->protocols.mutex);
-    celixThreadMutex_lock(&psa->topicReceivers.mutex);
-    pubsub_tcp_topic_receiver_t *receiver = hashMap_get(psa->topicReceivers.map, key);
-    if (receiver == NULL) {
-        psa_tcp_serializer_entry_t *serEntry = hashMap_get(psa->serializers.map, (void *) serializerSvcId);
-        psa_tcp_protocol_entry_t *protEntry = hashMap_get(psa->protocols.map, (void *) protocolSvcId);
-        if (serEntry != NULL && protEntry != NULL) {
-            receiver = pubsub_tcpTopicReceiver_create(psa->ctx, psa->log, scope, topic, topicProperties,
-                                                      &psa->endpointStore, serializerSvcId, serEntry->svc,
-                                                      protocolSvcId, protEntry->svc);
-        } else {
-            L_ERROR("[PSA_TCP] Cannot find serializer or protocol for TopicSender %s/%s", scope == NULL ? "(null)" : scope, topic);
-        }
-        if (receiver != NULL) {
-            const char *psaType = PUBSUB_TCP_ADMIN_TYPE;
-            const char *serType = serEntry->serType;
-            const char *protType = protEntry->protType;
-            newEndpoint = pubsubEndpoint_create(psa->fwUUID, scope, topic,
-                                                PUBSUB_SUBSCRIBER_ENDPOINT_TYPE, psaType, serType, protType, NULL);
-            //if available also set container name
-            const char *cn = celix_bundleContext_getProperty(psa->ctx, "CELIX_CONTAINER_NAME", NULL);
-            if (cn != NULL) {
-                celix_properties_set(newEndpoint, "container_name", cn);
-            }
-            hashMap_put(psa->topicReceivers.map, key, receiver);
-        } else {
-            L_ERROR("[PSA TCP] Error creating a TopicReceiver.");
-            free(key);
-        }
-    } else {
-        free(key);
-        L_ERROR("[PSA_TCP] Cannot setup already existing TopicReceiver for scope/topic %s/%s!",
-                scope == NULL ? "(null)" : scope,
-                topic);
-    }
-    celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-    celixThreadMutex_unlock(&psa->protocols.mutex);
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-
-    if (receiver != NULL && newEndpoint != NULL) {
-        celixThreadMutex_lock(&psa->discoveredEndpoints.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(psa->discoveredEndpoints.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            celix_properties_t *endpoint = hashMapIterator_nextValue(&iter);
-            if (pubsub_tcpAdmin_endpointIsPublisher(endpoint) && pubsubEndpoint_matchWithTopicAndScope(endpoint, topic, scope)) {
-                pubsub_tcpAdmin_connectEndpointToReceiver(psa, receiver, endpoint);
-            }
-        }
-        celixThreadMutex_unlock(&psa->discoveredEndpoints.mutex);
-    }
-
-    if (newEndpoint != NULL && outSubscriberEndpoint != NULL) {
-        *outSubscriberEndpoint = newEndpoint;
-    }
-
-    celix_status_t status = CELIX_SUCCESS;
-    return status;
-}
-
-celix_status_t pubsub_tcpAdmin_teardownTopicReceiver(void *handle, const char *scope, const char *topic) {
-    pubsub_tcp_admin_t *psa = handle;
-
-    char *key = pubsubEndpoint_createScopeTopicKey(scope, topic);
-    celixThreadMutex_lock(&psa->topicReceivers.mutex);
-    hash_map_entry_t *entry = hashMap_getEntry(psa->topicReceivers.map, key);
-    free(key);
-    if (entry != NULL) {
-        char *receiverKey = hashMapEntry_getKey(entry);
-        pubsub_tcp_topic_receiver_t *receiver = hashMapEntry_getValue(entry);
-        hashMap_remove(psa->topicReceivers.map, receiverKey);
-
-        free(receiverKey);
-        pubsub_tcpTopicReceiver_destroy(receiver);
-    }
-    celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-
-    celix_status_t status = CELIX_SUCCESS;
-    return status;
-}
-
-static celix_status_t
-pubsub_tcpAdmin_connectEndpointToReceiver(pubsub_tcp_admin_t *psa, pubsub_tcp_topic_receiver_t *receiver,
-                                          const celix_properties_t *endpoint) {
-    //note can be called with discoveredEndpoint.mutex lock
-    celix_status_t status = CELIX_SUCCESS;
-
-    const char *url = celix_properties_get(endpoint, PUBSUB_TCP_URL_KEY, NULL);
-
-    if (url == NULL) {
-        const char *admin = celix_properties_get(endpoint, PUBSUB_ENDPOINT_ADMIN_TYPE, NULL);
-        const char *type = celix_properties_get(endpoint, PUBSUB_ENDPOINT_TYPE, NULL);
-        L_WARN("[PSA TCP] Error got endpoint without a tcp url (admin: %s, type: %s)", admin, type);
-        status = CELIX_BUNDLE_EXCEPTION;
-    } else {
-        pubsub_tcpTopicReceiver_connectTo(receiver, url);
-    }
-
-    return status;
-}
-
-celix_status_t pubsub_tcpAdmin_addDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint) {
-    pubsub_tcp_admin_t *psa = handle;
-
-    if (pubsub_tcpAdmin_endpointIsPublisher(endpoint)) {
-        celixThreadMutex_lock(&psa->topicReceivers.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(psa->topicReceivers.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            pubsub_tcp_topic_receiver_t *receiver = hashMapIterator_nextValue(&iter);
-            if (pubsubEndpoint_matchWithTopicAndScope(endpoint, pubsub_tcpTopicReceiver_topic(receiver), pubsub_tcpTopicReceiver_scope(receiver))) {
-                pubsub_tcpAdmin_connectEndpointToReceiver(psa, receiver, endpoint);
-            }
-        }
-        celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-    }
-
-    celixThreadMutex_lock(&psa->discoveredEndpoints.mutex);
-    celix_properties_t *cpy = celix_properties_copy(endpoint);
-    const char *uuid = celix_properties_get(cpy, PUBSUB_ENDPOINT_UUID, NULL);
-    hashMap_put(psa->discoveredEndpoints.map, (void *) uuid, cpy);
-    celixThreadMutex_unlock(&psa->discoveredEndpoints.mutex);
-
-    celix_status_t status = CELIX_SUCCESS;
-    return status;
-}
-
-static celix_status_t
-pubsub_tcpAdmin_disconnectEndpointFromReceiver(pubsub_tcp_admin_t *psa, pubsub_tcp_topic_receiver_t *receiver,
-                                               const celix_properties_t *endpoint) {
-    //note can be called with discoveredEndpoint.mutex lock
-    celix_status_t status = CELIX_SUCCESS;
-
-    const char *url = celix_properties_get(endpoint, PUBSUB_TCP_URL_KEY, NULL);
-
-    if (url == NULL) {
-        L_WARN("[PSA TCP] Error got endpoint without tcp url");
-        status = CELIX_BUNDLE_EXCEPTION;
-    } else {
-        pubsub_tcpTopicReceiver_disconnectFrom(receiver, url);
-    }
-
-    return status;
-}
-
-celix_status_t pubsub_tcpAdmin_removeDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint) {
-    pubsub_tcp_admin_t *psa = handle;
-
-    if (pubsub_tcpAdmin_endpointIsPublisher(endpoint)) {
-        celixThreadMutex_lock(&psa->topicReceivers.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(psa->topicReceivers.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            pubsub_tcp_topic_receiver_t *receiver = hashMapIterator_nextValue(&iter);
-            pubsub_tcpAdmin_disconnectEndpointFromReceiver(psa, receiver, endpoint);
-        }
-        celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-    }
-
-    celixThreadMutex_lock(&psa->discoveredEndpoints.mutex);
-    const char *uuid = celix_properties_get(endpoint, PUBSUB_ENDPOINT_UUID, NULL);
-    celix_properties_t *found = hashMap_remove(psa->discoveredEndpoints.map, (void *) uuid);
-    celixThreadMutex_unlock(&psa->discoveredEndpoints.mutex);
-
-    if (found != NULL) {
-        celix_properties_destroy(found);
-    }
-
-    celix_status_t status = CELIX_SUCCESS;
-    return status;
-}
-
-bool pubsub_tcpAdmin_executeCommand(void *handle, const char *commandLine __attribute__((unused)), FILE *out,
-                                    FILE *errStream __attribute__((unused))) {
-    pubsub_tcp_admin_t *psa = handle;
-    celix_status_t status = CELIX_SUCCESS;
-    char *line = celix_utils_strdup(commandLine);
-    char *token = line;
-    strtok_r(line, " ", &token); //first token is command name
-    strtok_r(NULL, " ", &token); //second token is sub command
-
-    if (celix_utils_stringEquals(token, "nr_of_receivers")) {
-        celixThreadMutex_lock(&psa->topicReceivers.mutex);
-        fprintf(out,"%i\n", hashMap_size(psa->topicReceivers.map));
-        celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-    }
-    if (celix_utils_stringEquals(token, "nr_of_senders")) {
-        celixThreadMutex_lock(&psa->topicSenders.mutex);
-        fprintf(out, "%i\n", hashMap_size(psa->topicSenders.map));
-        celixThreadMutex_unlock(&psa->topicSenders.mutex);
-    }
-
-    fprintf(out, "\n");
-    fprintf(out, "Topic Senders:\n");
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    celixThreadMutex_lock(&psa->protocols.mutex);
-    celixThreadMutex_lock(&psa->topicSenders.mutex);
-    hash_map_iterator_t iter = hashMapIterator_construct(psa->topicSenders.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        pubsub_tcp_topic_sender_t *sender = hashMapIterator_nextValue(&iter);
-        long serSvcId = pubsub_tcpTopicSender_serializerSvcId(sender);
-        psa_tcp_serializer_entry_t *serEntry = hashMap_get(psa->serializers.map, (void *) serSvcId);
-        long protSvcId = pubsub_tcpTopicSender_protocolSvcId(sender);
-        psa_tcp_protocol_entry_t *protEntry = hashMap_get(psa->protocols.map, (void *) protSvcId);
-        const char *serType = serEntry == NULL ? "!Error!" : serEntry->serType;
-        const char *protType = protEntry == NULL ? "!Error!" : protEntry->protType;
-        const char *scope = pubsub_tcpTopicSender_scope(sender);
-        const char *topic = pubsub_tcpTopicSender_topic(sender);
-        const char *url = pubsub_tcpTopicSender_url(sender);
-        const char *isPassive = pubsub_tcpTopicSender_isPassive(sender) ? " (passive)" : "";
-        const char *postUrl = pubsub_tcpTopicSender_isStatic(sender) ? " (static)" : "";
-        fprintf(out, "|- Topic Sender %s/%s\n", scope == NULL ? "(null)" : scope, topic);
-        fprintf(out, "   |- serializer type = %s\n", serType);
-        fprintf(out, "   |- protocol type = %s\n", protType);
-        fprintf(out, "   |- url            = %s%s%s\n", url, postUrl, isPassive);
-    }
-    celixThreadMutex_unlock(&psa->topicSenders.mutex);
-    celixThreadMutex_unlock(&psa->protocols.mutex);
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-
-    fprintf(out, "\n");
-    fprintf(out, "\nTopic Receivers:\n");
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    celixThreadMutex_lock(&psa->protocols.mutex);
-    celixThreadMutex_lock(&psa->topicReceivers.mutex);
-    iter = hashMapIterator_construct(psa->topicReceivers.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        pubsub_tcp_topic_receiver_t *receiver = hashMapIterator_nextValue(&iter);
-        long serSvcId = pubsub_tcpTopicReceiver_serializerSvcId(receiver);
-        psa_tcp_serializer_entry_t *serEntry = hashMap_get(psa->serializers.map, (void *) serSvcId);
-        long protSvcId = pubsub_tcpTopicReceiver_protocolSvcId(receiver);
-        psa_tcp_protocol_entry_t *protEntry = hashMap_get(psa->protocols.map, (void *) protSvcId);
-        const char *serType = serEntry == NULL ? "!Error!" : serEntry->serType;
-        const char *protType = protEntry == NULL ? "!Error!" : protEntry->protType;
-        const char *scope = pubsub_tcpTopicReceiver_scope(receiver);
-        const char *topic = pubsub_tcpTopicReceiver_topic(receiver);
-
-        celix_array_list_t *connected = celix_arrayList_create();
-        celix_array_list_t *unconnected = celix_arrayList_create();
-        pubsub_tcpTopicReceiver_listConnections(receiver, connected, unconnected);
-
-        fprintf(out, "|- Topic Receiver %s/%s\n", scope == NULL ? "(null)" : scope, topic);
-        fprintf(out, "   |- serializer type = %s\n", serType);
-        fprintf(out, "   |- protocol type = %s\n", protType);
-        for (int i = 0; i < celix_arrayList_size(connected); ++i) {
-            char *url = celix_arrayList_get(connected, i);
-            fprintf(out, "   |- connected url   = %s\n", url);
-            free(url);
-        }
-        for (int i = 0; i < celix_arrayList_size(unconnected); ++i) {
-            char *url = celix_arrayList_get(unconnected, i);
-            fprintf(out, "   |- unconnected url = %s\n", url);
-            free(url);
-        }
-        celix_arrayList_destroy(connected);
-        celix_arrayList_destroy(unconnected);
-    }
-    celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-    celixThreadMutex_unlock(&psa->protocols.mutex);
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-    fprintf(out, "\n");
-
-    return status;
-}
-
-pubsub_admin_metrics_t *pubsub_tcpAdmin_metrics(void *handle) {
-    pubsub_tcp_admin_t *psa = handle;
-    pubsub_admin_metrics_t *result = calloc(1, sizeof(*result));
-    snprintf(result->psaType, PUBSUB_AMDIN_METRICS_NAME_MAX, "%s", PUBSUB_TCP_ADMIN_TYPE);
-    result->senders = celix_arrayList_create();
-    result->receivers = celix_arrayList_create();
-
-    celixThreadMutex_lock(&psa->topicSenders.mutex);
-    hash_map_iterator_t iter = hashMapIterator_construct(psa->topicSenders.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        pubsub_tcp_topic_sender_t *sender = hashMapIterator_nextValue(&iter);
-        pubsub_admin_sender_metrics_t *metrics = pubsub_tcpTopicSender_metrics(sender);
-        celix_arrayList_add(result->senders, metrics);
-    }
-    celixThreadMutex_unlock(&psa->topicSenders.mutex);
-
-    celixThreadMutex_lock(&psa->topicReceivers.mutex);
-    iter = hashMapIterator_construct(psa->topicReceivers.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        pubsub_tcp_topic_receiver_t *receiver = hashMapIterator_nextValue(&iter);
-        pubsub_admin_receiver_metrics_t *metrics = pubsub_tcpTopicReceiver_metrics(receiver);
-        celix_arrayList_add(result->receivers, metrics);
-    }
-    celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-
-    return result;
-}
diff --git a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_admin.h b/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_admin.h
deleted file mode 100644
index b6286c8..0000000
--- a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_admin.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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_PUBSUB_TCP_ADMIN_H
-#define CELIX_PUBSUB_TCP_ADMIN_H
-
-#include <pubsub_admin_metrics.h>
-#include "celix_api.h"
-#include "celix_log_helper.h"
-#include "pubsub_psa_tcp_constants.h"
-
-typedef struct pubsub_tcp_admin pubsub_tcp_admin_t;
-
-pubsub_tcp_admin_t *pubsub_tcpAdmin_create(celix_bundle_context_t *ctx, celix_log_helper_t *logHelper);
-void pubsub_tcpAdmin_destroy(pubsub_tcp_admin_t *psa);
-
-celix_status_t pubsub_tcpAdmin_matchPublisher(void *handle,
-                                              long svcRequesterBndId,
-                                              const celix_filter_t *svcFilter,
-                                              celix_properties_t **topicProperties,
-                                              double *score,
-                                              long *serializerSvcId,
-                                              long *protocolSvcId);
-celix_status_t pubsub_tcpAdmin_matchSubscriber(void *handle,
-                                               long svcProviderBndId,
-                                               const celix_properties_t *svcProperties,
-                                               celix_properties_t **topicProperties,
-                                               double *score,
-                                               long *serializerSvcId,
-                                               long *protocolSvcId);
-celix_status_t pubsub_tcpAdmin_matchDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint, bool *match);
-
-celix_status_t pubsub_tcpAdmin_setupTopicSender(void *handle,
-                                                const char *scope,
-                                                const char *topic,
-                                                const celix_properties_t *topicProperties,
-                                                long serializerSvcId,
-                                                long protocolSvcId,
-                                                celix_properties_t **publisherEndpoint);
-celix_status_t pubsub_tcpAdmin_teardownTopicSender(void *handle, const char *scope, const char *topic);
-
-celix_status_t pubsub_tcpAdmin_setupTopicReceiver(void *handle,
-                                                  const char *scope,
-                                                  const char *topic,
-                                                  const celix_properties_t *topicProperties,
-                                                  long serializerSvcId,
-                                                  long protocolSvcId,
-                                                  celix_properties_t **subscriberEndpoint);
-celix_status_t pubsub_tcpAdmin_teardownTopicReceiver(void *handle, const char *scope, const char *topic);
-
-celix_status_t pubsub_tcpAdmin_addDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint);
-celix_status_t pubsub_tcpAdmin_removeDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint);
-
-void pubsub_tcpAdmin_addSerializerSvc(void *handle, void *svc, const celix_properties_t *props);
-void pubsub_tcpAdmin_removeSerializerSvc(void *handle, void *svc, const celix_properties_t *props);
-
-void pubsub_tcpAdmin_addProtocolSvc(void *handle, void *svc, const celix_properties_t *props);
-void pubsub_tcpAdmin_removeProtocolSvc(void *handle, void *svc, const celix_properties_t *props);
-bool pubsub_tcpAdmin_executeCommand(void *handle, const char *commandLine, FILE *outStream, FILE *errStream);
-
-pubsub_admin_metrics_t *pubsub_tcpAdmin_metrics(void *handle);
-
-#endif //CELIX_PUBSUB_TCP_ADMIN_H
-
diff --git a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_common.c b/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_common.c
deleted file mode 100644
index d8f05f7..0000000
--- a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_common.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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 <stdio.h>
-#include <string.h>
-#include "pubsub_tcp_common.h"
-
-
-bool psa_tcp_isPassive(const char* buffer) {
-    bool isPassive = false;
-    // Parse Properties
-    if (buffer != NULL) {
-        char buf[32];
-        snprintf(buf, 32, "%s", buffer);
-        char *trimmed = utils_stringTrim(buf);
-        if (strncasecmp("true", trimmed, strlen("true")) == 0) {
-            isPassive = true;
-        } else if (strncasecmp("false", trimmed, strlen("false")) == 0) {
-            isPassive = false;
-        }
-    }
-    return isPassive;
-}
diff --git a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_common.h b/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_common.h
deleted file mode 100644
index 9ea31db..0000000
--- a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_common.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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_PUBSUB_TCP_COMMON_H
-#define CELIX_PUBSUB_TCP_COMMON_H
-
-#include <utils.h>
-#include <hash_map.h>
-
-typedef struct pubsub_tcp_endPointStore {
-    celix_thread_mutex_t mutex;
-    hash_map_t *map;
-} pubsub_tcp_endPointStore_t;
-
-bool psa_tcp_isPassive(const char* buffer);
-
-#endif //CELIX_PUBSUB_TCP_COMMON_H
diff --git a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_handler.c b/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_handler.c
deleted file mode 100644
index 262940b..0000000
--- a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_handler.c
+++ /dev/null
@@ -1,1448 +0,0 @@
-/*
- * 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.
- */
-/*
- * pubsub_tcp_handler.c
- *
- *  \date       July 18, 2019
- *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright  Apache License, Version 2.0
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <array_list.h>
-#include <pthread.h>
-#if defined(__APPLE__)
-#include <sys/types.h>
-#include <sys/event.h>
-#include <sys/time.h>
-#else
-#include <sys/epoll.h>
-#endif
-#include <limits.h>
-#include <fcntl.h>
-#include <arpa/inet.h>
-#include <netinet/tcp.h>
-#include "hash_map.h"
-#include "utils.h"
-#include "pubsub_tcp_handler.h"
-
-#define MAX_EVENTS   64
-#define MAX_DEFAULT_BUFFER_SIZE 4u
-
-#if defined(__APPLE__)
-#ifndef MSG_NOSIGNAL
-#define MSG_NOSIGNAL (0)
-#endif
-#endif
-
-#define L_DEBUG(...) \
-    celix_logHelper_log(handle->logHelper, CELIX_LOG_LEVEL_DEBUG, __VA_ARGS__)
-#define L_INFO(...) \
-    celix_logHelper_log(handle->logHelper, CELIX_LOG_LEVEL_INFO, __VA_ARGS__)
-#define L_WARN(...) \
-    celix_logHelper_log(handle->logHelper, CELIX_LOG_LEVEL_WARNING, __VA_ARGS__)
-#define L_ERROR(...) \
-    celix_logHelper_log(handle->logHelper, CELIX_LOG_LEVEL_ERROR, __VA_ARGS__)
-
-//
-// Entry administration
-//
-typedef struct psa_tcp_connection_entry {
-    char *interface_url;
-    char *url;
-    int fd;
-    struct sockaddr_in addr;
-    socklen_t len;
-    bool connected;
-    bool headerError;
-    pubsub_protocol_message_t header;
-    size_t maxMsgSize;
-    size_t readHeaderSize;
-    size_t readHeaderBufferSize; // Size of headerBuffer
-    void *readHeaderBuffer;
-    size_t writeHeaderBufferSize; // Size of headerBuffer
-    void *writeHeaderBuffer;
-    size_t readFooterSize;
-    size_t readFooterBufferSize;
-    void *readFooterBuffer;
-    size_t writeFooterBufferSize;
-    void *writeFooterBuffer;
-    size_t bufferSize;
-    void *buffer;
-    size_t readMetaBufferSize;
-    void *readMetaBuffer;
-    size_t writeMetaBufferSize;
-    void *writeMetaBuffer;
-    unsigned int retryCount;
-    celix_thread_mutex_t writeMutex;
-    struct msghdr readMsg;
-} psa_tcp_connection_entry_t;
-
-//
-// Handle administration
-//
-struct pubsub_tcpHandler {
-    celix_thread_rwlock_t dbLock;
-    unsigned int timeout;
-    hash_map_t *connection_url_map;
-    hash_map_t *connection_fd_map;
-    hash_map_t *interface_url_map;
-    hash_map_t *interface_fd_map;
-    int efd;
-    pubsub_tcpHandler_receiverConnectMessage_callback_t receiverConnectMessageCallback;
-    pubsub_tcpHandler_receiverConnectMessage_callback_t receiverDisconnectMessageCallback;
-    void *receiverConnectPayload;
-    pubsub_tcpHandler_acceptConnectMessage_callback_t acceptConnectMessageCallback;
-    pubsub_tcpHandler_acceptConnectMessage_callback_t acceptDisconnectMessageCallback;
-    void *acceptConnectPayload;
-    pubsub_tcpHandler_processMessage_callback_t processMessageCallback;
-    void *processMessagePayload;
-    celix_log_helper_t *logHelper;
-    pubsub_protocol_service_t *protocol;
-    unsigned int bufferSize;
-    unsigned int maxMsgSize;
-    unsigned int maxSendRetryCount;
-    unsigned int maxRcvRetryCount;
-    double sendTimeout;
-    double rcvTimeout;
-    celix_thread_t thread;
-    bool running;
-    bool enableReceiveEvent;
-};
-
-static inline int pubsub_tcpHandler_closeConnectionEntry(pubsub_tcpHandler_t *handle, psa_tcp_connection_entry_t *entry, bool lock);
-static inline int pubsub_tcpHandler_closeInterfaceEntry(pubsub_tcpHandler_t *handle, psa_tcp_connection_entry_t *entry);
-static inline int pubsub_tcpHandler_makeNonBlocking(pubsub_tcpHandler_t *handle, int fd);
-static inline psa_tcp_connection_entry_t* pubsub_tcpHandler_createEntry(pubsub_tcpHandler_t *handle, int fd, char *url, char *interface_url, struct sockaddr_in *addr);
-static inline void pubsub_tcpHandler_freeEntry(psa_tcp_connection_entry_t *entry);
-static inline void pubsub_tcpHandler_releaseEntryBuffer(pubsub_tcpHandler_t *handle, int fd, unsigned int index);
-static inline long int pubsub_tcpHandler_getMsgSize(psa_tcp_connection_entry_t *entry);
-static inline void pubsub_tcpHandler_ensureReadBufferCapacity(pubsub_tcpHandler_t *handle, psa_tcp_connection_entry_t *entry);
-static inline bool pubsub_tcpHandler_readHeader(pubsub_tcpHandler_t *handle, int fd, psa_tcp_connection_entry_t *entry, long int* msgSize);
-static inline void pubsub_tcpHandler_decodePayload(pubsub_tcpHandler_t *handle, psa_tcp_connection_entry_t *entry);
-static inline long int pubsub_tcpHandler_readPayload(pubsub_tcpHandler_t *handle, int fd, psa_tcp_connection_entry_t *entry);
-static inline void pubsub_tcpHandler_connectionHandler(pubsub_tcpHandler_t *handle, int fd);
-static inline void pubsub_tcpHandler_handler(pubsub_tcpHandler_t *handle);
-static void *pubsub_tcpHandler_thread(void *data);
-
-
-
-//
-// Create a handle
-//
-pubsub_tcpHandler_t *pubsub_tcpHandler_create(pubsub_protocol_service_t *protocol, celix_log_helper_t *logHelper) {
-    pubsub_tcpHandler_t *handle = calloc(sizeof(*handle), 1);
-    if (handle != NULL) {
-#if defined(__APPLE__)
-        handle->efd = kqueue();
-#else
-        handle->efd = epoll_create1(0);
-#endif
-        handle->connection_url_map = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-        handle->connection_fd_map = hashMap_create(NULL, NULL, NULL, NULL);
-        handle->interface_url_map = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-        handle->interface_fd_map = hashMap_create(NULL, NULL, NULL, NULL);
-        handle->timeout = 2000; // default 2 sec
-        handle->logHelper = logHelper;
-        handle->protocol = protocol;
-        handle->bufferSize = MAX_DEFAULT_BUFFER_SIZE;
-        celixThreadRwlock_create(&handle->dbLock, 0);
-        handle->running = true;
-        celixThread_create(&handle->thread, NULL, pubsub_tcpHandler_thread, handle);
-        // signal(SIGPIPE, SIG_IGN);
-    }
-    return handle;
-}
-
-//
-// Destroys the handle
-//
-void pubsub_tcpHandler_destroy(pubsub_tcpHandler_t *handle) {
-    if (handle != NULL) {
-        celixThreadRwlock_readLock(&handle->dbLock);
-        bool running = handle->running;
-        celixThreadRwlock_unlock(&handle->dbLock);
-        if (running) {
-            celixThreadRwlock_writeLock(&handle->dbLock);
-            handle->running = false;
-            celixThreadRwlock_unlock(&handle->dbLock);
-            celixThread_join(handle->thread, NULL);
-        }
-        celixThreadRwlock_writeLock(&handle->dbLock);
-        hash_map_iterator_t interface_iter = hashMapIterator_construct(handle->interface_url_map);
-        while (hashMapIterator_hasNext(&interface_iter)) {
-            psa_tcp_connection_entry_t *entry = hashMapIterator_nextValue(&interface_iter);
-            if (entry != NULL) {
-                pubsub_tcpHandler_closeInterfaceEntry(handle, entry);
-            }
-        }
-
-        hash_map_iterator_t connection_iter = hashMapIterator_construct(handle->connection_url_map);
-        while (hashMapIterator_hasNext(&connection_iter)) {
-            psa_tcp_connection_entry_t *entry = hashMapIterator_nextValue(&connection_iter);
-            if (entry != NULL) {
-                pubsub_tcpHandler_closeConnectionEntry(handle, entry, true);
-            }
-        }
-        if (handle->efd >= 0) close(handle->efd);
-        hashMap_destroy(handle->connection_url_map, false, false);
-        hashMap_destroy(handle->connection_fd_map, false, false);
-        hashMap_destroy(handle->interface_url_map, false, false);
-        hashMap_destroy(handle->interface_fd_map, false, false);
-        celixThreadRwlock_unlock(&handle->dbLock);
-        celixThreadRwlock_destroy(&handle->dbLock);
-        free(handle);
-    }
-}
-
-//
-// Open the socket using an url
-//
-int pubsub_tcpHandler_open(pubsub_tcpHandler_t *handle, char *url) {
-    int rc = 0;
-    celixThreadRwlock_readLock(&handle->dbLock);
-    pubsub_utils_url_t *url_info = pubsub_utils_url_parse(url);
-    int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-    if (rc >= 0) {
-        int setting = 1;
-        if (rc == 0) {
-            rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &setting, sizeof(setting));
-            if (rc != 0) {
-                close(fd);
-                L_ERROR("[TCP Socket] Error setsockopt(SO_REUSEADDR): %s\n", strerror(errno));
-            }
-        }
-        if (rc == 0) {
-            rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &setting, sizeof(setting));
-            if (rc != 0) {
-                close(fd);
-                L_ERROR("[TCP Socket] Error setsockopt(TCP_NODELAY): %s\n", strerror(errno));
-            }
-        } else {
-            L_ERROR("[TCP Socket] Error creating socket: %s\n", strerror(errno));
-        }
-        if (rc == 0 && handle->sendTimeout != 0.0) {
-            struct timeval tv;
-            tv.tv_sec = (long int) handle->sendTimeout;
-            tv.tv_usec = (long int) ((handle->sendTimeout - tv.tv_sec) * 1000000.0);
-            rc = setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
-            if (rc != 0) {
-                L_ERROR("[TCP Socket] Error setsockopt (SO_SNDTIMEO) to set send timeout: %s", strerror(errno));
-            }
-        }
-        if (rc == 0 && handle->rcvTimeout != 0.0) {
-            struct timeval tv;
-            tv.tv_sec = (long int) handle->rcvTimeout;
-            tv.tv_usec = (long int) ((handle->rcvTimeout - tv.tv_sec) * 1000000.0);
-            rc = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
-            if (rc != 0) {
-                L_ERROR("[TCP Socket] Error setsockopt (SO_RCVTIMEO) to set send timeout: %s", strerror(errno));
-            }
-        }
-        struct sockaddr_in *addr = pubsub_utils_url_getInAddr(url_info->hostname, url_info->port_nr);
-        if (addr) {
-            rc = bind(fd, (struct sockaddr *) addr, sizeof(struct sockaddr));
-            if (rc != 0) {
-                close(fd);
-                L_ERROR("[TCP Socket] Error bind: %s\n", strerror(errno));
-            }
-            free(addr);
-        }
-    }
-    pubsub_utils_url_free(url_info);
-    celixThreadRwlock_unlock(&handle->dbLock);
-    return (!rc) ? fd : rc;
-}
-
-//
-// Closes the discriptor with it's connection/interfaces (receiver/sender)
-//
-int pubsub_tcpHandler_close(pubsub_tcpHandler_t *handle, int fd) {
-    int rc = 0;
-    if (handle != NULL) {
-        psa_tcp_connection_entry_t *entry = NULL;
-        celixThreadRwlock_writeLock(&handle->dbLock);
-        entry = hashMap_get(handle->interface_fd_map, (void *) (intptr_t) fd);
-        if (entry) {
-            entry = hashMap_remove(handle->interface_url_map, (void *) (intptr_t) entry->url);
-            rc = pubsub_tcpHandler_closeInterfaceEntry(handle, entry);
-            entry = NULL;
-        }
-        entry = hashMap_get(handle->connection_fd_map, (void *) (intptr_t) fd);
-        if (entry) {
-            entry = hashMap_remove(handle->connection_url_map, (void *) (intptr_t) entry->url);
-            rc = pubsub_tcpHandler_closeConnectionEntry(handle, entry, false);
-            entry = NULL;
-        }
-        celixThreadRwlock_unlock(&handle->dbLock);
-    }
-    return rc;
-}
-
-//
-// Create connection/interface entry
-//
-static inline psa_tcp_connection_entry_t *
-pubsub_tcpHandler_createEntry(pubsub_tcpHandler_t *handle, int fd, char *url, char *interface_url,
-                              struct sockaddr_in *addr) {
-    psa_tcp_connection_entry_t *entry = NULL;
-    if (fd >= 0) {
-        entry = calloc(sizeof(psa_tcp_connection_entry_t), 1);
-        entry->fd = fd;
-        celixThreadMutex_create(&entry->writeMutex, NULL);
-        if (url) {
-            entry->url = strndup(url, 1024 * 1024);
-        }
-        if (interface_url) {
-            entry->interface_url = strndup(interface_url, 1024 * 1024);
-        } else {
-            if (url) {
-                entry->interface_url = strndup(url, 1024 * 1024);
-            }
-        }
-        if (addr) {
-            entry->addr = *addr;
-        }
-        entry->len = sizeof(struct sockaddr_in);
-        size_t headerSize = 0;
-        size_t footerSize = 0;
-        handle->protocol->getHeaderSize(handle->protocol->handle, &headerSize);
-        handle->protocol->getFooterSize(handle->protocol->handle, &footerSize);
-        entry->readHeaderBufferSize = headerSize;
-        entry->writeHeaderBufferSize = headerSize;
-
-        entry->readFooterBufferSize = footerSize;
-        entry->writeFooterBufferSize = footerSize;
-        entry->bufferSize = MAX(handle->bufferSize, headerSize);
-        entry->connected = false;
-        unsigned minimalMsgSize = entry->writeHeaderBufferSize + entry->writeFooterBufferSize;
-        if ((minimalMsgSize > handle->maxMsgSize) && (handle->maxMsgSize)) {
-            L_ERROR("[TCP Socket] maxMsgSize (%d) < headerSize + FooterSize (%d): %s\n", handle->maxMsgSize, minimalMsgSize);
-        } else {
-            entry->maxMsgSize = (handle->maxMsgSize) ? handle->maxMsgSize : LONG_MAX;
-        }
-        entry->readHeaderBuffer = calloc(sizeof(char), headerSize);
-        entry->writeHeaderBuffer = calloc(sizeof(char), headerSize);
-        if (entry->readFooterBufferSize ) entry->readFooterBuffer = calloc(sizeof(char), entry->readFooterBufferSize );
-        if (entry->writeFooterBufferSize) entry->writeFooterBuffer = calloc(sizeof(char), entry->writeFooterBufferSize);
-        if (entry->bufferSize) entry->buffer = calloc(sizeof(char), entry->bufferSize);
-        memset(&entry->readMsg, 0x00, sizeof(struct msghdr));
-        entry->readMsg.msg_iov = calloc(sizeof(struct iovec), IOV_MAX);
-    }
-    return entry;
-}
-
-//
-// Free connection/interface entry
-//
-static inline void
-pubsub_tcpHandler_freeEntry(psa_tcp_connection_entry_t *entry) {
-    if (entry) {
-        free(entry->url);
-        free(entry->interface_url);
-        if (entry->fd >= 0) close(entry->fd);
-        free(entry->buffer);
-        free(entry->readHeaderBuffer);
-        free(entry->writeHeaderBuffer);
-        free(entry->readFooterBuffer);
-        free(entry->writeFooterBuffer);
-        free(entry->readMetaBuffer);
-        free(entry->writeMetaBuffer);
-        free(entry->readMsg.msg_iov);
-        celixThreadMutex_destroy(&entry->writeMutex);
-        free(entry);
-    }
-}
-
-//
-// Releases the Buffer
-//
-static inline void
-pubsub_tcpHandler_releaseEntryBuffer(pubsub_tcpHandler_t *handle, int fd, unsigned int index __attribute__((unused))) {
-    psa_tcp_connection_entry_t *entry = hashMap_get(handle->connection_fd_map, (void *) (intptr_t) fd);
-    if (entry != NULL) {
-        entry->buffer = NULL;
-        entry->bufferSize = 0;
-    }
-}
-
-//
-// Connect to url (receiver)
-//
-int pubsub_tcpHandler_connect(pubsub_tcpHandler_t *handle, char *url) {
-    int rc = 0;
-    psa_tcp_connection_entry_t *entry = hashMap_get(handle->connection_url_map, (void *) (intptr_t) url);
-    if (entry == NULL) {
-        pubsub_utils_url_t *url_info = pubsub_utils_url_parse(url);
-        int fd = pubsub_tcpHandler_open(handle, url_info->interface_url);
-        rc = fd;
-        // Connect to sender
-        struct sockaddr_in sin;
-        socklen_t len = sizeof(sin);
-        getsockname(fd, (struct sockaddr *) &sin, &len);
-        char *interface_url = pubsub_utils_url_get_url(&sin, NULL);
-        struct sockaddr_in *addr = pubsub_utils_url_getInAddr(url_info->hostname, url_info->port_nr);
-        if ((rc >= 0) && addr) {
-            rc = connect(fd, (struct sockaddr *) addr, sizeof(struct sockaddr));
-            if (rc < 0 && errno != EINPROGRESS) {
-                L_ERROR("[TCP Socket] Cannot connect to %s:%d: using %s err(%d): %s\n", url_info->hostname, url_info->port_nr, interface_url, errno, strerror(errno));
-                close(fd);
-            } else {
-                entry = pubsub_tcpHandler_createEntry(handle, fd, url, interface_url, &sin);
-            }
-            free(addr);
-        }
-        free(interface_url);
-        // Subscribe File Descriptor to epoll
-        if ((rc >= 0) && (entry)) {
-#if defined(__APPLE__)
-            struct kevent ev;
-            EV_SET (&ev, entry->fd, EVFILT_READ | EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, 0);
-            rc = kevent (handle->efd, &ev, 1, NULL, 0, NULL);
-#else
-            struct epoll_event event;
-            bzero(&event,  sizeof(struct epoll_event)); // zero the struct
-            event.events = EPOLLIN | EPOLLRDHUP | EPOLLERR;
-            event.data.fd = entry->fd;
-            rc = epoll_ctl(handle->efd, EPOLL_CTL_ADD, entry->fd, &event);
-#endif
-            if (rc < 0) {
-                pubsub_tcpHandler_freeEntry(entry);
-                L_ERROR("[TCP Socket] Cannot create poll event %s\n", strerror(errno));
-                entry = NULL;
-            }
-        }
-        if ((rc >= 0) && (entry)) {
-            celixThreadRwlock_writeLock(&handle->dbLock);
-            hashMap_put(handle->connection_url_map, entry->url, entry);
-            hashMap_put(handle->connection_fd_map, (void *) (intptr_t) entry->fd, entry);
-            celixThreadRwlock_unlock(&handle->dbLock);
-            pubsub_tcpHandler_connectionHandler(handle, fd);
-            L_INFO("[TCP Socket] Connect to %s using: %s\n", entry->url, entry->interface_url);
-        }
-        pubsub_utils_url_free(url_info);
-    }
-    return rc;
-}
-
-//
-// Disconnect from url
-//
-int pubsub_tcpHandler_disconnect(pubsub_tcpHandler_t *handle, char *url) {
-    int rc = 0;
-    if (handle != NULL) {
-        celixThreadRwlock_writeLock(&handle->dbLock);
-        psa_tcp_connection_entry_t *entry = NULL;
-        entry = hashMap_remove(handle->connection_url_map, url);
-        if (entry) {
-            pubsub_tcpHandler_closeConnectionEntry(handle, entry, false);
-        }
-        celixThreadRwlock_unlock(&handle->dbLock);
-    }
-    return rc;
-}
-
-// loses the connection entry (of receiver)
-//
-static inline int pubsub_tcpHandler_closeConnectionEntry(
-    pubsub_tcpHandler_t *handle, psa_tcp_connection_entry_t *entry, bool lock) {
-    int rc = 0;
-    if (handle != NULL && entry != NULL) {
-        fprintf(stdout, "[TCP Socket] Close connection to url: %s: \n", entry->url);
-        hashMap_remove(handle->connection_fd_map, (void *) (intptr_t) entry->fd);
-        if ((handle->efd >= 0)) {
-#if defined(__APPLE__)
-          struct kevent ev;
-          EV_SET (&ev, entry->fd, EVFILT_READ, EV_DELETE , 0, 0, 0);
-          rc = kevent (handle->efd, &ev, 1, NULL, 0, NULL);
-#else
-            struct epoll_event event;
-            bzero(&event, sizeof(struct epoll_event)); // zero the struct
-            rc = epoll_ctl(handle->efd, EPOLL_CTL_DEL, entry->fd, &event);
-#endif
-            if (rc < 0) {
-                L_ERROR("[PSA TCP] Error disconnecting %s\n", strerror(errno));
-            }
-        }
-        if (entry->fd >= 0) {
-            if (handle->receiverDisconnectMessageCallback)
-                handle->receiverDisconnectMessageCallback(handle->receiverConnectPayload, entry->url, lock);
-            if (handle->acceptConnectMessageCallback)
-                handle->acceptConnectMessageCallback(handle->acceptConnectPayload, entry->url);
-            pubsub_tcpHandler_freeEntry(entry);
-            entry = NULL;
-        }
-    }
-    return rc;
-}
-
-//
-// Closes the interface entry (of sender)
-//
-static inline int
-pubsub_tcpHandler_closeInterfaceEntry(pubsub_tcpHandler_t *handle,
-                                      psa_tcp_connection_entry_t *entry) {
-    int rc = 0;
-    if (handle != NULL && entry != NULL) {
-        L_INFO("[TCP Socket] Close interface url: %s: \n", entry->url);
-        hashMap_remove(handle->interface_fd_map, (void *) (intptr_t) entry->fd);
-        if ((handle->efd >= 0)) {
-#if defined(__APPLE__)
-            struct kevent ev;
-            EV_SET (&ev, entry->fd, EVFILT_READ, EV_DELETE , 0, 0, 0);
-            rc = kevent (handle->efd, &ev, 1, NULL, 0, NULL);
-#else
-            struct epoll_event event;
-            bzero(&event, sizeof(struct epoll_event)); // zero the struct
-            rc = epoll_ctl(handle->efd, EPOLL_CTL_DEL, entry->fd, &event);
-#endif
-            if (rc < 0) {
-                L_ERROR("[PSA TCP] Error disconnecting %s\n", strerror(errno));
-            }
-        }
-        if (entry->fd >= 0) {
-            pubsub_tcpHandler_freeEntry(entry);
-        }
-    }
-    return rc;
-}
-
-//
-// Make accept file descriptor non blocking
-//
-static inline int pubsub_tcpHandler_makeNonBlocking(pubsub_tcpHandler_t *handle, int fd) {
-    int rc = 0;
-    int flags = fcntl(fd, F_GETFL, 0);
-    if (flags == -1)
-        rc = flags;
-    else {
-        rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
-        if (rc < 0) {
-            L_ERROR("[TCP Socket] Cannot set to NON_BLOCKING: %s\n", strerror(errno));
-        }
-    }
-    return rc;
-}
-
-//
-// setup listening to interface (sender) using an url
-//
-int pubsub_tcpHandler_listen(pubsub_tcpHandler_t *handle, char *url) {
-    int rc = 0;
-    celixThreadRwlock_readLock(&handle->dbLock);
-    psa_tcp_connection_entry_t *entry =
-        hashMap_get(handle->connection_url_map, (void *) (intptr_t) url);
-    celixThreadRwlock_unlock(&handle->dbLock);
-    if (entry == NULL) {
-        char protocol[] = "tcp";
-        int fd = pubsub_tcpHandler_open(handle, url);
-        rc = fd;
-        struct sockaddr_in *sin = pubsub_utils_url_from_fd(fd);
-        // Make handler fd entry
-        char *pUrl = pubsub_utils_url_get_url(sin, protocol);
-        entry = pubsub_tcpHandler_createEntry(handle, fd, pUrl, NULL, sin);
-        if (entry != NULL) {
-            entry->connected = true;
-            free(pUrl);
-            free(sin);
-            celixThreadRwlock_writeLock(&handle->dbLock);
-            if (rc >= 0) {
-                rc = listen(fd, SOMAXCONN);
-                if (rc != 0) {
-                    L_ERROR("[TCP Socket] Error listen: %s\n", strerror(errno));
-                    pubsub_tcpHandler_freeEntry(entry);
-                    entry = NULL;
-                }
-            }
-            if (rc >= 0) {
-                rc = pubsub_tcpHandler_makeNonBlocking(handle, fd);
-                if (rc < 0) {
-                    pubsub_tcpHandler_freeEntry(entry);
-                    entry = NULL;
-                }
-            }
-            if ((rc >= 0) && (handle->efd >= 0)) {
-#if defined(__APPLE__)
-                struct kevent ev;
-                EV_SET (&ev, fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
-                rc = kevent(handle->efd, &ev, 1, NULL, 0, NULL);
-#else
-                struct epoll_event event;
-                bzero(&event, sizeof(event)); // zero the struct
-                event.events = EPOLLIN | EPOLLRDHUP | EPOLLERR;
-                event.data.fd = fd;
-                rc = epoll_ctl(handle->efd, EPOLL_CTL_ADD, fd, &event);
-#endif
-                if (rc < 0) {
-                    L_ERROR("[TCP Socket] Cannot create poll: %s\n", strerror(errno));
-                    errno = 0;
-                    pubsub_tcpHandler_freeEntry(entry);
-                    entry = NULL;
-                }
-                if (entry) {
-                    L_INFO("[TCP Socket] Using %s for service annunciation", entry->url);
-                    hashMap_put(handle->interface_fd_map, (void *) (intptr_t) entry->fd, entry);
-                    hashMap_put(handle->interface_url_map, entry->url, entry);
-                }
-            }
-            celixThreadRwlock_unlock(&handle->dbLock);
-        } else {
-            L_ERROR("[TCP Socket] Error listen socket cannot bind to %s: %s\n", url ? url : "", strerror(errno));
-        }
-    }
-    return rc;
-}
-
-//
-// Setup default receive buffer size.
-// This size is used to allocated the initial read buffer, to avoid receive buffer reallocting.
-// The default receive buffer is allocated in the createEntry when the connection is establised
-//
-int pubsub_tcpHandler_setReceiveBufferSize(pubsub_tcpHandler_t *handle, unsigned int size) {
-    if (handle != NULL) {
-        celixThreadRwlock_writeLock(&handle->dbLock);
-        handle->bufferSize = size;
-        celixThreadRwlock_unlock(&handle->dbLock);
-    }
-    return 0;
-}
-
-//
-// Set Maximum message size
-//
-int pubsub_tcpHandler_setMaxMsgSize(pubsub_tcpHandler_t *handle, unsigned int size) {
-    if (handle != NULL) {
-        celixThreadRwlock_writeLock(&handle->dbLock);
-        handle->maxMsgSize = size;
-        celixThreadRwlock_unlock(&handle->dbLock);
-    }
-    return 0;
-}
-
-//
-// Setup thread timeout
-//
-void pubsub_tcpHandler_setTimeout(pubsub_tcpHandler_t *handle,
-                                  unsigned int timeout) {
-    if (handle != NULL) {
-        celixThreadRwlock_writeLock(&handle->dbLock);
-        handle->timeout = timeout;
-        celixThreadRwlock_unlock(&handle->dbLock);
-    }
-}
-
-//
-// Setup thread name
-//
-void pubsub_tcpHandler_setThreadName(pubsub_tcpHandler_t *handle,
-                                     const char *topic, const char *scope) {
-    if ((handle != NULL) && (topic)) {
-        char *thread_name = NULL;
-        if ((scope) && (topic))
-            asprintf(&thread_name, "TCP TS %s/%s", scope, topic);
-        else
-            asprintf(&thread_name, "TCP TS %s", topic);
-        celixThreadRwlock_writeLock(&handle->dbLock);
-        celixThread_setName(&handle->thread, thread_name);
-        celixThreadRwlock_unlock(&handle->dbLock);
-        free(thread_name);
-    }
-}
-
-//
-// Setup thread priorities
-//
-void pubsub_tcpHandler_setThreadPriority(pubsub_tcpHandler_t *handle, long prio,
-                                         const char *sched) {
-    if (handle == NULL)
-        return;
-    // NOTE. Function will abort when performing a sched_setscheduler without
-    // permission. As result permission has to be checked first.
-    // TODO update this to use cap_get_pid and cap-get_flag instead of check user
-    // is root (note adds dep to -lcap)
-    bool gotPermission = false;
-    if (getuid() == 0) {
-        gotPermission = true;
-    }
-    if (sched != NULL) {
-        int policy = SCHED_OTHER;
-        if (strncmp("SCHED_OTHER", sched, 16) == 0) {
-            policy = SCHED_OTHER;
-#if !defined(__APPLE__)
-        } else if (strncmp("SCHED_BATCH", sched, 16) == 0) {
-            policy = SCHED_BATCH;
-        } else if (strncmp("SCHED_IDLE", sched, 16) == 0) {
-            policy = SCHED_IDLE;
-#endif
-        } else if (strncmp("SCHED_FIFO", sched, 16) == 0) {
-            policy = SCHED_FIFO;
-        } else if (strncmp("SCHED_RR", sched, 16) == 0) {
-            policy = SCHED_RR;
-        }
-        if (gotPermission) {
-            celixThreadRwlock_writeLock(&handle->dbLock);
-            if (prio > 0 && prio < 100) {
-                struct sched_param sch;
-                bzero(&sch, sizeof(struct sched_param));
-                sch.sched_priority = (int)prio;
-                pthread_setschedparam(handle->thread.thread, policy, &sch);
-            } else {
-                L_INFO("Skipping configuration of thread prio to %i and thread "
-                       "scheduling to %s. No permission\n",
-                       (int) prio, sched);
-            }
-            celixThreadRwlock_unlock(&handle->dbLock);
-        }
-    }
-}
-
-void pubsub_tcpHandler_setSendRetryCnt(pubsub_tcpHandler_t *handle, unsigned int count) {
-    if (handle != NULL) {
-        celixThreadRwlock_writeLock(&handle->dbLock);
-        handle->maxSendRetryCount = count;
-        celixThreadRwlock_unlock(&handle->dbLock);
-    }
-}
-
-void pubsub_tcpHandler_setReceiveRetryCnt(pubsub_tcpHandler_t *handle, unsigned int count) {
-    if (handle != NULL) {
-        celixThreadRwlock_writeLock(&handle->dbLock);
-        handle->maxRcvRetryCount = count;
-        celixThreadRwlock_unlock(&handle->dbLock);
-    }
-}
-
-void pubsub_tcpHandler_setSendTimeOut(pubsub_tcpHandler_t *handle, double timeout) {
-    if (handle != NULL) {
-        celixThreadRwlock_writeLock(&handle->dbLock);
-        handle->sendTimeout = timeout;
-        celixThreadRwlock_unlock(&handle->dbLock);
-    }
-}
-
-void pubsub_tcpHandler_setReceiveTimeOut(pubsub_tcpHandler_t *handle, double timeout) {
-    if (handle != NULL) {
-        celixThreadRwlock_writeLock(&handle->dbLock);
-        handle->rcvTimeout = timeout;
-        celixThreadRwlock_unlock(&handle->dbLock);
-    }
-}
-
-void pubsub_tcpHandler_enableReceiveEvent(pubsub_tcpHandler_t *handle,bool enable) {
-    if (handle != NULL) {
-        celixThreadRwlock_writeLock(&handle->dbLock);
-        handle->enableReceiveEvent = enable;
-        celixThreadRwlock_unlock(&handle->dbLock);
-    }
-}
-
-static inline long int pubsub_tcpHandler_getMsgSize(psa_tcp_connection_entry_t *entry) {
-    // Note header message is already read
-    return (long int)entry->header.header.payloadPartSize + (long int)entry->header.header.metadataSize + (long int)entry->readFooterSize;
-}
-
-static inline 
-bool pubsub_tcpHandler_readHeader(pubsub_tcpHandler_t *handle, int fd, psa_tcp_connection_entry_t *entry, long int* msgSize) {
-    bool result = false;
-    size_t syncSize = 0;
-    size_t protocolHeaderBufferSize = 0;
-    // Get Sync Size
-    handle->protocol->getSyncHeaderSize(handle->protocol->handle, &syncSize);
-    // Get HeaderSize of the Protocol Header
-    handle->protocol->getHeaderSize(handle->protocol->handle, &entry->readHeaderSize);
-    // Get HeaderBufferSize of the Protocol Header, when headerBufferSize == 0, the protocol header is included in the payload (needed for endpoints)
-    handle->protocol->getHeaderBufferSize(handle->protocol->handle, &protocolHeaderBufferSize);
-
-    // Ensure capacity in header buffer
-    pubsub_tcpHandler_ensureReadBufferCapacity(handle, entry);
-
-    entry->readMsg.msg_iovlen = 0;
-    entry->readMsg.msg_iov[entry->readMsg.msg_iovlen].iov_base = entry->readHeaderBuffer;
-    entry->readMsg.msg_iov[entry->readMsg.msg_iovlen].iov_len  = entry->readHeaderBufferSize;
-    entry->readMsg.msg_iovlen++;
-
-    // Read the message
-    long int nbytes = 0;
-    // Use peek flag to find sync word or when header is part of the payload
-    unsigned int flag = (entry->headerError || (!protocolHeaderBufferSize)) ? MSG_PEEK : 0;
-    if (entry->readHeaderSize) nbytes = recvmsg(fd, &(entry->readMsg), MSG_NOSIGNAL | MSG_WAITALL | flag);
-    if (nbytes >= entry->readHeaderSize) {
-        if (handle->protocol->decodeHeader(handle->protocol->handle,
-                                           entry->readMsg.msg_iov[0].iov_base,
-                                           entry->readMsg.msg_iov[0].iov_len,
-                                           &entry->header) == CELIX_SUCCESS) {
-            // read header from queue, when recovered from headerError and when header is not part of the payload. (Because of MSG_PEEK)
-            if (entry->headerError && protocolHeaderBufferSize && entry->readHeaderSize) nbytes = recvmsg(fd, &(entry->readMsg), MSG_NOSIGNAL | MSG_WAITALL);
-            entry->headerError = false;
-            result = true;
-        } else {
-            // Did not receive correct header
-            // skip sync word and try to read next header
-            if (!entry->headerError) {
-                L_WARN("[TCP Socket] Failed to decode message header (fd: %d) (url: %s)", entry->fd, entry->url);
-            }
-            entry->headerError = true;
-            entry->readMsg.msg_iovlen = 0;
-            entry->readMsg.msg_iov[entry->readMsg.msg_iovlen].iov_len = syncSize;
-            entry->readMsg.msg_iovlen++;
-            // remove sync item from the queue
-            if (syncSize) nbytes = recvmsg(fd, &(entry->readMsg), MSG_NOSIGNAL | MSG_WAITALL);
-        }
-    }
-    if (msgSize) *msgSize = nbytes;
-    return result;
-}
-
-
-static inline void pubsub_tcpHandler_ensureReadBufferCapacity(pubsub_tcpHandler_t *handle, psa_tcp_connection_entry_t *entry) {
-    if (entry->readHeaderSize > entry->readHeaderBufferSize) {
-        free(entry->readHeaderBuffer);
-        entry->readHeaderBuffer = malloc((size_t) entry->readHeaderSize);
-        entry->readHeaderBufferSize = entry->readHeaderSize;
-    }
-
-    if (entry->header.header.payloadSize > entry->bufferSize) {
-        free(entry->buffer);
-        entry->buffer = malloc((size_t)entry->header.header.payloadSize);
-        entry->bufferSize = entry->header.header.payloadSize;
-    }
-
-    if (entry->header.header.metadataSize > entry->readMetaBufferSize) {
-        free(entry->readMetaBuffer);
-        entry->readMetaBuffer = malloc((size_t) entry->header.header.metadataSize);
-        entry->readMetaBufferSize = entry->header.header.metadataSize;
-    }
-
-    if (entry->readFooterSize > entry->readFooterBufferSize) {
-        free(entry->readFooterBuffer);
-        entry->readFooterBuffer = malloc( (size_t) entry->readFooterSize);
-        entry->readFooterBufferSize = entry->readFooterSize;
-    }
-}
-
-static inline
-void pubsub_tcpHandler_decodePayload(pubsub_tcpHandler_t *handle, psa_tcp_connection_entry_t *entry) {
-
-  if (entry->header.header.payloadSize > 0) {
-      handle->protocol->decodePayload(handle->protocol->handle, entry->buffer, entry->header.header.payloadSize, &entry->header);
-  }
-  if (entry->header.header.metadataSize > 0) {
-      handle->protocol->decodeMetadata(handle->protocol->handle, entry->readMetaBuffer,
-                                       entry->header.header.metadataSize, &entry->header);
-  }
-  if (handle->processMessageCallback && entry->header.payload.payload != NULL && entry->header.payload.length) {
-    struct timespec receiveTime;
-    clock_gettime(CLOCK_REALTIME, &receiveTime);
-    bool releaseEntryBuffer = false;
-    handle->processMessageCallback(handle->processMessagePayload, &entry->header, &releaseEntryBuffer, &receiveTime);
-    if (releaseEntryBuffer) pubsub_tcpHandler_releaseEntryBuffer(handle, entry->fd, 0);
-  }
-}
-
-static inline
-long int pubsub_tcpHandler_readPayload(pubsub_tcpHandler_t *handle, int fd, psa_tcp_connection_entry_t *entry) {
-    entry->readMsg.msg_iovlen = 0;
-    handle->protocol->getFooterSize(handle->protocol->handle, &entry->readFooterSize);
-
-    // from the header can be determined how large buffers should be. Even before receiving all data these buffers can be allocated
-    pubsub_tcpHandler_ensureReadBufferCapacity(handle, entry);
-
-    if (entry->header.header.payloadPartSize) {
-        char* buffer = entry->buffer;
-        entry->readMsg.msg_iov[entry->readMsg.msg_iovlen].iov_base = &buffer[entry->header.header.payloadOffset];
-        entry->readMsg.msg_iov[entry->readMsg.msg_iovlen].iov_len = entry->header.header.payloadPartSize;
-        entry->readMsg.msg_iovlen++;
-    }
-    if (entry->header.header.metadataSize) {
-        entry->readMsg.msg_iov[entry->readMsg.msg_iovlen].iov_base = entry->readMetaBuffer;
-        entry->readMsg.msg_iov[entry->readMsg.msg_iovlen].iov_len  = entry->header.header.metadataSize;
-        entry->readMsg.msg_iovlen++;
-    }
-
-    if (entry->readFooterSize) {
-        entry->readMsg.msg_iov[entry->readMsg.msg_iovlen].iov_base = entry->readFooterBuffer;
-        entry->readMsg.msg_iov[entry->readMsg.msg_iovlen].iov_len  = entry->readFooterSize;
-        entry->readMsg.msg_iovlen++;
-    }
-
-    long int nbytes = recvmsg(fd, &(entry->readMsg), MSG_NOSIGNAL | MSG_WAITALL);
-    if (nbytes >= pubsub_tcpHandler_getMsgSize(entry)) {
-        bool valid = true;
-        if (entry->readFooterSize) {
-            if (handle->protocol->decodeFooter(handle->protocol->handle, entry->readFooterBuffer, entry->readFooterBufferSize, &entry->header) != CELIX_SUCCESS) {
-                // Did not receive correct footer
-                L_ERROR("[TCP Socket] Failed to decode message footer seq %d (received corrupt message, transmit buffer full?) (fd: %d) (url: %s)", entry->header.header.seqNr, entry->fd, entry->url);
-                valid = false;
-            }
-        }
-        if (!entry->header.header.isLastSegment) {
-            // Not last Segment of message
-            valid = false;
-        }
-
-        if (valid) {
-            // Complete message is received
-            pubsub_tcpHandler_decodePayload(handle, entry);
-        }
-    }
-    return nbytes;
-}
-
-//
-// Reads data from the filedescriptor which has date (determined by epoll()) and stores it in the internal structure
-// If the message is completely reassembled true is returned and the index and size have valid values
-//
-int pubsub_tcpHandler_read(pubsub_tcpHandler_t *handle, int fd) {
-    celixThreadRwlock_readLock(&handle->dbLock);
-    psa_tcp_connection_entry_t *entry = hashMap_get(handle->interface_fd_map, (void *) (intptr_t) fd);
-    if (entry == NULL) {
-        entry = hashMap_get(handle->connection_fd_map, (void *) (intptr_t) fd);
-    }
-    // Find FD entry
-    if (entry == NULL) {
-        celixThreadRwlock_unlock(&handle->dbLock);
-        return -1;
-    }
-    // If it's not connected return from function
-    if (!entry->connected) {
-        celixThreadRwlock_unlock(&handle->dbLock);
-        return -1;
-    }
-    long int nbytes = 0;
-    // if not yet enough bytes are received the header can not be read
-    if (pubsub_tcpHandler_readHeader(handle, fd, entry, &nbytes)) {
-        nbytes = pubsub_tcpHandler_readPayload(handle, fd, entry);
-    }
-    if (nbytes > 0) {
-        entry->retryCount = 0;
-    } else if (nbytes < 0) {
-        if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
-            // Non blocking interrupt
-            entry->retryCount = 0;
-        } else if (entry->retryCount < handle->maxRcvRetryCount) {
-            entry->retryCount++;
-            L_WARN(
-                    "[TCP Socket] Failed to receive message (fd: %d), try again. error(%d): %s, Retry count %u of %u.",
-                    entry->fd, errno, strerror(errno), entry->retryCount, handle->maxSendRetryCount);
-        } else {
-            L_ERROR("[TCP Socket] Failed to receive message (fd: %d) after %u retries! Closing connection... Error: %s",
-                    entry->fd, handle->maxRcvRetryCount, strerror(errno));
-            nbytes = 0; //Return 0 as indicator to close the connection
-        }
-    }
-    celixThreadRwlock_unlock(&handle->dbLock);
-    return (int)nbytes;
-}
-
-int pubsub_tcpHandler_addMessageHandler(pubsub_tcpHandler_t *handle, void *payload,
-                                        pubsub_tcpHandler_processMessage_callback_t processMessageCallback) {
-    int result = 0;
-    celixThreadRwlock_writeLock(&handle->dbLock);
-    handle->processMessageCallback = processMessageCallback;
-    handle->processMessagePayload = payload;
-    celixThreadRwlock_unlock(&handle->dbLock);
-    return result;
-}
-
-int pubsub_tcpHandler_addReceiverConnectionCallback(pubsub_tcpHandler_t *handle, void *payload,
-                                                    pubsub_tcpHandler_receiverConnectMessage_callback_t connectMessageCallback,
-                                                    pubsub_tcpHandler_receiverConnectMessage_callback_t disconnectMessageCallback) {
-    int result = 0;
-    celixThreadRwlock_writeLock(&handle->dbLock);
-    handle->receiverConnectMessageCallback = connectMessageCallback;
-    handle->receiverDisconnectMessageCallback = disconnectMessageCallback;
-    handle->receiverConnectPayload = payload;
-    celixThreadRwlock_unlock(&handle->dbLock);
-    return result;
-}
-
-//
-// Write large data to TCP. .
-//
-int pubsub_tcpHandler_write(pubsub_tcpHandler_t *handle, pubsub_protocol_message_t *message, struct iovec *msgIoVec,
-                            size_t msg_iov_len, int flags) {
-    int result = 0;
-    if (handle == NULL) {
-        return -1;
-    }
-    int connFdCloseQueue[hashMap_size(handle->connection_fd_map)];
-    int nofConnToClose = 0;
-    if (handle) {
-        celixThreadRwlock_readLock(&handle->dbLock);
-        hash_map_iterator_t iter = hashMapIterator_construct(handle->connection_fd_map);
-        size_t max_msg_iov_len = IOV_MAX - 2; // header , footer, padding
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_tcp_connection_entry_t *entry = hashMapIterator_nextValue(&iter);
-            if (!entry->connected) {
-                continue;
-            }
-            // When maxMsgSize is zero then payloadSize is disabled
-            if (entry->maxMsgSize == 0) {
-                // if max msg size is set to zero nothing will be send
-                continue;
-            }
-            celixThreadMutex_lock(&entry->writeMutex);
-            void *payloadData = NULL;
-            size_t payloadSize = 0;
-            if (msg_iov_len == 1) {
-                handle->protocol->encodePayload(handle->protocol->handle, message, &payloadData, &payloadSize);
-            } else {
-                for (size_t i = 0; i < msg_iov_len; i++) {
-                    payloadSize += msgIoVec[i].iov_len;
-                }
-            }
-
-            // check if message is not too large
-            bool isMessageSegmentationSupported = false;
-            handle->protocol->isMessageSegmentationSupported(handle->protocol->handle, &isMessageSegmentationSupported);
-            if (!isMessageSegmentationSupported && (msg_iov_len > max_msg_iov_len || payloadSize > entry->maxMsgSize)) {
-                L_WARN("[TCP Socket] Failed to send message (fd: %d), Message segmentation is not supported\n", entry->fd);
-                celixThreadMutex_unlock(&entry->writeMutex);
-                continue;
-            }
-
-            message->header.convertEndianess = 0;
-            message->header.payloadSize = payloadSize;
-            message->header.payloadPartSize = payloadSize;
-            message->header.payloadOffset = 0;
-            message->header.isLastSegment = 1;
-
-            void *metadataData = NULL;
-            size_t metadataSize = 0;
-            if (message->metadata.metadata) {
-                metadataSize = entry->writeMetaBufferSize;
-                metadataData = entry->writeMetaBuffer;
-                // When maxMsgSize is smaller then meta data is disabled
-                if (metadataSize > entry->maxMsgSize) {
-                    metadataSize = 0;
-                }
-                handle->protocol->encodeMetadata(handle->protocol->handle, message, &metadataData, &metadataSize);
-            }
-
-            message->header.metadataSize = metadataSize;
-            size_t totalMsgSize = payloadSize + metadataSize;
-
-            size_t sendMsgSize = 0;
-            size_t msgPayloadOffset = 0;
-            size_t msgIovOffset     = 0;
-            bool allPayloadAdded = (payloadSize == 0);
-            long int nbytes = LONG_MAX;
-            while (sendMsgSize < totalMsgSize && nbytes > 0) {
-                struct msghdr msg;
-                struct iovec msg_iov[IOV_MAX];
-                memset(&msg, 0x00, sizeof(struct msghdr));
-                msg.msg_name = &entry->addr;
-                msg.msg_namelen = entry->len;
-                msg.msg_flags = flags;
-                msg.msg_iov = msg_iov;
-
-                size_t msgPartSize = 0;
-                message->header.payloadPartSize = 0;
-                message->header.payloadOffset = 0;
-                message->header.metadataSize = 0;
-                message->header.isLastSegment = 0;
-
-                size_t protocolHeaderBufferSize = 0;
-                // Get HeaderBufferSize of the Protocol Header, when headerBufferSize == 0, the protocol header is included in the payload (needed for endpoints)
-                handle->protocol->getHeaderBufferSize(handle->protocol->handle, &protocolHeaderBufferSize);
-                size_t footerSize = 0;
-                // Get size of the Protocol Footer
-                handle->protocol->getFooterSize(handle->protocol->handle, &footerSize);
-                size_t maxMsgSize = entry->maxMsgSize - protocolHeaderBufferSize - footerSize;
-
-                // reserve space for the header if required, header is added later when size of message is known (message can split in parts)
-                if (protocolHeaderBufferSize) {
-                    msg.msg_iovlen++;
-                }
-                // Write generic seralized payload in vector buffer
-                if (!allPayloadAdded) {
-                    if (payloadSize && payloadData && maxMsgSize) {
-                        char *buffer = payloadData;
-                        msg.msg_iov[msg.msg_iovlen].iov_base = &buffer[msgPayloadOffset];
-                        msg.msg_iov[msg.msg_iovlen].iov_len = MIN((payloadSize - msgPayloadOffset), maxMsgSize);
-                        msgPartSize += msg.msg_iov[msg.msg_iovlen].iov_len;
-                        msg.msg_iovlen++;
-
-                    } else {
-                        // copy serialized vector into vector buffer
-                        size_t i;
-                        for (i = msgIovOffset; i < MIN(msg_iov_len, msgIovOffset + max_msg_iov_len); i++) {
-                            if ((msgPartSize + msgIoVec[i].iov_len) > maxMsgSize) {
-                                break;
-                            }
-                            msg.msg_iov[msg.msg_iovlen].iov_base = msgIoVec[i].iov_base;
-                            msg.msg_iov[msg.msg_iovlen].iov_len = msgIoVec[i].iov_len;
-                            msgPartSize += msg.msg_iov[msg.msg_iovlen].iov_len;
-                            msg.msg_iovlen++;
-                        }
-                        // if no entry could be added
-                        if (i == msgIovOffset) {
-                            // TODO element can be split in parts?
-                            L_ERROR("[TCP Socket] vector io element is larger than max msg size");
-                            break;
-                        }
-                        msgIovOffset = i;
-                    }
-                    message->header.payloadPartSize = msgPartSize;
-                    message->header.payloadOffset   = msgPayloadOffset;
-                    msgPayloadOffset += message->header.payloadPartSize;
-                    sendMsgSize = msgPayloadOffset;
-                    allPayloadAdded= msgPayloadOffset >= payloadSize;
-                }
-
-                // Write optional metadata in vector buffer
-                if (allPayloadAdded &&
-                    (metadataSize != 0 && metadataData) &&
-                    (msgPartSize < maxMsgSize) &&
-                    (msg.msg_iovlen-1 < max_msg_iov_len)) {  // header is already included
-                    msg.msg_iov[msg.msg_iovlen].iov_base = metadataData;
-                    msg.msg_iov[msg.msg_iovlen].iov_len = metadataSize;
-                    msg.msg_iovlen++;
-                    msgPartSize += metadataSize;
-                    message->header.metadataSize = metadataSize;
-                    sendMsgSize += metadataSize;
-                }
-                if (sendMsgSize >= totalMsgSize) {
-                    message->header.isLastSegment = 0x1;
-                }
-
-                void *headerData = NULL;
-                size_t headerSize = 0;
-                // Get HeaderSize of the Protocol Header
-                handle->protocol->getHeaderSize(handle->protocol->handle, &headerSize);
-
-                // check if header is not part of the payload (=> headerBufferSize = 0)
-                if (protocolHeaderBufferSize) {
-                    headerData = entry->writeHeaderBuffer;
-                    // Encode the header, with payload size and metadata size
-                    handle->protocol->encodeHeader(handle->protocol->handle, message, &headerData, &headerSize);
-                    entry->writeHeaderBufferSize = MAX(headerSize, entry->writeHeaderBufferSize);
-                    if (headerData && entry->writeHeaderBuffer != headerData) {
-                        entry->writeHeaderBuffer = headerData;
-                    }
-                    if (headerSize && headerData) {
-                        // Write header in 1st vector buffer item
-                        msg.msg_iov[0].iov_base = headerData;
-                        msg.msg_iov[0].iov_len = headerSize;
-                        msgPartSize += msg.msg_iov[0].iov_len;
-                    } else {
-                        L_ERROR("[TCP Socket] No header buffer is generated");
-                        break;
-                    }
-                }
-
-                void *footerData = NULL;
-                // Write optional footerData in vector buffer
-                if (footerSize) {
-                    footerData = entry->writeFooterBuffer;
-                    handle->protocol->encodeFooter(handle->protocol->handle, message, &footerData, &footerSize);
-                    if (footerData && entry->writeFooterBuffer != footerData) {
-                        entry->writeFooterBuffer = footerData;
-                        entry->writeFooterBufferSize = footerSize;
-                    }
-                    if (footerData) {
-                        msg.msg_iov[msg.msg_iovlen].iov_base = footerData;
-                        msg.msg_iov[msg.msg_iovlen].iov_len  = footerSize;
-                        msg.msg_iovlen++;
-                        msgPartSize += footerSize;
-                    }
-                }
-                nbytes = sendmsg(entry->fd, &msg, flags | MSG_NOSIGNAL);
-
-                //  When a specific socket keeps reporting errors can indicate a subscriber
-                //  which is not active anymore, the connection will remain until the retry
-                //  counter exceeds the maximum retry count.
-                //  Btw, also, SIGSTOP issued by a debugging tool can result in EINTR error.
-                if (nbytes == -1) {
-                    if (entry->retryCount < handle->maxSendRetryCount) {
-                        entry->retryCount++;
-                        L_ERROR(
-                            "[TCP Socket] Failed to send message (fd: %d), try again. Retry count %u of %u, error(%d): %s.",
-                            entry->fd, entry->retryCount, handle->maxSendRetryCount, errno, strerror(errno));
-                    } else {
-                        L_ERROR(
-                            "[TCP Socket] Failed to send message (fd: %d) after %u retries! Closing connection... Error: %s", entry->fd, handle->maxSendRetryCount, strerror(errno));
-                        connFdCloseQueue[nofConnToClose++] = entry->fd;
-                    }
-                    result = -1; //At least one connection failed sending
-                } else if (msgPartSize) {
-                    entry->retryCount = 0;
-                    if (nbytes != msgPartSize) {
-                        L_ERROR("[TCP Socket] seq: %d MsgSize not correct: %d != %d (%s)\n", message->header.seqNr, msgPartSize, nbytes, strerror(errno));
-                    }
-                }
-                // Note: serialized Payload is deleted by serializer
-                if (payloadData && (payloadData != message->payload.payload)) {
-                    free(payloadData);
-                }
-            }
-            celixThreadMutex_unlock(&entry->writeMutex);
-        }
-        celixThreadRwlock_unlock(&handle->dbLock);
-    }
-    //Force close all connections that are queued in a list, done outside of locking handle->dbLock to prevent deadlock
-    for (int i = 0; i < nofConnToClose; i++) {
-        pubsub_tcpHandler_close(handle, connFdCloseQueue[i]);
-    }
-    return result;
-}
-
-//
-// get interface URL
-//
-char *pubsub_tcpHandler_get_interface_url(pubsub_tcpHandler_t *handle) {
-    hash_map_iterator_t iter =
-        hashMapIterator_construct(handle->interface_url_map);
-    char *url = NULL;
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_tcp_connection_entry_t *entry =
-            hashMapIterator_nextValue(&iter);
-        if (entry && entry->url) {
-            if (!url) {
-                url = celix_utils_strdup(entry->url);
-            } else {
-                char *tmp = url;
-                asprintf(&url, "%s %s", tmp, entry->url);
-                free(tmp);
-            }
-        }
-    }
-    return url;
-}
-//
-// get interface URL
-//
-char *pubsub_tcpHandler_get_connection_url(pubsub_tcpHandler_t *handle) {
-    celixThreadRwlock_writeLock(&handle->dbLock);
-    hash_map_iterator_t iter =
-            hashMapIterator_construct(handle->connection_url_map);
-    char *url = NULL;
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_tcp_connection_entry_t *entry =
-                hashMapIterator_nextValue(&iter);
-        if (entry && entry->url) {
-            if (!url) {
-                pubsub_utils_url_t *url_info = pubsub_utils_url_parse(entry->url);
-                url = celix_utils_strdup(url_info->interface_url ? url_info->interface_url : entry->url);
-                pubsub_utils_url_free(url_info);
-            } else {
-                char *tmp = url;
-                pubsub_utils_url_t *url_info = pubsub_utils_url_parse(entry->url);
-                asprintf(&url, "%s %s", tmp, url_info->interface_url ? url_info->interface_url : entry->url);
-                pubsub_utils_url_free(url_info);
-                free(tmp);
-            }
-        }
-    }
-    celixThreadRwlock_unlock(&handle->dbLock);
-    return url;
-}
-
-//
-// Handle non-blocking accept (sender)
-//
-static inline
-int pubsub_tcpHandler_acceptHandler(pubsub_tcpHandler_t *handle, psa_tcp_connection_entry_t *pendingConnectionEntry) {
-    celixThreadRwlock_writeLock(&handle->dbLock);
-    // new connection available
-    struct sockaddr_in their_addr;
-    socklen_t len = sizeof(struct sockaddr_in);
-    int fd = accept(pendingConnectionEntry->fd, (struct sockaddr*)&their_addr, &len);
-    int rc = fd;
-    if (rc == -1) {
-        L_ERROR("[TCP Socket] accept failed: %s\n", strerror(errno));
-    }
-    if (rc >= 0) {
-        // handle new connection:
-        struct sockaddr_in sin;
-        getsockname(pendingConnectionEntry->fd, (struct sockaddr *) &sin, &len);
-        char *interface_url = pubsub_utils_url_get_url(&sin, NULL);
-        char *url = pubsub_utils_url_get_url(&their_addr, NULL);
-        psa_tcp_connection_entry_t *entry = pubsub_tcpHandler_createEntry(handle, fd, url, interface_url, &their_addr);
-#if defined(__APPLE__)
-        struct kevent ev;
-        EV_SET (&ev, entry->fd, EVFILT_READ, EV_ADD | EV_ENABLE , 0, 0, 0);
-        rc = kevent (handle->efd, &ev, 1, NULL, 0, NULL);
-#else
-        struct epoll_event event;
-        bzero(&event, sizeof(event)); // zero the struct
-        event.events = EPOLLRDHUP | EPOLLERR;
-        if (handle->enableReceiveEvent) event.events |= EPOLLIN;
-        event.data.fd = entry->fd;
-        // Register Read to epoll
-        rc = epoll_ctl(handle->efd, EPOLL_CTL_ADD, entry->fd, &event);
-#endif
-        if (rc < 0) {
-            pubsub_tcpHandler_freeEntry(entry);
-            free(entry);
-            L_ERROR("[TCP Socket] Cannot create epoll\n");
-        } else {
-            // Call Accept Connection callback
-            if (handle->acceptConnectMessageCallback)
-                handle->acceptConnectMessageCallback(handle->acceptConnectPayload, url);
-            hashMap_put(handle->connection_fd_map, (void *) (intptr_t) entry->fd, entry);
-            hashMap_put(handle->connection_url_map, entry->url, entry);
-            L_INFO("[TCP Socket] New connection to url: %s: \n", url);
-        }
-        free(url);
-        free(interface_url);
-    }
-    celixThreadRwlock_unlock(&handle->dbLock);
-    return fd;
-}
-
-//
-// Handle sockets connection (sender)
-//
-static inline
-void pubsub_tcpHandler_connectionHandler(pubsub_tcpHandler_t *handle, int fd) {
-    celixThreadRwlock_readLock(&handle->dbLock);
-    psa_tcp_connection_entry_t *entry = hashMap_get(handle->connection_fd_map, (void *) (intptr_t) fd);
-    if (entry)
-        if ((!entry->connected)) {
-            // tell sender that an receiver is connected
-            if (handle->receiverConnectMessageCallback)
-                handle->receiverConnectMessageCallback(handle->receiverConnectPayload, entry->url, false);
-            entry->connected = true;
-        }
-    celixThreadRwlock_unlock(&handle->dbLock);
-}
-
-#if defined(__APPLE__)
-//
-// The main socket event loop
-//
-static inline
-void pubsub_tcpHandler_handler(pubsub_tcpHandler_t *handle) {
-  int rc = 0;
-  if (handle->efd >= 0) {
-    int nof_events = 0;
-    //  Wait for events.
-    struct kevent events[MAX_EVENTS];
-    struct timespec ts = {handle->timeout / 1000, (handle->timeout  % 1000) * 1000000};
-    nof_events = kevent (handle->efd, NULL, 0, &events[0], MAX_EVENTS, handle->timeout ? &ts : NULL);
-    if (nof_events < 0) {
-      if ((errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)) {
-      } else
-        L_ERROR("[TCP Socket] Cannot create poll wait (%d) %s\n", nof_events, strerror(errno));
-    }
-    for (int i = 0; i < nof_events; i++) {
-      hash_map_iterator_t iter = hashMapIterator_construct(handle->interface_fd_map);
-      psa_tcp_connection_entry_t *pendingConnectionEntry = NULL;
-      while (hashMapIterator_hasNext(&iter)) {
-        psa_tcp_connection_entry_t *entry = hashMapIterator_nextValue(&iter);
-        if (events[i].ident == entry->fd)
-          pendingConnectionEntry = entry;
-      }
-      if (pendingConnectionEntry) {
-        int fd = pubsub_tcpHandler_acceptHandler(handle, pendingConnectionEntry);
-        pubsub_tcpHandler_connectionHandler(handle, fd);
-      } else if (events[i].filter & EVFILT_READ) {
-        int rc = pubsub_tcpHandler_read(handle, events[i].ident);
-        if (rc == 0) pubsub_tcpHandler_close(handle, events[i].ident);
-      } else if (events[i].flags & EV_EOF) {
-        int err = 0;
-        socklen_t len = sizeof(int);
-        rc = getsockopt(events[i].ident, SOL_SOCKET, SO_ERROR, &err, &len);
-        if (rc != 0) {
-          L_ERROR("[TCP Socket]:EPOLLRDHUP ERROR read from socket %s\n", strerror(errno));
-          continue;
-        }
-        pubsub_tcpHandler_close(handle, events[i].ident);
-      } else if (events[i].flags & EV_ERROR) {
-        L_ERROR("[TCP Socket]:EPOLLERR  ERROR read from socket %s\n", strerror(errno));
-        pubsub_tcpHandler_close(handle, events[i].ident);
-        continue;
-      }
-    }
-  }
-  return;
-}
-
-#else
-
-//
-// The main socket event loop
-//
-static inline
-void pubsub_tcpHandler_handler(pubsub_tcpHandler_t *handle) {
-    int rc = 0;
-    if (handle->efd >= 0) {
-        int nof_events = 0;
-        struct epoll_event events[MAX_EVENTS];
-        nof_events = epoll_wait(handle->efd, events, MAX_EVENTS, (int)handle->timeout);
-        if (nof_events < 0) {
-            if ((errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)) {
-            } else
-                L_ERROR("[TCP Socket] Cannot create epoll wait (%d) %s\n", nof_events, strerror(errno));
-        }
-        for (int i = 0; i < nof_events; i++) {
-            hash_map_iterator_t iter = hashMapIterator_construct(handle->interface_fd_map);
-            psa_tcp_connection_entry_t *pendingConnectionEntry = NULL;
-            while (hashMapIterator_hasNext(&iter)) {
-                psa_tcp_connection_entry_t *entry = hashMapIterator_nextValue(&iter);
-                if (events[i].data.fd == entry->fd)
-                    pendingConnectionEntry = entry;
-            }
-            if (pendingConnectionEntry) {
-               int fd = pubsub_tcpHandler_acceptHandler(handle, pendingConnectionEntry);
-               pubsub_tcpHandler_connectionHandler(handle, fd);
-            } else if (events[i].events & EPOLLIN) {
-                rc = pubsub_tcpHandler_read(handle, events[i].data.fd);
-                if (rc == 0) pubsub_tcpHandler_close(handle, events[i].data.fd);
-            } else if (events[i].events & EPOLLRDHUP) {
-                int err = 0;
-                socklen_t len = sizeof(int);
-                rc = getsockopt(events[i].data.fd, SOL_SOCKET, SO_ERROR, &err, &len);
-                if (rc != 0) {
-                    L_ERROR("[TCP Socket]:EPOLLRDHUP ERROR read from socket %s\n", strerror(errno));
-                    continue;
-                }
-                pubsub_tcpHandler_close(handle, events[i].data.fd);
-            } else if (events[i].events & EPOLLERR) {
-                L_ERROR("[TCP Socket]:EPOLLERR  ERROR read from socket %s\n", strerror(errno));
-                pubsub_tcpHandler_close(handle, events[i].data.fd);
-                continue;
-            }
-        }
-    }
-}
-#endif
-
-//
-// The socket thread
-//
-static void *pubsub_tcpHandler_thread(void *data) {
-    pubsub_tcpHandler_t *handle = data;
-    celixThreadRwlock_readLock(&handle->dbLock);
-    bool running = handle->running;
-    celixThreadRwlock_unlock(&handle->dbLock);
-
-    while (running) {
-        pubsub_tcpHandler_handler(handle);
-        celixThreadRwlock_readLock(&handle->dbLock);
-        running = handle->running;
-        celixThreadRwlock_unlock(&handle->dbLock);
-    } // while
-    return NULL;
-}
diff --git a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_handler.h b/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_handler.h
deleted file mode 100644
index 2d97634..0000000
--- a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_handler.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.
- */
-/*
- * pubsub_tcp_handler.h
- *
- *  \date       July 18, 2016
- *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright  Apache License, Version 2.0
- */
-
-#ifndef _PUBSUB_TCP_BUFFER_HANDLER_H_
-#define _PUBSUB_TCP_BUFFER_HANDLER_H_
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <celix_log_helper.h>
-#include "celix_threads.h"
-#include "pubsub_utils_url.h"
-#include <pubsub_protocol.h>
-
-#ifndef MIN
-#define MIN(a, b) ((a<b) ? (a) : (b))
-#endif
-
-#ifndef MAX
-#define MAX(a, b) ((a>b) ? (a) : (b))
-#endif
-
-typedef struct pubsub_tcpHandler pubsub_tcpHandler_t;
-typedef void(*pubsub_tcpHandler_processMessage_callback_t)
-    (void *payload, const pubsub_protocol_message_t *header, bool *release, struct timespec *receiveTime);
-typedef void (*pubsub_tcpHandler_receiverConnectMessage_callback_t)(void *payload, const char *url, bool lock);
-typedef void (*pubsub_tcpHandler_acceptConnectMessage_callback_t)(void *payload, const char *url);
-
-pubsub_tcpHandler_t *pubsub_tcpHandler_create(pubsub_protocol_service_t *protocol, celix_log_helper_t *logHelper);
-void pubsub_tcpHandler_destroy(pubsub_tcpHandler_t *handle);
-int pubsub_tcpHandler_open(pubsub_tcpHandler_t *handle, char *url);
-int pubsub_tcpHandler_close(pubsub_tcpHandler_t *handle, int fd);
-int pubsub_tcpHandler_connect(pubsub_tcpHandler_t *handle, char *url);
-int pubsub_tcpHandler_disconnect(pubsub_tcpHandler_t *handle, char *url);
-int pubsub_tcpHandler_listen(pubsub_tcpHandler_t *handle, char *url);
-int pubsub_tcpHandler_setReceiveBufferSize(pubsub_tcpHandler_t *handle, unsigned int size);
-int pubsub_tcpHandler_setMaxMsgSize(pubsub_tcpHandler_t *handle, unsigned int size);
-void pubsub_tcpHandler_setTimeout(pubsub_tcpHandler_t *handle, unsigned int timeout);
-void pubsub_tcpHandler_setSendRetryCnt(pubsub_tcpHandler_t *handle, unsigned int count);
-void pubsub_tcpHandler_setReceiveRetryCnt(pubsub_tcpHandler_t *handle, unsigned int count);
-void pubsub_tcpHandler_setSendTimeOut(pubsub_tcpHandler_t *handle, double timeout);
-void pubsub_tcpHandler_setReceiveTimeOut(pubsub_tcpHandler_t *handle, double timeout);
-void pubsub_tcpHandler_enableReceiveEvent(pubsub_tcpHandler_t *handle, bool enable);
-
-int pubsub_tcpHandler_read(pubsub_tcpHandler_t *handle, int fd);
-int pubsub_tcpHandler_write(pubsub_tcpHandler_t *handle,
-                            pubsub_protocol_message_t *message,
-                            struct iovec *msg_iovec,
-                            size_t msg_iov_len,
-                            int flags);
-int pubsub_tcpHandler_addMessageHandler(pubsub_tcpHandler_t *handle,
-                                        void *payload,
-                                        pubsub_tcpHandler_processMessage_callback_t processMessageCallback);
-int pubsub_tcpHandler_addReceiverConnectionCallback(pubsub_tcpHandler_t *handle,
-                                                    void *payload,
-                                                    pubsub_tcpHandler_receiverConnectMessage_callback_t connectMessageCallback,
-                                                    pubsub_tcpHandler_receiverConnectMessage_callback_t disconnectMessageCallback);
-int pubsub_tcpHandler_addAcceptConnectionCallback(pubsub_tcpHandler_t *handle,
-                                                  void *payload,
-                                                  pubsub_tcpHandler_acceptConnectMessage_callback_t connectMessageCallback,
-                                                  pubsub_tcpHandler_acceptConnectMessage_callback_t disconnectMessageCallback);
-char *pubsub_tcpHandler_get_interface_url(pubsub_tcpHandler_t *handle);
-char *pubsub_tcpHandler_get_connection_url(pubsub_tcpHandler_t *handle);
-void pubsub_tcpHandler_setThreadPriority(pubsub_tcpHandler_t *handle, long prio, const char *sched);
-void pubsub_tcpHandler_setThreadName(pubsub_tcpHandler_t *handle, const char *topic, const char *scope);
-
-#endif /* _PUBSUB_TCP_BUFFER_HANDLER_H_ */
diff --git a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_topic_receiver.c b/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_topic_receiver.c
deleted file mode 100644
index aeda1c3..0000000
--- a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_topic_receiver.c
+++ /dev/null
@@ -1,804 +0,0 @@
-/*
- * 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 <pubsub_serializer.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <pubsub/subscriber.h>
-#include <memory.h>
-#include <pubsub_constants.h>
-#include <arpa/inet.h>
-#include <celix_log_helper.h>
-#include "pubsub_tcp_handler.h"
-#include "pubsub_tcp_topic_receiver.h"
-#include "pubsub_psa_tcp_constants.h"
-#include "pubsub_tcp_common.h"
-
-#include <uuid/uuid.h>
-#include <pubsub_admin_metrics.h>
-#include <pubsub_utils.h>
-#include <celix_api.h>
-
-#ifndef UUID_STR_LEN
-#define UUID_STR_LEN  37
-#endif
-
-#define L_DEBUG(...) \
-    celix_logHelper_log(receiver->logHelper, CELIX_LOG_LEVEL_DEBUG, __VA_ARGS__)
-#define L_INFO(...) \
-    celix_logHelper_log(receiver->logHelper, CELIX_LOG_LEVEL_INFO, __VA_ARGS__)
-#define L_WARN(...) \
-    celix_logHelper_log(receiver->logHelper, CELIX_LOG_LEVEL_WARNING, __VA_ARGS__)
-#define L_ERROR(...) \
-    celix_logHelper_log(receiver->logHelper, CELIX_LOG_LEVEL_ERROR, __VA_ARGS__)
-
-struct pubsub_tcp_topic_receiver {
-    celix_bundle_context_t *ctx;
-    celix_log_helper_t *logHelper;
-    long serializerSvcId;
-    pubsub_serializer_service_t *serializer;
-    long protocolSvcId;
-    pubsub_protocol_service_t *protocol;
-    char *scope;
-    char *topic;
-    size_t timeout;
-    bool metricsEnabled;
-    bool isPassive;
-    pubsub_tcpHandler_t *socketHandler;
-    pubsub_tcpHandler_t *sharedSocketHandler;
-
-    struct {
-        celix_thread_t thread;
-        celix_thread_mutex_t mutex;
-        bool running;
-    } thread;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = tcp url, value = psa_tcp_requested_connection_entry_t*
-        bool allConnected; //true if all requestedConnection are connected
-    } requestedConnections;
-
-    long subscriberTrackerId;
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = bnd id, value = psa_tcp_subscriber_entry_t
-        bool allInitialized;
-    } subscribers;
-};
-
-typedef struct psa_tcp_requested_connection_entry {
-    pubsub_tcp_topic_receiver_t *parent;
-    char *url;
-    bool connected;
-    bool statically; //true if the connection is statically configured through the topic properties.
-} psa_tcp_requested_connection_entry_t;
-
-typedef struct psa_tcp_subscriber_metrics_entry_t {
-    unsigned int msgTypeId;
-    uuid_t origin;
-
-    unsigned long nrOfMessagesReceived;
-    unsigned long nrOfSerializationErrors;
-    struct timespec lastMessageReceived;
-    double averageTimeBetweenMessagesInSeconds;
-    double averageSerializationTimeInSeconds;
-    double averageDelayInSeconds;
-    double maxDelayInSeconds;
-    double minDelayInSeconds;
-    unsigned long nrOfMissingSeqNumbers;
-} psa_tcp_subscriber_metrics_entry_t;
-
-typedef struct psa_tcp_subscriber_entry {
-    hash_map_t *msgTypes; //map from serializer svc
-    hash_map_t *metrics; //key = msg type id, value = hash_map (key = origin uuid, value = psa_tcp_subscriber_metrics_entry_t*
-    hash_map_t *subscriberServices; //key = servide id, value = pubsub_subscriber_t*
-    bool initialized; //true if the init function is called through the receive thread
-} psa_tcp_subscriber_entry_t;
-
-static void pubsub_tcpTopicReceiver_addSubscriber(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *owner);
-static void pubsub_tcpTopicReceiver_removeSubscriber(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *owner);
-static void *psa_tcp_recvThread(void *data);
-static void psa_tcp_connectToAllRequestedConnections(pubsub_tcp_topic_receiver_t *receiver);
-static void psa_tcp_initializeAllSubscribers(pubsub_tcp_topic_receiver_t *receiver);
-static void processMsg(void *handle, const pubsub_protocol_message_t *hdr, bool *release, struct timespec *receiveTime);
-static void psa_tcp_connectHandler(void *handle, const char *url, bool lock);
-static void psa_tcp_disConnectHandler(void *handle, const char *url, bool lock);
-static bool psa_tcp_checkVersion(version_pt msgVersion, uint16_t major, uint16_t minor);
-
-pubsub_tcp_topic_receiver_t *pubsub_tcpTopicReceiver_create(celix_bundle_context_t *ctx,
-                                                            celix_log_helper_t *logHelper,
-                                                            const char *scope,
-                                                            const char *topic,
-                                                            const celix_properties_t *topicProperties,
-                                                            pubsub_tcp_endPointStore_t *handlerStore,
-                                                            long serializerSvcId,
-                                                            pubsub_serializer_service_t *serializer,
-                                                            long protocolSvcId,
-                                                            pubsub_protocol_service_t *protocol) {
-    pubsub_tcp_topic_receiver_t *receiver = calloc(1, sizeof(*receiver));
-    receiver->ctx = ctx;
-    receiver->logHelper = logHelper;
-    receiver->serializerSvcId = serializerSvcId;
-    receiver->serializer = serializer;
-    receiver->protocolSvcId = protocolSvcId;
-    receiver->protocol = protocol;
-    receiver->scope = scope == NULL ? NULL : strndup(scope, 1024 * 1024);
-    receiver->topic = strndup(topic, 1024 * 1024);
-    const char *staticConnectUrls = pubsub_getEnvironmentVariableWithScopeTopic(ctx, PUBSUB_TCP_STATIC_CONNECT_URLS_FOR, topic, scope);
-    const char *isPassive = pubsub_getEnvironmentVariableWithScopeTopic(ctx, PUBSUB_TCP_PASSIVE_ENABLED, topic, scope);
-    const char *passiveKey = pubsub_getEnvironmentVariableWithScopeTopic(ctx, PUBSUB_TCP_PASSIVE_SELECTION_KEY, topic, scope);
-
-    if (isPassive) {
-        receiver->isPassive = psa_tcp_isPassive(isPassive);
-    }
-    if (topicProperties != NULL) {
-        if(staticConnectUrls == NULL) {
-            staticConnectUrls = celix_properties_get(topicProperties, PUBSUB_TCP_STATIC_CONNECT_URLS, NULL);
-        }
-        if (isPassive == NULL) {
-            receiver->isPassive = celix_properties_getAsBool(topicProperties, PUBSUB_TCP_PASSIVE_CONFIGURED, false);
-        }
-        if (passiveKey == NULL) {
-            passiveKey = celix_properties_get(topicProperties, PUBSUB_TCP_PASSIVE_KEY, NULL);
-        }
-    }
-
-    // Set receiver connection thread timeout.
-    // property is in ms, timeout value in us. (convert ms to us).
-    receiver->timeout = celix_bundleContext_getPropertyAsLong(ctx, PSA_TCP_SUBSCRIBER_CONNECTION_TIMEOUT,
-                                                              PSA_TCP_SUBSCRIBER_CONNECTION_DEFAULT_TIMEOUT) * 1000;
-    /* When it's an endpoint share the socket with the sender */
-    if (passiveKey != NULL) {
-        celixThreadMutex_lock(&handlerStore->mutex);
-        pubsub_tcpHandler_t *entry = hashMap_get(handlerStore->map, passiveKey);
-        if (entry == NULL) {
-            if (receiver->socketHandler == NULL)
-                receiver->socketHandler = pubsub_tcpHandler_create(receiver->protocol, receiver->logHelper);
-            entry = receiver->socketHandler;
-            receiver->sharedSocketHandler = receiver->socketHandler;
-            hashMap_put(handlerStore->map, (void *) passiveKey, entry);
-        } else {
-            receiver->socketHandler = entry;
-            receiver->sharedSocketHandler = entry;
-        }
-        celixThreadMutex_unlock(&handlerStore->mutex);
-    } else {
-        receiver->socketHandler = pubsub_tcpHandler_create(receiver->protocol, receiver->logHelper);
-    }
-
-    if (receiver->socketHandler != NULL) {
-        long prio = celix_properties_getAsLong(topicProperties, PUBSUB_TCP_THREAD_REALTIME_PRIO, -1L);
-        const char *sched = celix_properties_get(topicProperties, PUBSUB_TCP_THREAD_REALTIME_SCHED, NULL);
-        long retryCnt = celix_properties_getAsLong(topicProperties, PUBSUB_TCP_SUBSCRIBER_RETRY_CNT_KEY,
-                                                   PUBSUB_TCP_SUBSCRIBER_RETRY_CNT_DEFAULT);
-        double rcvTimeout = celix_properties_getAsDouble(topicProperties, PUBSUB_TCP_SUBSCRIBER_RCVTIMEO_KEY, PUBSUB_TCP_SUBSCRIBER_RCVTIMEO_DEFAULT);
-        long bufferSize = celix_bundleContext_getPropertyAsLong(ctx, PSA_TCP_RECV_BUFFER_SIZE,
-                                                                 PSA_TCP_DEFAULT_RECV_BUFFER_SIZE);
-        long timeout = celix_bundleContext_getPropertyAsLong(ctx, PSA_TCP_TIMEOUT, PSA_TCP_DEFAULT_TIMEOUT);
-
-        pubsub_tcpHandler_setThreadName(receiver->socketHandler, topic, scope);
-        pubsub_tcpHandler_setReceiveBufferSize(receiver->socketHandler, (unsigned int) bufferSize);
-        pubsub_tcpHandler_setTimeout(receiver->socketHandler, (unsigned int) timeout);
-        pubsub_tcpHandler_addMessageHandler(receiver->socketHandler, receiver, processMsg);
-        pubsub_tcpHandler_addReceiverConnectionCallback(receiver->socketHandler, receiver, psa_tcp_connectHandler,
-                                                        psa_tcp_disConnectHandler);
-        pubsub_tcpHandler_setThreadPriority(receiver->socketHandler, prio, sched);
-        pubsub_tcpHandler_setReceiveRetryCnt(receiver->socketHandler, (unsigned int) retryCnt);
-        pubsub_tcpHandler_setReceiveTimeOut(receiver->socketHandler, rcvTimeout);
-    }
-    receiver->metricsEnabled = celix_bundleContext_getPropertyAsBool(ctx, PSA_TCP_METRICS_ENABLED,
-                                                                          PSA_TCP_DEFAULT_METRICS_ENABLED);
-    celixThreadMutex_create(&receiver->subscribers.mutex, NULL);
-    celixThreadMutex_create(&receiver->requestedConnections.mutex, NULL);
-    celixThreadMutex_create(&receiver->thread.mutex, NULL);
-
-    receiver->subscribers.map = hashMap_create(NULL, NULL, NULL, NULL);
-    receiver->requestedConnections.map = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-
-    if ((staticConnectUrls != NULL) && (receiver->socketHandler != NULL) && (!receiver->isPassive)) {
-        char *urlsCopy = strndup(staticConnectUrls, 1024 * 1024);
-        char *url;
-        char *save = urlsCopy;
-        while ((url = strtok_r(save, " ", &save))) {
-            psa_tcp_requested_connection_entry_t *entry = calloc(1, sizeof(*entry));
-            entry->statically = true;
-            entry->connected = false;
-            entry->url = strndup(url, 1024 * 1024);
-            entry->parent = receiver;
-            hashMap_put(receiver->requestedConnections.map, entry->url, entry);
-            receiver->requestedConnections.allConnected = false;
-        }
-        free(urlsCopy);
-    }
-
-    if (receiver->socketHandler != NULL && (!receiver->isPassive)) {
-        // Configure Receiver thread
-        receiver->thread.running = true;
-        celixThread_create(&receiver->thread.thread, NULL, psa_tcp_recvThread, receiver);
-        char name[64];
-        snprintf(name, 64, "TCP TR %s/%s", scope == NULL ? "(null)" : scope, topic);
-        celixThread_setName(&receiver->thread.thread, name);
-    }
-
-    //track subscribers
-    if (receiver->socketHandler != NULL) {
-        int size = snprintf(NULL, 0, "(%s=%s)", PUBSUB_SUBSCRIBER_TOPIC, topic);
-        char buf[size + 1];
-        snprintf(buf, (size_t) size + 1, "(%s=%s)", PUBSUB_SUBSCRIBER_TOPIC, topic);
-        celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
-        opts.filter.ignoreServiceLanguage = true;
-        opts.filter.serviceName = PUBSUB_SUBSCRIBER_SERVICE_NAME;
-        opts.filter.filter = buf;
-        opts.callbackHandle = receiver;
-        opts.addWithOwner = pubsub_tcpTopicReceiver_addSubscriber;
-        opts.removeWithOwner = pubsub_tcpTopicReceiver_removeSubscriber;
-        receiver->subscriberTrackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts);
-    }
-
-    if (receiver->socketHandler == NULL) {
-        if (receiver->scope != NULL) {
-            free(receiver->scope);
-        }
-        free(receiver->topic);
-        free(receiver);
-        receiver = NULL;
-        L_ERROR("[PSA_TCP] Cannot create TopicReceiver for %s/%s", scope == NULL ? "(null)" : scope, topic);
-    }
-    return receiver;
-}
-
-void pubsub_tcpTopicReceiver_destroy(pubsub_tcp_topic_receiver_t *receiver) {
-    if (receiver != NULL) {
-
-        celixThreadMutex_lock(&receiver->thread.mutex);
-        if (receiver->thread.running) {
-            receiver->thread.running = false;
-            celixThreadMutex_unlock(&receiver->thread.mutex);
-            celixThread_join(receiver->thread.thread, NULL);
-        }
-
-        celix_bundleContext_stopTracker(receiver->ctx, receiver->subscriberTrackerId);
-
-        celixThreadMutex_lock(&receiver->subscribers.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(receiver->subscribers.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_tcp_subscriber_entry_t *entry = hashMapIterator_nextValue(&iter);
-            if (entry != NULL) {
-                receiver->serializer->destroySerializerMap(receiver->serializer->handle, entry->msgTypes);
-                hashMap_destroy(entry->subscriberServices, false, false);
-                hash_map_iterator_t iter2 = hashMapIterator_construct(entry->metrics);
-                while (hashMapIterator_hasNext(&iter2)) {
-                    hash_map_t *origins = hashMapIterator_nextValue(&iter2);
-                    hashMap_destroy(origins, true, true);
-                }
-                hashMap_destroy(entry->metrics, false, false);
-                free(entry);
-            }
-        }
-        hashMap_destroy(receiver->subscribers.map, false, false);
-
-        celixThreadMutex_unlock(&receiver->subscribers.mutex);
-
-        celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-        iter = hashMapIterator_construct(receiver->requestedConnections.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_tcp_requested_connection_entry_t *entry = hashMapIterator_nextValue(&iter);
-            if (entry != NULL) {
-                free(entry->url);
-                free(entry);
-            }
-        }
-        hashMap_destroy(receiver->requestedConnections.map, false, false);
-        celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-
-        celixThreadMutex_destroy(&receiver->subscribers.mutex);
-        celixThreadMutex_destroy(&receiver->requestedConnections.mutex);
-        celixThreadMutex_destroy(&receiver->thread.mutex);
-
-        pubsub_tcpHandler_addMessageHandler(receiver->socketHandler, NULL, NULL);
-        pubsub_tcpHandler_addReceiverConnectionCallback(receiver->socketHandler, NULL, NULL, NULL);
-        if ((receiver->socketHandler) && (receiver->sharedSocketHandler == NULL)) {
-            pubsub_tcpHandler_destroy(receiver->socketHandler);
-            receiver->socketHandler = NULL;
-        }
-        if (receiver->scope != NULL) {
-            free(receiver->scope);
-        }
-        free(receiver->topic);
-    }
-    free(receiver);
-}
-
-const char *pubsub_tcpTopicReceiver_scope(pubsub_tcp_topic_receiver_t *receiver) {
-    return receiver->scope;
-}
-
-const char *pubsub_tcpTopicReceiver_topic(pubsub_tcp_topic_receiver_t *receiver) {
-    return receiver->topic;
-}
-
-long pubsub_tcpTopicReceiver_serializerSvcId(pubsub_tcp_topic_receiver_t *receiver) {
-    return receiver->serializerSvcId;
-}
-
-long pubsub_tcpTopicReceiver_protocolSvcId(pubsub_tcp_topic_receiver_t *receiver) {
-    return receiver->protocolSvcId;
-}
-
-void pubsub_tcpTopicReceiver_listConnections(pubsub_tcp_topic_receiver_t *receiver, celix_array_list_t *connectedUrls,
-                                             celix_array_list_t *unconnectedUrls) {
-    celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-    if (receiver->isPassive) {
-        char* interface_url = pubsub_tcpHandler_get_interface_url(receiver->socketHandler);
-        char *url = NULL;
-        asprintf(&url, "%s (passive)", interface_url ? interface_url : "");
-        if (interface_url) {
-            celix_arrayList_add(connectedUrls, url);
-        } else {
-            celix_arrayList_add(unconnectedUrls, url);
-        }
-        free(interface_url);
-    } else {
-        hash_map_iterator_t iter = hashMapIterator_construct(receiver->requestedConnections.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_tcp_requested_connection_entry_t *entry = hashMapIterator_nextValue(&iter);
-            char *url = NULL;
-            asprintf(&url, "%s%s", entry->url, entry->statically ? " (static)" : "");
-            if (entry->connected) {
-                celix_arrayList_add(connectedUrls, url);
-            } else {
-                celix_arrayList_add(unconnectedUrls, url);
-            }
-        }
-    }
-    celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-}
-
-bool pubsub_tcpTopicReceiver_isPassive(pubsub_tcp_topic_receiver_t *receiver) {
-    return receiver->isPassive;
-}
-
-void pubsub_tcpTopicReceiver_connectTo(
-    pubsub_tcp_topic_receiver_t *receiver,
-    const char *url) {
-    L_DEBUG("[PSA_TCP] TopicReceiver %s/%s connecting to tcp url %s",
-            receiver->scope == NULL ? "(null)" : receiver->scope,
-            receiver->topic,
-            url);
-
-    celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-    psa_tcp_requested_connection_entry_t *entry = hashMap_get(receiver->requestedConnections.map, url);
-    if (entry == NULL) {
-        entry = calloc(1, sizeof(*entry));
-        entry->url = strndup(url, 1024 * 1024);
-        entry->connected = false;
-        entry->statically = false;
-        entry->parent = receiver;
-        hashMap_put(receiver->requestedConnections.map, (void *) entry->url, entry);
-        receiver->requestedConnections.allConnected = false;
-    }
-    celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-
-    psa_tcp_connectToAllRequestedConnections(receiver);
-}
-
-void pubsub_tcpTopicReceiver_disconnectFrom(pubsub_tcp_topic_receiver_t *receiver, const char *url) {
-    L_DEBUG("[PSA TCP] TopicReceiver %s/%s disconnect from tcp url %s",
-            receiver->scope == NULL ? "(null)" : receiver->scope,
-            receiver->topic,
-            url);
-
-    celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-    psa_tcp_requested_connection_entry_t *entry = hashMap_remove(receiver->requestedConnections.map, url);
-    if (entry != NULL) {
-        int rc = pubsub_tcpHandler_disconnect(receiver->socketHandler, entry->url);
-        if (rc < 0)
-            L_WARN("[PSA_TCP] Error disconnecting from tcp url %s. (%s)", url, strerror(errno));
-    }
-    if (entry != NULL) {
-        free(entry->url);
-        free(entry);
-    }
-    celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-}
-
-static void pubsub_tcpTopicReceiver_addSubscriber(void *handle, void *svc, const celix_properties_t *props,
-                                                  const celix_bundle_t *bnd) {
-    pubsub_tcp_topic_receiver_t *receiver = handle;
-
-    long bndId = celix_bundle_getId(bnd);
-    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1);
-    const char *subScope = celix_properties_get(props, PUBSUB_SUBSCRIBER_SCOPE, NULL);
-    if (receiver->scope == NULL) {
-        if (subScope != NULL) {
-            return;
-        }
-    } else if (subScope != NULL) {
-        if (strncmp(subScope, receiver->scope, strlen(receiver->scope)) != 0) {
-            //not the same scope. ignore
-            return;
-        }
-    } else {
-        //receiver scope is not NULL, but subScope is NULL -> ignore
-        return;
-    }
-
-    celixThreadMutex_lock(&receiver->subscribers.mutex);
-    psa_tcp_subscriber_entry_t *entry = hashMap_get(receiver->subscribers.map, (void *) bndId);
-    if (entry != NULL) {
-        hashMap_put(entry->subscriberServices, (void*)svcId, svc);
-    } else {
-        //new create entry
-        entry = calloc(1, sizeof(*entry));
-        entry->subscriberServices = hashMap_create(NULL, NULL, NULL, NULL);
-        entry->initialized = false;
-        receiver->subscribers.allInitialized = false;
-
-        hashMap_put(entry->subscriberServices, (void*)svcId, svc);
-
-        int rc = receiver->serializer->createSerializerMap(receiver->serializer->handle, (celix_bundle_t *) bnd, &entry->msgTypes);
-
-        if (rc == 0) {
-            entry->metrics = hashMap_create(NULL, NULL, NULL, NULL);
-            hash_map_iterator_t iter = hashMapIterator_construct(entry->msgTypes);
-            while (hashMapIterator_hasNext(&iter)) {
-                pubsub_msg_serializer_t *msgSer = hashMapIterator_nextValue(&iter);
-                hash_map_t *origins = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-                hashMap_put(entry->metrics, (void *) (uintptr_t) msgSer->msgId, origins);
-            }
-        }
-
-        if (rc == 0) {
-            hashMap_put(receiver->subscribers.map, (void *) bndId, entry);
-        } else {
-            L_ERROR("[PSA_TCP] Cannot create msg serializer map for TopicReceiver %s/%s",
-                    receiver->scope == NULL ? "(null)" : receiver->scope,
-                    receiver->topic);
-            free(entry);
-        }
-    }
-    celixThreadMutex_unlock(&receiver->subscribers.mutex);
-}
-
-static void pubsub_tcpTopicReceiver_removeSubscriber(void *handle, void *svc __attribute__((unused)), const celix_properties_t *props,
-                                                     const celix_bundle_t *bnd) {
-    pubsub_tcp_topic_receiver_t *receiver = handle;
-
-    long bndId = celix_bundle_getId(bnd);
-    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1);
-
-    celixThreadMutex_lock(&receiver->subscribers.mutex);
-    psa_tcp_subscriber_entry_t *entry = hashMap_get(receiver->subscribers.map, (void *) bndId);
-    if (entry != NULL) {
-        hashMap_remove(entry->subscriberServices, (void*)svcId);
-    }
-    if (entry != NULL && hashMap_size(entry->subscriberServices) == 0) {
-        //remove entry
-        hashMap_remove(receiver->subscribers.map, (void *) bndId);
-        int rc = receiver->serializer->destroySerializerMap(receiver->serializer->handle, entry->msgTypes);
-        if (rc != 0) {
-            L_ERROR("[PSA_TCP] Cannot destroy msg serializers map for TopicReceiver %s/%s",
-                    receiver->scope == NULL ? "(null)" : receiver->scope,
-                    receiver->topic);
-        }
-        hash_map_iterator_t iter = hashMapIterator_construct(entry->metrics);
-        while (hashMapIterator_hasNext(&iter)) {
-            hash_map_t *origins = hashMapIterator_nextValue(&iter);
-            hashMap_destroy(origins, true, true);
-        }
-        hashMap_destroy(entry->metrics, false, false);
-        hashMap_destroy(entry->subscriberServices, false, false);
-        free(entry);
-    }
-    celixThreadMutex_unlock(&receiver->subscribers.mutex);
-}
-
-static inline void
-processMsgForSubscriberEntry(pubsub_tcp_topic_receiver_t *receiver, psa_tcp_subscriber_entry_t *entry,
-                             const pubsub_protocol_message_t *message, bool *releaseMsg, struct timespec *receiveTime __attribute__((unused))) {
-    //NOTE receiver->subscribers.mutex locked
-    pubsub_msg_serializer_t *msgSer = hashMap_get(entry->msgTypes, (void *) (uintptr_t) (message->header.msgId));
-    bool monitor = receiver->metricsEnabled;
-
-    //monitoring
-    struct timespec beginSer;
-    struct timespec endSer;
-    int updateReceiveCount = 0;
-    int updateSerError = 0;
-
-    if (msgSer != NULL) {
-        void *deSerializedMsg = NULL;
-        bool validVersion = psa_tcp_checkVersion(msgSer->msgVersion, message->header.msgMajorVersion,
-                                                 message->header.msgMinorVersion);
-        if (validVersion) {
-            if (monitor) {
-                clock_gettime(CLOCK_REALTIME, &beginSer);
-            }
-            struct iovec deSerializeBuffer;
-            deSerializeBuffer.iov_base = message->payload.payload;
-            deSerializeBuffer.iov_len = message->payload.length;
-            celix_status_t status = msgSer->deserialize(msgSer->handle, &deSerializeBuffer, 1, &deSerializedMsg);
-            if (monitor) {
-                clock_gettime(CLOCK_REALTIME, &endSer);
-            }
-            // When received payload pointer is the same as deserializedMsg, set ownership of pointer to topic receiver
-            if (message->payload.payload == deSerializedMsg) {
-                *releaseMsg = true;
-            }
-
-            if (status == CELIX_SUCCESS) {
-                bool release = true;
-                hash_map_iterator_t iter = hashMapIterator_construct(entry->subscriberServices);
-                while (hashMapIterator_hasNext(&iter)) {
-                    pubsub_subscriber_t *svc = hashMapIterator_nextValue(&iter);
-                    svc->receive(svc->handle, msgSer->msgName, msgSer->msgId, deSerializedMsg, message->metadata.metadata, &release);
-                    if (!release) {
-                        //receive function has taken ownership, deserialize again for new message
-                        status = msgSer->deserialize(msgSer->handle, &deSerializeBuffer, 1, &deSerializedMsg);
-                        if (status != CELIX_SUCCESS) {
-                            L_WARN("[PSA_TCP_TR] Cannot deserialize msg type %s for scope/topic %s/%s",
-                                   msgSer->msgName,
-                                   receiver->scope == NULL ? "(null)" : receiver->scope,
-                                   receiver->topic);
-                            break;
-                        }
-                        release = true;
-                    }
-                }
-                if (release) {
-                    msgSer->freeDeserializeMsg(msgSer->handle, deSerializedMsg);
-                }
-                if (message->metadata.metadata) {
-                    celix_properties_destroy(message->metadata.metadata);
-                }
-                updateReceiveCount += 1;
-            } else {
-                updateSerError += 1;
-                L_WARN("[PSA_TCP_TR] Cannot deserialize msg type %s for scope/topic %s/%s", msgSer->msgName,
-                       receiver->scope == NULL ? "(null)" : receiver->scope, receiver->topic);
-            }
-        }
-    } else {
-        L_WARN("[PSA_TCP_TR] Cannot find serializer for type id 0x%X. Received payload size is %u.", message->header.msgId, message->payload.length);
-    }
-}
-
-static void
-processMsg(void *handle, const pubsub_protocol_message_t *message, bool *release, struct timespec *receiveTime) {
-    pubsub_tcp_topic_receiver_t *receiver = handle;
-    celixThreadMutex_lock(&receiver->subscribers.mutex);
-    hash_map_iterator_t iter = hashMapIterator_construct(receiver->subscribers.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_tcp_subscriber_entry_t *entry = hashMapIterator_nextValue(&iter);
-        if (entry != NULL) {
-            processMsgForSubscriberEntry(receiver, entry, message, release, receiveTime);
-        }
-    }
-    celixThreadMutex_unlock(&receiver->subscribers.mutex);
-}
-
-static void *psa_tcp_recvThread(void *data) {
-    pubsub_tcp_topic_receiver_t *receiver = data;
-
-    celixThreadMutex_lock(&receiver->thread.mutex);
-    bool running = receiver->thread.running;
-    celixThreadMutex_unlock(&receiver->thread.mutex);
-
-    celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-    bool allConnected = receiver->requestedConnections.allConnected;
-    celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-
-    celixThreadMutex_lock(&receiver->subscribers.mutex);
-    bool allInitialized = receiver->subscribers.allInitialized;
-    celixThreadMutex_unlock(&receiver->subscribers.mutex);
-
-    while (running) {
-        if (!allConnected) {
-            psa_tcp_connectToAllRequestedConnections(receiver);
-        }
-        if (!allInitialized) {
-            psa_tcp_initializeAllSubscribers(receiver);
-        }
-        usleep(receiver->timeout);
-
-        celixThreadMutex_lock(&receiver->thread.mutex);
-        running = receiver->thread.running;
-        celixThreadMutex_unlock(&receiver->thread.mutex);
-
-        celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-        allConnected = receiver->requestedConnections.allConnected;
-        celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-
-        celixThreadMutex_lock(&receiver->subscribers.mutex);
-        allInitialized = receiver->subscribers.allInitialized;
-        celixThreadMutex_unlock(&receiver->subscribers.mutex);
-    } // while
-    return NULL;
-}
-
-pubsub_admin_receiver_metrics_t *pubsub_tcpTopicReceiver_metrics(pubsub_tcp_topic_receiver_t *receiver) {
-    pubsub_admin_receiver_metrics_t *result = calloc(1, sizeof(*result));
-    snprintf(result->scope, PUBSUB_AMDIN_METRICS_NAME_MAX, "%s", receiver->scope == NULL ? PUBSUB_DEFAULT_ENDPOINT_SCOPE : receiver->scope);
-    snprintf(result->topic, PUBSUB_AMDIN_METRICS_NAME_MAX, "%s", receiver->topic);
-
-    int msgTypesCount = 0;
-    celixThreadMutex_lock(&receiver->subscribers.mutex);
-    hash_map_iterator_t iter = hashMapIterator_construct(receiver->subscribers.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_tcp_subscriber_entry_t *entry = hashMapIterator_nextValue(&iter);
-        hash_map_iterator_t iter2 = hashMapIterator_construct(entry->metrics);
-        while (hashMapIterator_hasNext(&iter2)) {
-            hashMapIterator_nextValue(&iter2);
-            msgTypesCount += 1;
-        }
-    }
-
-    result->nrOfMsgTypes = (unsigned long) msgTypesCount;
-    result->msgTypes = calloc(msgTypesCount, sizeof(*result->msgTypes));
-    int i = 0;
-    iter = hashMapIterator_construct(receiver->subscribers.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_tcp_subscriber_entry_t *entry = hashMapIterator_nextValue(&iter);
-        hash_map_iterator_t iter2 = hashMapIterator_construct(entry->metrics);
-        while (hashMapIterator_hasNext(&iter2)) {
-            hash_map_t *origins = hashMapIterator_nextValue(&iter2);
-            result->msgTypes[i].origins = calloc((size_t) hashMap_size(origins), sizeof(*(result->msgTypes[i].origins)));
-            result->msgTypes[i].nrOfOrigins = hashMap_size(origins);
-            int k = 0;
-            hash_map_iterator_t iter3 = hashMapIterator_construct(origins);
-            while (hashMapIterator_hasNext(&iter3)) {
-                psa_tcp_subscriber_metrics_entry_t *metrics = hashMapIterator_nextValue(&iter3);
-                result->msgTypes[i].typeId = metrics->msgTypeId;
-                pubsub_msg_serializer_t *msgSer = hashMap_get(entry->msgTypes, (void *) (uintptr_t) metrics->msgTypeId);
-                if (msgSer) {
-                    snprintf(result->msgTypes[i].typeFqn, PUBSUB_AMDIN_METRICS_NAME_MAX, "%s", msgSer->msgName);
-                    uuid_copy(result->msgTypes[i].origins[k].originUUID, metrics->origin);
-                    result->msgTypes[i].origins[k].nrOfMessagesReceived = metrics->nrOfMessagesReceived;
-                    result->msgTypes[i].origins[k].nrOfSerializationErrors = metrics->nrOfSerializationErrors;
-                    result->msgTypes[i].origins[k].averageDelayInSeconds = metrics->averageDelayInSeconds;
-                    result->msgTypes[i].origins[k].maxDelayInSeconds = metrics->maxDelayInSeconds;
-                    result->msgTypes[i].origins[k].minDelayInSeconds = metrics->minDelayInSeconds;
-                    result->msgTypes[i].origins[k].averageTimeBetweenMessagesInSeconds = metrics->averageTimeBetweenMessagesInSeconds;
-                    result->msgTypes[i].origins[k].averageSerializationTimeInSeconds = metrics->averageSerializationTimeInSeconds;
-                    result->msgTypes[i].origins[k].lastMessageReceived = metrics->lastMessageReceived;
-                    result->msgTypes[i].origins[k].nrOfMissingSeqNumbers = metrics->nrOfMissingSeqNumbers;
-
-                    k += 1;
-                } else {
-                    L_WARN("[PSA_TCP]: Error cannot find key 0x%X in msg map during metrics collection!\n",
-                           metrics->msgTypeId);
-                }
-            }
-            i += 1;
-        }
-    }
-    celixThreadMutex_unlock(&receiver->subscribers.mutex);
-    return result;
-}
-
-static void psa_tcp_connectToAllRequestedConnections(pubsub_tcp_topic_receiver_t *receiver) {
-    celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-    if (!receiver->requestedConnections.allConnected) {
-        bool allConnected = true;
-        hash_map_iterator_t iter = hashMapIterator_construct(receiver->requestedConnections.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_tcp_requested_connection_entry_t *entry = hashMapIterator_nextValue(&iter);
-            if ((entry) && (!entry->connected) && (!receiver->isPassive)) {
-                int rc = pubsub_tcpHandler_connect(entry->parent->socketHandler, entry->url);
-                if (rc < 0) {
-                    allConnected = false;
-                }
-            }
-        }
-        receiver->requestedConnections.allConnected = allConnected;
-    }
-    celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-}
-
-static void psa_tcp_connectHandler(void *handle, const char *url, bool lock) {
-    pubsub_tcp_topic_receiver_t *receiver = handle;
-    L_DEBUG("[PSA_TCP] TopicReceiver %s/%s connecting to tcp url %s",
-            receiver->scope == NULL ? "(null)" : receiver->scope,
-            receiver->topic,
-            url);
-    if (lock)
-        celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-    psa_tcp_requested_connection_entry_t *entry = hashMap_get(receiver->requestedConnections.map, url);
-    if (entry == NULL) {
-        entry = calloc(1, sizeof(*entry));
-        entry->parent = receiver;
-        entry->url = strndup(url, 1024 * 1024);
-        entry->statically = true;
-        hashMap_put(receiver->requestedConnections.map, (void *) entry->url, entry);
-        receiver->requestedConnections.allConnected = false;
-    }
-    entry->connected = true;
-    if (lock)
-        celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-}
-
-static void psa_tcp_disConnectHandler(void *handle, const char *url, bool lock) {
-    pubsub_tcp_topic_receiver_t *receiver = handle;
-    L_DEBUG("[PSA TCP] TopicReceiver %s/%s disconnect from tcp url %s",
-            receiver->scope == NULL ? "(null)" : receiver->scope,
-            receiver->topic,
-            url);
-    if (lock)
-        celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-    psa_tcp_requested_connection_entry_t *entry = hashMap_get(receiver->requestedConnections.map, url);
-    if (entry != NULL) {
-        entry->connected = false;
-        receiver->requestedConnections.allConnected = false;
-    }
-    if (lock)
-        celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-}
-
-static void psa_tcp_initializeAllSubscribers(pubsub_tcp_topic_receiver_t *receiver) {
-    celixThreadMutex_lock(&receiver->subscribers.mutex);
-    if (!receiver->subscribers.allInitialized) {
-        bool allInitialized = true;
-        hash_map_iterator_t iter = hashMapIterator_construct(receiver->subscribers.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_tcp_subscriber_entry_t *entry = hashMapIterator_nextValue(&iter);
-            if (!entry->initialized) {
-                hash_map_iterator_t iter2 = hashMapIterator_construct(entry->subscriberServices);
-                while (hashMapIterator_hasNext(&iter2)) {
-                    pubsub_subscriber_t *svc = hashMapIterator_nextValue(&iter2);
-                    int rc = 0;
-                    if (svc != NULL && svc->init != NULL) {
-                        rc = svc->init(svc->handle);
-                    }
-                    if (rc == 0) {
-                        //note now only initialized on first subscriber entries added.
-                        entry->initialized = true;
-                    } else {
-                        L_WARN("Cannot initialize subscriber svc. Got rc %i", rc);
-                        allInitialized = false;
-                    }
-                }
-            }
-        }
-        receiver->subscribers.allInitialized = allInitialized;
-    }
-    celixThreadMutex_unlock(&receiver->subscribers.mutex);
-}
-
-static bool psa_tcp_checkVersion(version_pt msgVersion, uint16_t major, uint16_t minor) {
-    bool check = false;
-
-    if (major == 0 && minor == 0) {
-        //no check
-        return true;
-    }
-
-    int versionMajor;
-    int versionMinor;
-    if (msgVersion!=NULL) {
-        version_getMajor(msgVersion, &versionMajor);
-        version_getMinor(msgVersion, &versionMinor);
-        if (major==((unsigned char)versionMajor)) { /* Different major means incompatible */
-            check = (minor>=((unsigned char)versionMinor)); /* Compatible only if the provider has a minor equals or greater (means compatible update) */
-        }
-    }
-
-    return check;
-}
diff --git a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_topic_receiver.h b/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_topic_receiver.h
deleted file mode 100644
index 118bf11..0000000
--- a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_topic_receiver.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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_PUBSUB_TCP_TOPIC_RECEIVER_H
-#define CELIX_PUBSUB_TCP_TOPIC_RECEIVER_H
-
-#include <pubsub_admin_metrics.h>
-#include "celix_bundle_context.h"
-#include <pubsub_protocol.h>
-#include "pubsub_tcp_common.h"
-
-typedef struct pubsub_tcp_topic_receiver pubsub_tcp_topic_receiver_t;
-
-pubsub_tcp_topic_receiver_t *pubsub_tcpTopicReceiver_create(celix_bundle_context_t *ctx,
-                                                            celix_log_helper_t *logHelper,
-                                                            const char *scope,
-                                                            const char *topic,
-                                                            const celix_properties_t *topicProperties,
-                                                            pubsub_tcp_endPointStore_t *handlerStore,
-                                                            long serializerSvcId,
-                                                            pubsub_serializer_service_t *serializer,
-                                                            long protocolSvcId,
-                                                            pubsub_protocol_service_t *protocol);
-void pubsub_tcpTopicReceiver_destroy(pubsub_tcp_topic_receiver_t *receiver);
-
-const char *pubsub_tcpTopicReceiver_scope(pubsub_tcp_topic_receiver_t *receiver);
-const char *pubsub_tcpTopicReceiver_topic(pubsub_tcp_topic_receiver_t *receiver);
-
-long pubsub_tcpTopicReceiver_serializerSvcId(pubsub_tcp_topic_receiver_t *receiver);
-long pubsub_tcpTopicReceiver_protocolSvcId(pubsub_tcp_topic_receiver_t *receiver);
-void pubsub_tcpTopicReceiver_listConnections(pubsub_tcp_topic_receiver_t *receiver,
-                                             celix_array_list_t *connectedUrls,
-                                             celix_array_list_t *unconnectedUrls);
-bool pubsub_tcpTopicReceiver_isPassive(pubsub_tcp_topic_receiver_t *sender);
-
-void pubsub_tcpTopicReceiver_connectTo(pubsub_tcp_topic_receiver_t *receiver, const char *url);
-void pubsub_tcpTopicReceiver_disconnectFrom(pubsub_tcp_topic_receiver_t *receiver, const char *url);
-
-pubsub_admin_receiver_metrics_t *pubsub_tcpTopicReceiver_metrics(pubsub_tcp_topic_receiver_t *receiver);
-
-#endif //CELIX_PUBSUB_TCP_TOPIC_RECEIVER_H
diff --git a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_topic_sender.c b/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_topic_sender.c
deleted file mode 100644
index 7bea628..0000000
--- a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_topic_sender.c
+++ /dev/null
@@ -1,613 +0,0 @@
-/*
- * 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 <pubsub_serializer.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <memory.h>
-#include <pubsub_constants.h>
-#include <pubsub/publisher.h>
-#include <utils.h>
-#include <zconf.h>
-#include <arpa/inet.h>
-#include <celix_log_helper.h>
-#include "pubsub_psa_tcp_constants.h"
-#include "pubsub_tcp_topic_sender.h"
-#include "pubsub_tcp_handler.h"
-#include "pubsub_tcp_common.h"
-#include <uuid/uuid.h>
-#include "celix_constants.h"
-#include <pubsub_utils.h>
-
-#define TCP_BIND_MAX_RETRY                      10
-
-#define L_DEBUG(...) \
-    celix_logHelper_log(sender->logHelper, CELIX_LOG_LEVEL_DEBUG, __VA_ARGS__)
-#define L_INFO(...) \
-    celix_logHelper_log(sender->logHelper, CELIX_LOG_LEVEL_INFO, __VA_ARGS__)
-#define L_WARN(...) \
-    celix_logHelper_log(sender->logHelper, CELIX_LOG_LEVEL_WARNING, __VA_ARGS__)
-#define L_ERROR(...) \
-    celix_logHelper_log(sender->logHelper, CELIX_LOG_LEVEL_ERROR, __VA_ARGS__)
-
-struct pubsub_tcp_topic_sender {
-    celix_bundle_context_t *ctx;
-    celix_log_helper_t *logHelper;
-    long serializerSvcId;
-    pubsub_serializer_service_t *serializer;
-    long protocolSvcId;
-    pubsub_protocol_service_t *protocol;
-    uuid_t fwUUID;
-    bool metricsEnabled;
-    pubsub_tcpHandler_t *socketHandler;
-    pubsub_tcpHandler_t *sharedSocketHandler;
-
-    char *scope;
-    char *topic;
-    char *url;
-    bool isStatic;
-    bool isPassive;
-    bool verbose;
-    unsigned long send_delay;
-
-    struct {
-        long svcId;
-        celix_service_factory_t factory;
-    } publisher;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map;  //key = bndId, value = psa_tcp_bounded_service_entry_t
-    } boundedServices;
-};
-
-typedef struct psa_tcp_send_msg_entry {
-    uint32_t type; //msg type id (hash of fqn)
-    uint8_t major;
-    uint8_t minor;
-    unsigned char originUUID[16];
-    pubsub_msg_serializer_t *msgSer;
-    pubsub_protocol_service_t *protSer;
-    struct iovec *serializedIoVecOutput;
-    size_t serializedIoVecOutputLen;
-    unsigned int seqNr;
-    struct {
-        celix_thread_mutex_t mutex; //protects entries in struct
-        unsigned long nrOfMessagesSend;
-        unsigned long nrOfMessagesSendFailed;
-        unsigned long nrOfSerializationErrors;
-        struct timespec lastMessageSend;
-        double averageTimeBetweenMessagesInSeconds;
-        double averageSerializationTimeInSeconds;
-    } metrics;
-} psa_tcp_send_msg_entry_t;
-
-typedef struct psa_tcp_bounded_service_entry {
-    pubsub_tcp_topic_sender_t *parent;
-    pubsub_publisher_t service;
-    long bndId;
-    hash_map_t *msgTypes; //key = msg type id, value = pubsub_msg_serializer_t
-    hash_map_t *msgTypeIds; // key = msg name, value = msg type id
-    hash_map_t *msgEntries; //key = msg type id, value = psa_tcp_send_msg_entry_t
-    int getCount;
-} psa_tcp_bounded_service_entry_t;
-
-static int psa_tcp_localMsgTypeIdForMsgType(void *handle, const char *msgType, unsigned int *msgTypeId);
-
-static void *psa_tcp_getPublisherService(void *handle, const celix_bundle_t *requestingBundle,
-                                         const celix_properties_t *svcProperties);
-
-static void psa_tcp_ungetPublisherService(void *handle, const celix_bundle_t *requestingBundle,
-                                          const celix_properties_t *svcProperties);
-
-static void delay_first_send_for_late_joiners(pubsub_tcp_topic_sender_t *sender);
-
-static int
-psa_tcp_topicPublicationSend(void *handle, unsigned int msgTypeId, const void *msg, celix_properties_t *metadata);
-
-pubsub_tcp_topic_sender_t *pubsub_tcpTopicSender_create(
-    celix_bundle_context_t *ctx,
-    celix_log_helper_t *logHelper,
-    const char *scope,
-    const char *topic,
-    const celix_properties_t *topicProperties,
-    pubsub_tcp_endPointStore_t *handlerStore,
-    long serializerSvcId,
-    pubsub_serializer_service_t *ser,
-    long protocolSvcId,
-    pubsub_protocol_service_t *protocol) {
-    pubsub_tcp_topic_sender_t *sender = calloc(1, sizeof(*sender));
-    sender->ctx = ctx;
-    sender->logHelper = logHelper;
-    sender->serializerSvcId = serializerSvcId;
-    sender->serializer = ser;
-    sender->protocolSvcId = protocolSvcId;
-    sender->protocol = protocol;
-    const char *uuid = celix_bundleContext_getProperty(ctx, OSGI_FRAMEWORK_FRAMEWORK_UUID, NULL);
-    if (uuid != NULL) {
-        uuid_parse(uuid, sender->fwUUID);
-    }
-    sender->isPassive = false;
-    sender->metricsEnabled = celix_bundleContext_getPropertyAsBool(ctx, PSA_TCP_METRICS_ENABLED, PSA_TCP_DEFAULT_METRICS_ENABLED);
-    char *urls = NULL;
-    const char *ip = celix_bundleContext_getProperty(ctx, PUBSUB_TCP_PSA_IP_KEY, NULL);
-    const char *discUrl = pubsub_getEnvironmentVariableWithScopeTopic(ctx, PUBSUB_TCP_STATIC_BIND_URL_FOR, topic, scope);
-    const char *isPassive = pubsub_getEnvironmentVariableWithScopeTopic(ctx, PUBSUB_TCP_PASSIVE_ENABLED, topic, scope);
-    const char *passiveKey = pubsub_getEnvironmentVariableWithScopeTopic(ctx, PUBSUB_TCP_PASSIVE_SELECTION_KEY, topic, scope);
-
-    if (isPassive) {
-        sender->isPassive = psa_tcp_isPassive(isPassive);
-    }
-    if (topicProperties != NULL) {
-        if (discUrl == NULL) {
-            discUrl = celix_properties_get(topicProperties, PUBSUB_TCP_STATIC_DISCOVER_URL, NULL);
-        }
-        if (isPassive == NULL) {
-            sender->isPassive = celix_properties_getAsBool(topicProperties, PUBSUB_TCP_PASSIVE_CONFIGURED, false);
-        }
-        if (passiveKey == NULL) {
-            passiveKey = celix_properties_get(topicProperties, PUBSUB_TCP_PASSIVE_KEY, NULL);
-        }
-    }
-    /* When it's an endpoint share the socket with the receiver */
-    if (passiveKey != NULL) {
-        celixThreadMutex_lock(&handlerStore->mutex);
-        pubsub_tcpHandler_t *entry = hashMap_get(handlerStore->map, passiveKey);
-        if (entry == NULL) {
-            if (sender->socketHandler == NULL)
-                sender->socketHandler = pubsub_tcpHandler_create(sender->protocol, sender->logHelper);
-            entry = sender->socketHandler;
-            sender->sharedSocketHandler = sender->socketHandler;
-            hashMap_put(handlerStore->map, (void *) passiveKey, entry);
-        } else {
-            sender->socketHandler = entry;
-            sender->sharedSocketHandler = entry;
-        }
-        celixThreadMutex_unlock(&handlerStore->mutex);
-    } else {
-        sender->socketHandler = pubsub_tcpHandler_create(sender->protocol, sender->logHelper);
-    }
-
-    if ((sender->socketHandler != NULL) && (topicProperties != NULL)) {
-        long prio = celix_properties_getAsLong(topicProperties, PUBSUB_TCP_THREAD_REALTIME_PRIO, -1L);
-        const char *sched = celix_properties_get(topicProperties, PUBSUB_TCP_THREAD_REALTIME_SCHED, NULL);
-        long retryCnt = celix_properties_getAsLong(topicProperties, PUBSUB_TCP_PUBLISHER_RETRY_CNT_KEY, PUBSUB_TCP_PUBLISHER_RETRY_CNT_DEFAULT);
-        double sendTimeout = celix_properties_getAsDouble(topicProperties, PUBSUB_TCP_PUBLISHER_SNDTIMEO_KEY, PUBSUB_TCP_PUBLISHER_SNDTIMEO_DEFAULT);
-        long maxMsgSize = celix_properties_getAsLong(topicProperties, PSA_TCP_MAX_MESSAGE_SIZE, PSA_TCP_DEFAULT_MAX_MESSAGE_SIZE);
-        long timeout = celix_bundleContext_getPropertyAsLong(ctx, PSA_TCP_TIMEOUT, PSA_TCP_DEFAULT_TIMEOUT);
-        sender->send_delay = celix_bundleContext_getPropertyAsLong(ctx,  PUBSUB_UTILS_PSA_SEND_DELAY, PUBSUB_UTILS_PSA_DEFAULT_SEND_DELAY);
-        pubsub_tcpHandler_setThreadName(sender->socketHandler, topic, scope);
-        pubsub_tcpHandler_setThreadPriority(sender->socketHandler, prio, sched);
-        pubsub_tcpHandler_setSendRetryCnt(sender->socketHandler, (unsigned int) retryCnt);
-        pubsub_tcpHandler_setSendTimeOut(sender->socketHandler, sendTimeout);
-        pubsub_tcpHandler_setMaxMsgSize(sender->socketHandler, (unsigned int) maxMsgSize);
-        // Hhen passiveKey is specified, enable receive event for full-duplex connection using key.
-        // Because the topic receiver is already started, enable the receive event.
-        pubsub_tcpHandler_enableReceiveEvent(sender->socketHandler, (passiveKey) ? true : false);
-        pubsub_tcpHandler_setTimeout(sender->socketHandler, (unsigned int) timeout);
-    }
-
-    if (!sender->isPassive) {
-        //setting up tcp socket for TCP TopicSender
-        if (discUrl != NULL) {
-            urls = strndup(discUrl, 1024 * 1024);
-            sender->isStatic = true;
-        } else if (ip != NULL) {
-            urls = strndup(ip, 1024 * 1024);
-        } else {
-            struct sockaddr_in *sin = pubsub_utils_url_getInAddr(NULL, 0);
-            urls = pubsub_utils_url_get_url(sin, NULL);
-            free(sin);
-        }
-        if (!sender->url) {
-            char *urlsCopy = strndup(urls, 1024 * 1024);
-            char *url;
-            char *save = urlsCopy;
-            while ((url = strtok_r(save, " ", &save))) {
-                int retry = 0;
-                while (url && retry < TCP_BIND_MAX_RETRY) {
-                    pubsub_utils_url_t *urlInfo = pubsub_utils_url_parse(url);
-                    int rc = pubsub_tcpHandler_listen(sender->socketHandler, urlInfo->url);
-                    if (rc < 0) {
-                        L_WARN("Error for tcp_bind using dynamic bind url '%s'. %s", urlInfo->url, strerror(errno));
-                    } else {
-                        url = NULL;
-                    }
-                    pubsub_utils_url_free(urlInfo);
-                    retry++;
-                }
-            }
-            free(urlsCopy);
-            sender->url = pubsub_tcpHandler_get_interface_url(sender->socketHandler);
-        }
-        free(urls);
-    }
-
-    //register publisher services using a service factory
-    if ((sender->url != NULL) ||  (sender->isPassive)) {
-        sender->scope = scope == NULL ? NULL : strndup(scope, 1024 * 1024);
-        sender->topic = strndup(topic, 1024 * 1024);
-
-        celixThreadMutex_create(&sender->boundedServices.mutex, NULL);
-        sender->boundedServices.map = hashMap_create(NULL, NULL, NULL, NULL);
-
-        sender->publisher.factory.handle = sender;
-        sender->publisher.factory.getService = psa_tcp_getPublisherService;
-        sender->publisher.factory.ungetService = psa_tcp_ungetPublisherService;
-
-        celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, PUBSUB_PUBLISHER_TOPIC, sender->topic);
-        if (sender->scope != NULL) {
-            celix_properties_set(props, PUBSUB_PUBLISHER_SCOPE, sender->scope);
-        }
-
-        celix_service_registration_options_t opts = CELIX_EMPTY_SERVICE_REGISTRATION_OPTIONS;
-        opts.factory = &sender->publisher.factory;
-        opts.serviceName = PUBSUB_PUBLISHER_SERVICE_NAME;
-        opts.serviceVersion = PUBSUB_PUBLISHER_SERVICE_VERSION;
-        opts.properties = props;
-
-        sender->publisher.svcId = celix_bundleContext_registerServiceWithOptions(ctx, &opts);
-    } else {
-        free(sender);
-        sender = NULL;
-    }
-
-    return sender;
-}
-
-void pubsub_tcpTopicSender_destroy(pubsub_tcp_topic_sender_t *sender) {
-    if (sender != NULL) {
-
-        celix_bundleContext_unregisterService(sender->ctx, sender->publisher.svcId);
-
-        celixThreadMutex_lock(&sender->boundedServices.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(sender->boundedServices.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_tcp_bounded_service_entry_t *entry = hashMapIterator_nextValue(&iter);
-            if (entry != NULL) {
-                sender->serializer->destroySerializerMap(sender->serializer->handle, entry->msgTypes);
-                hash_map_iterator_t iter2 = hashMapIterator_construct(entry->msgEntries);
-                while (hashMapIterator_hasNext(&iter2)) {
-                    psa_tcp_send_msg_entry_t *msgEntry = hashMapIterator_nextValue(&iter2);
-                    if (msgEntry->serializedIoVecOutput)
-                        free(msgEntry->serializedIoVecOutput);
-                    msgEntry->serializedIoVecOutput = NULL;
-                    celixThreadMutex_destroy(&msgEntry->metrics.mutex);
-                    free(msgEntry);
-                }
-                hashMap_destroy(entry->msgEntries, false, false);
-                free(entry);
-            }
-        }
-        hashMap_destroy(sender->boundedServices.map, false, false);
-        celixThreadMutex_unlock(&sender->boundedServices.mutex);
-        celixThreadMutex_destroy(&sender->boundedServices.mutex);
-
-        if ((sender->socketHandler) && (sender->sharedSocketHandler == NULL)) {
-            pubsub_tcpHandler_destroy(sender->socketHandler);
-            sender->socketHandler = NULL;
-        }
-
-        if (sender->scope != NULL) {
-            free(sender->scope);
-        }
-        free(sender->topic);
-        free(sender->url);
-        free(sender);
-    }
-}
-
-long pubsub_tcpTopicSender_serializerSvcId(pubsub_tcp_topic_sender_t *sender) {
-    return sender->serializerSvcId;
-}
-
-long pubsub_tcpTopicSender_protocolSvcId(pubsub_tcp_topic_sender_t *sender) {
-    return sender->protocolSvcId;
-}
-
-const char *pubsub_tcpTopicSender_scope(pubsub_tcp_topic_sender_t *sender) {
-    return sender->scope;
-}
-
-const char *pubsub_tcpTopicSender_topic(pubsub_tcp_topic_sender_t *sender) {
-    return sender->topic;
-}
-
-const char *pubsub_tcpTopicSender_url(pubsub_tcp_topic_sender_t *sender) {
-    if (sender->isPassive) {
-        return pubsub_tcpHandler_get_connection_url(sender->socketHandler);
-    } else {
-        return sender->url;
-    }
-}
-bool pubsub_tcpTopicSender_isStatic(pubsub_tcp_topic_sender_t *sender) {
-    return sender->isStatic;
-}
-
-bool pubsub_tcpTopicSender_isPassive(pubsub_tcp_topic_sender_t *sender) {
-    return sender->isPassive;
-}
-
-void pubsub_tcpTopicSender_connectTo(pubsub_tcp_topic_sender_t *sender __attribute__((unused)), const celix_properties_t *endpoint __attribute__((unused))) {
-    //TODO subscriber count -> topic info
-}
-
-void pubsub_tcpTopicSender_disconnectFrom(pubsub_tcp_topic_sender_t *sender __attribute__((unused)), const celix_properties_t *endpoint __attribute__((unused))) {
-    //TODO
-}
-
-static int psa_tcp_localMsgTypeIdForMsgType(void *handle, const char *msgType, unsigned int *msgTypeId) {
-    psa_tcp_bounded_service_entry_t *entry = (psa_tcp_bounded_service_entry_t *) handle;
-    *msgTypeId = (unsigned int) (uintptr_t) hashMap_get(entry->msgTypeIds, msgType);
-    return 0;
-}
-
-static void *psa_tcp_getPublisherService(void *handle, const celix_bundle_t *requestingBundle,
-                                         const celix_properties_t *svcProperties __attribute__((unused))) {
-    pubsub_tcp_topic_sender_t *sender = handle;
-    long bndId = celix_bundle_getId(requestingBundle);
-
-    celixThreadMutex_lock(&sender->boundedServices.mutex);
-    psa_tcp_bounded_service_entry_t *entry = hashMap_get(sender->boundedServices.map, (void *) bndId);
-    if (entry != NULL) {
-        entry->getCount += 1;
-    } else {
-        entry = calloc(1, sizeof(*entry));
-        entry->getCount = 1;
-        entry->parent = sender;
-        entry->bndId = bndId;
-        entry->msgEntries = hashMap_create(NULL, NULL, NULL, NULL);
-        entry->msgTypeIds = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-
-        int rc = sender->serializer->createSerializerMap(sender->serializer->handle,
-                                                         (celix_bundle_t *) requestingBundle, &entry->msgTypes);
-        if (rc == 0) {
-            hash_map_iterator_t iter = hashMapIterator_construct(entry->msgTypes);
-            while (hashMapIterator_hasNext(&iter)) {
-                hash_map_entry_t *hashMapEntry = hashMapIterator_nextEntry(&iter);
-                void *key = hashMapEntry_getKey(hashMapEntry);
-                psa_tcp_send_msg_entry_t *sendEntry = calloc(1, sizeof(*sendEntry));
-                sendEntry->msgSer = hashMapEntry_getValue(hashMapEntry);
-                sendEntry->protSer = sender->protocol;
-                sendEntry->type = (int32_t) sendEntry->msgSer->msgId;
-                int major;
-                int minor;
-                version_getMajor(sendEntry->msgSer->msgVersion, &major);
-                version_getMinor(sendEntry->msgSer->msgVersion, &minor);
-                sendEntry->major = (uint8_t) major;
-                sendEntry->minor = (uint8_t) minor;
-                uuid_copy(sendEntry->originUUID, sender->fwUUID);
-                celixThreadMutex_create(&sendEntry->metrics.mutex, NULL);
-                hashMap_put(entry->msgEntries, key, sendEntry);
-                hashMap_put(entry->msgTypeIds, strndup(sendEntry->msgSer->msgName, 1024),
-                            (void *) (uintptr_t) sendEntry->msgSer->msgId);
-            }
-            entry->service.handle = entry;
-            entry->service.localMsgTypeIdForMsgType = psa_tcp_localMsgTypeIdForMsgType;
-            entry->service.send = psa_tcp_topicPublicationSend;
-            hashMap_put(sender->boundedServices.map, (void *) bndId, entry);
-        } else {
-            L_ERROR("Error creating serializer map for TCP TopicSender %s/%s", sender->scope == NULL ? "(null)" : sender->scope, sender->topic);
-        }
-    }
-    celixThreadMutex_unlock(&sender->boundedServices.mutex);
-
-    return &entry->service;
-}
-
-static void psa_tcp_ungetPublisherService(void *handle, const celix_bundle_t *requestingBundle,
-                                          const celix_properties_t *svcProperties __attribute__((unused))) {
-    pubsub_tcp_topic_sender_t *sender = handle;
-    long bndId = celix_bundle_getId(requestingBundle);
-
-    celixThreadMutex_lock(&sender->boundedServices.mutex);
-    psa_tcp_bounded_service_entry_t *entry = hashMap_get(sender->boundedServices.map, (void *) bndId);
-    if (entry != NULL) {
-        entry->getCount -= 1;
-    }
-    if (entry != NULL && entry->getCount == 0) {
-        //free entry
-        hashMap_remove(sender->boundedServices.map, (void *) bndId);
-        int rc = sender->serializer->destroySerializerMap(sender->serializer->handle, entry->msgTypes);
-        if (rc != 0) {
-            L_ERROR("Error destroying publisher service, serializer not available / cannot get msg serializer map\n");
-        }
-
-        hash_map_iterator_t iter = hashMapIterator_construct(entry->msgEntries);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_tcp_send_msg_entry_t *msgEntry = hashMapIterator_nextValue(&iter);
-            if (msgEntry->serializedIoVecOutput)
-                free(msgEntry->serializedIoVecOutput);
-            msgEntry->serializedIoVecOutput = NULL;
-            celixThreadMutex_destroy(&msgEntry->metrics.mutex);
-            free(msgEntry);
-        }
-        hashMap_destroy(entry->msgEntries, false, false);
-
-        hashMap_destroy(entry->msgTypeIds, true, false);
-        free(entry);
-    }
-    celixThreadMutex_unlock(&sender->boundedServices.mutex);
-
-}
-
-pubsub_admin_sender_metrics_t *pubsub_tcpTopicSender_metrics(pubsub_tcp_topic_sender_t *sender) {
-    pubsub_admin_sender_metrics_t *result = calloc(1, sizeof(*result));
-    snprintf(result->scope, PUBSUB_AMDIN_METRICS_NAME_MAX, "%s", sender->scope == NULL ? PUBSUB_DEFAULT_ENDPOINT_SCOPE : sender->scope);
-    snprintf(result->topic, PUBSUB_AMDIN_METRICS_NAME_MAX, "%s", sender->topic);
-    celixThreadMutex_lock(&sender->boundedServices.mutex);
-    size_t count = 0;
-    hash_map_iterator_t iter = hashMapIterator_construct(sender->boundedServices.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_tcp_bounded_service_entry_t *entry = hashMapIterator_nextValue(&iter);
-        hash_map_iterator_t iter2 = hashMapIterator_construct(entry->msgEntries);
-        while (hashMapIterator_hasNext(&iter2)) {
-            hashMapIterator_nextValue(&iter2);
-            count += 1;
-        }
-    }
-
-    result->msgMetrics = calloc(count, sizeof(*result));
-
-    iter = hashMapIterator_construct(sender->boundedServices.map);
-    int i = 0;
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_tcp_bounded_service_entry_t *entry = hashMapIterator_nextValue(&iter);
-        hash_map_iterator_t iter2 = hashMapIterator_construct(entry->msgEntries);
-        while (hashMapIterator_hasNext(&iter2)) {
-            psa_tcp_send_msg_entry_t *mEntry = hashMapIterator_nextValue(&iter2);
-            celixThreadMutex_lock(&mEntry->metrics.mutex);
-            result->msgMetrics[i].nrOfMessagesSend = mEntry->metrics.nrOfMessagesSend;
-            result->msgMetrics[i].nrOfMessagesSendFailed = mEntry->metrics.nrOfMessagesSendFailed;
-            result->msgMetrics[i].nrOfSerializationErrors = mEntry->metrics.nrOfSerializationErrors;
-            result->msgMetrics[i].averageSerializationTimeInSeconds = mEntry->metrics.averageSerializationTimeInSeconds;
-            result->msgMetrics[i].averageTimeBetweenMessagesInSeconds = mEntry->metrics.averageTimeBetweenMessagesInSeconds;
-            result->msgMetrics[i].lastMessageSend = mEntry->metrics.lastMessageSend;
-            result->msgMetrics[i].bndId = entry->bndId;
-            result->msgMetrics[i].typeId = mEntry->type;
-            snprintf(result->msgMetrics[i].typeFqn, PUBSUB_AMDIN_METRICS_NAME_MAX, "%s", mEntry->msgSer->msgName);
-            i += 1;
-            celixThreadMutex_unlock(&mEntry->metrics.mutex);
-        }
-    }
-
-    celixThreadMutex_unlock(&sender->boundedServices.mutex);
-    result->nrOfmsgMetrics = (int) count;
-    return result;
-}
-
-static int
-psa_tcp_topicPublicationSend(void *handle, unsigned int msgTypeId, const void *inMsg, celix_properties_t *metadata) {
-    int status = CELIX_SUCCESS;
-    psa_tcp_bounded_service_entry_t *bound = handle;
-    pubsub_tcp_topic_sender_t *sender = bound->parent;
-    bool monitor = sender->metricsEnabled;
-
-    psa_tcp_send_msg_entry_t *entry = hashMap_get(bound->msgEntries, (void *) (uintptr_t) (msgTypeId));
-
-    //metrics updates
-    struct timespec sendTime = {0, 0};
-    struct timespec serializationStart;
-    struct timespec serializationEnd;
-
-    int sendErrorUpdate = 0;
-    int serializationErrorUpdate = 0;
-    int sendCountUpdate = 0;
-
-    if (entry != NULL) {
-        delay_first_send_for_late_joiners(sender);
-        if (monitor) {
-            clock_gettime(CLOCK_REALTIME, &serializationStart);
-        }
-
-        size_t serializedIoVecOutputLen = 0; //entry->serializedIoVecOutputLen;
-        struct iovec *serializedIoVecOutput = NULL;
-        status = entry->msgSer->serialize(entry->msgSer->handle, inMsg, &serializedIoVecOutput,
-                                          &serializedIoVecOutputLen);
-        entry->serializedIoVecOutputLen = MAX(serializedIoVecOutputLen, entry->serializedIoVecOutputLen);
-
-        if (monitor) {
-            clock_gettime(CLOCK_REALTIME, &serializationEnd);
-        }
-
-        pubsub_protocol_message_t message;
-        message.metadata.metadata = NULL;
-        message.payload.payload = NULL;
-        message.payload.length = 0;
-        if (serializedIoVecOutput) {
-            message.payload.payload = serializedIoVecOutput->iov_base;
-            message.payload.length = serializedIoVecOutput->iov_len;
-        }
-        message.header.msgId = msgTypeId;
-        message.header.seqNr = entry->seqNr;
-        message.header.msgMajorVersion = entry->major;
-        message.header.msgMinorVersion = entry->minor;
-        message.header.payloadSize = 0;
-        message.header.payloadPartSize = 0;
-        message.header.payloadOffset = 0;
-        message.header.metadataSize = 0;
-        if (metadata != NULL)
-            message.metadata.metadata = metadata;
-        entry->seqNr++;
-        bool sendOk = true;
-        {
-            int rc = pubsub_tcpHandler_write(sender->socketHandler, &message, serializedIoVecOutput, serializedIoVecOutputLen, 0);
-            if (rc < 0) {
-                status = -1;
-                sendOk = false;
-            }
-            if (message.metadata.metadata)
-                celix_properties_destroy(message.metadata.metadata);
-            if (serializedIoVecOutput) {
-                entry->msgSer->freeSerializeMsg(entry->msgSer->handle,
-                                                serializedIoVecOutput,
-                                                serializedIoVecOutputLen);
-                serializedIoVecOutput = NULL;
-            }
-        }
-
-        if (sendOk) {
-            sendCountUpdate = 1;
-        } else {
-            sendErrorUpdate = 1;
-            L_WARN("[PSA_TCP_TS] Error sending msg. %s", strerror(errno));
-        }
-    } else {
-        //unknownMessageCountUpdate = 1;
-        status = CELIX_SERVICE_EXCEPTION;
-        L_WARN("[PSA_TCP_TS] Error cannot serialize message with msg type id %i for scope/topic %s/%s", msgTypeId,
-               sender->scope == NULL ? "(null)" : sender->scope, sender->topic);
-    }
-
-    if (monitor && entry != NULL) {
-        celixThreadMutex_lock(&entry->metrics.mutex);
-        long n = entry->metrics.nrOfMessagesSend + entry->metrics.nrOfMessagesSendFailed;
-        double diff = celix_difftime(&serializationStart, &serializationEnd);
-        double average = (entry->metrics.averageSerializationTimeInSeconds * n + diff) / (n + 1);
-        entry->metrics.averageSerializationTimeInSeconds = average;
-
-        if (entry->metrics.nrOfMessagesSend > 2) {
-            diff = celix_difftime(&entry->metrics.lastMessageSend, &sendTime);
-            n = entry->metrics.nrOfMessagesSend;
-            average = (entry->metrics.averageTimeBetweenMessagesInSeconds * n + diff) / (n + 1);
-            entry->metrics.averageTimeBetweenMessagesInSeconds = average;
-        }
-
-        entry->metrics.lastMessageSend = sendTime;
-        entry->metrics.nrOfMessagesSend += sendCountUpdate;
-        entry->metrics.nrOfMessagesSendFailed += sendErrorUpdate;
-        entry->metrics.nrOfSerializationErrors += serializationErrorUpdate;
-        celixThreadMutex_unlock(&entry->metrics.mutex);
-    }
-    return status;
-}
-
-static void delay_first_send_for_late_joiners(pubsub_tcp_topic_sender_t *sender) {
-
-    static bool firstSend = true;
-
-    if (firstSend) {
-        if (sender->send_delay ) {
-            L_INFO("PSA_TCP_TP: Delaying first send for late joiners...\n");
-        }
-        usleep(sender->send_delay * 1000);
-        firstSend = false;
-    }
-}
\ No newline at end of file
diff --git a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_topic_sender.h b/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_topic_sender.h
deleted file mode 100644
index 167c208..0000000
--- a/bundles/pubsub/pubsub_admin_tcp/v1/src/pubsub_tcp_topic_sender.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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_PUBSUB_TCP_TOPIC_SENDER_H
-#define CELIX_PUBSUB_TCP_TOPIC_SENDER_H
-
-#include "celix_bundle_context.h"
-#include "pubsub_admin_metrics.h"
-#include "pubsub_protocol.h"
-#include "pubsub_tcp_common.h"
-
-typedef struct pubsub_tcp_topic_sender pubsub_tcp_topic_sender_t;
-
-pubsub_tcp_topic_sender_t *pubsub_tcpTopicSender_create(
-    celix_bundle_context_t *ctx,
-    celix_log_helper_t *logHelper,
-    const char *scope,
-    const char *topic,
-    const celix_properties_t *topicProperties,
-    pubsub_tcp_endPointStore_t *handlerStore,
-    long serializerSvcId,
-    pubsub_serializer_service_t *ser,
-    long protocolSvcId,
-    pubsub_protocol_service_t *prot);
-
-void pubsub_tcpTopicSender_destroy(pubsub_tcp_topic_sender_t *sender);
-const char *pubsub_tcpTopicSender_scope(pubsub_tcp_topic_sender_t *sender);
-const char *pubsub_tcpTopicSender_topic(pubsub_tcp_topic_sender_t *sender);
-const char *pubsub_tcpTopicSender_url(pubsub_tcp_topic_sender_t *sender);
-bool pubsub_tcpTopicSender_isStatic(pubsub_tcp_topic_sender_t *sender);
-bool pubsub_tcpTopicSender_isPassive(pubsub_tcp_topic_sender_t *sender);
-long pubsub_tcpTopicSender_protocolSvcId(pubsub_tcp_topic_sender_t *sender);
-long pubsub_tcpTopicSender_serializerSvcId(pubsub_tcp_topic_sender_t *sender);
-/* Note this functions are deprecated and not used */
-void pubsub_tcpTopicSender_connectTo(pubsub_tcp_topic_sender_t *sender, const celix_properties_t *endpoint);
-/* Note this functions are deprecated and not used */
-void pubsub_tcpTopicSender_disconnectFrom(pubsub_tcp_topic_sender_t *sender, const celix_properties_t *endpoint);
-
-/**
- * Returns a array of pubsub_admin_sender_msg_type_metrics_t entries for every msg_type/bundle send with the topic sender.
- */
-pubsub_admin_sender_metrics_t *pubsub_tcpTopicSender_metrics(pubsub_tcp_topic_sender_t *sender);
-
-#endif //CELIX_PUBSUB_TCP_TOPIC_SENDER_H
diff --git a/bundles/pubsub/pubsub_admin_websocket/v2/CMakeLists.txt b/bundles/pubsub/pubsub_admin_websocket/CMakeLists.txt
similarity index 100%
rename from bundles/pubsub/pubsub_admin_websocket/v2/CMakeLists.txt
rename to bundles/pubsub/pubsub_admin_websocket/CMakeLists.txt
diff --git a/bundles/pubsub/pubsub_admin_websocket/v2/src/psa_activator.c b/bundles/pubsub/pubsub_admin_websocket/src/psa_activator.c
similarity index 100%
rename from bundles/pubsub/pubsub_admin_websocket/v2/src/psa_activator.c
rename to bundles/pubsub/pubsub_admin_websocket/src/psa_activator.c
diff --git a/bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_psa_websocket_constants.h b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_psa_websocket_constants.h
similarity index 100%
rename from bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_psa_websocket_constants.h
rename to bundles/pubsub/pubsub_admin_websocket/src/pubsub_psa_websocket_constants.h
diff --git a/bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_websocket_admin.c b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_admin.c
similarity index 100%
rename from bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_websocket_admin.c
rename to bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_admin.c
diff --git a/bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_websocket_admin.h b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_admin.h
similarity index 100%
rename from bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_websocket_admin.h
rename to bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_admin.h
diff --git a/bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_websocket_common.c b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_common.c
similarity index 100%
rename from bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_websocket_common.c
rename to bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_common.c
diff --git a/bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_websocket_common.h b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_common.h
similarity index 100%
rename from bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_websocket_common.h
rename to bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_common.h
diff --git a/bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_websocket_topic_receiver.c b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_receiver.c
similarity index 100%
rename from bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_websocket_topic_receiver.c
rename to bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_receiver.c
diff --git a/bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_websocket_topic_receiver.h b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_receiver.h
similarity index 100%
rename from bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_websocket_topic_receiver.h
rename to bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_receiver.h
diff --git a/bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_websocket_topic_sender.c b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_sender.c
similarity index 100%
rename from bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_websocket_topic_sender.c
rename to bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_sender.c
diff --git a/bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_websocket_topic_sender.h b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_sender.h
similarity index 100%
rename from bundles/pubsub/pubsub_admin_websocket/v2/src/pubsub_websocket_topic_sender.h
rename to bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_sender.h
diff --git a/bundles/pubsub/pubsub_admin_websocket/v1/CMakeLists.txt b/bundles/pubsub/pubsub_admin_websocket/v1/CMakeLists.txt
deleted file mode 100644
index a38ac85..0000000
--- a/bundles/pubsub/pubsub_admin_websocket/v1/CMakeLists.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-# 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.
-
-message(STATUS "PubSub Websocket Admin V1 is deprecated, and will eventually be replaced with PubSub Websocket Admin v2")
-
-find_package(Jansson REQUIRED)
-find_package(UUID REQUIRED)
-
-add_celix_bundle(celix_pubsub_admin_websocket
-    BUNDLE_SYMBOLICNAME "apache_celix_pubsub_admin_websocket"
-    VERSION "1.0.0"
-    GROUP "Celix/PubSub"
-    SOURCES
-        src/psa_activator.c
-        src/pubsub_websocket_admin.c
-        src/pubsub_websocket_topic_sender.c
-        src/pubsub_websocket_topic_receiver.c
-        src/pubsub_websocket_common.c
-)
-
-set_target_properties(celix_pubsub_admin_websocket PROPERTIES INSTALL_RPATH "$ORIGIN")
-target_link_libraries(celix_pubsub_admin_websocket PRIVATE
-        Celix::framework Celix::dfi Celix::log_helper Celix::utils
-        Celix::http_admin_api
-)
-target_link_libraries(celix_pubsub_admin_websocket PRIVATE Celix::pubsub_spi Celix::pubsub_utils )
-target_include_directories(celix_pubsub_admin_websocket PRIVATE
-    src
-)
-
-install_celix_bundle(celix_pubsub_admin_websocket EXPORT celix COMPONENT pubsub)
-target_link_libraries(celix_pubsub_admin_websocket PRIVATE Celix::shell_api)
-add_library(Celix::celix_pubsub_admin_websocket ALIAS celix_pubsub_admin_websocket)
diff --git a/bundles/pubsub/pubsub_admin_websocket/v1/src/psa_activator.c b/bundles/pubsub/pubsub_admin_websocket/v1/src/psa_activator.c
deleted file mode 100644
index 2f4b8cc..0000000
--- a/bundles/pubsub/pubsub_admin_websocket/v1/src/psa_activator.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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 <stdlib.h>
-
-#include "celix_api.h"
-#include "pubsub_serializer.h"
-#include "celix_log_helper.h"
-
-#include "pubsub_admin.h"
-#include "pubsub_admin_metrics.h"
-#include "pubsub_websocket_admin.h"
-#include "celix_shell_command.h"
-
-typedef struct psa_websocket_activator {
-    celix_log_helper_t *logHelper;
-
-    pubsub_websocket_admin_t *admin;
-
-    long serializersTrackerId;
-
-    pubsub_admin_service_t adminService;
-    long adminSvcId;
-
-    celix_shell_command_t cmdSvc;
-    long cmdSvcId;
-} psa_websocket_activator_t;
-
-int psa_websocket_start(psa_websocket_activator_t *act, celix_bundle_context_t *ctx) {
-    act->adminSvcId = -1L;
-    act->cmdSvcId = -1L;
-    act->serializersTrackerId = -1L;
-
-    act->logHelper = celix_logHelper_create(ctx, "celix_psa_admin_websocket");
-
-    act->admin = pubsub_websocketAdmin_create(ctx, act->logHelper);
-    celix_status_t status = act->admin != NULL ? CELIX_SUCCESS : CELIX_BUNDLE_EXCEPTION;
-
-    //track serializers (only json)
-    if (status == CELIX_SUCCESS) {
-        celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
-        opts.filter.serviceName = PUBSUB_SERIALIZER_SERVICE_NAME;
-        opts.filter.filter = "(pubsub.serializer=json)";
-        opts.filter.ignoreServiceLanguage = true;
-        opts.callbackHandle = act->admin;
-        opts.addWithProperties = pubsub_websocketAdmin_addSerializerSvc;
-        opts.removeWithProperties = pubsub_websocketAdmin_removeSerializerSvc;
-        act->serializersTrackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts);
-    }
-
-    //register pubsub admin service
-    if (status == CELIX_SUCCESS) {
-        pubsub_admin_service_t *psaSvc = &act->adminService;
-        psaSvc->handle = act->admin;
-        psaSvc->matchPublisher = pubsub_websocketAdmin_matchPublisher;
-        psaSvc->matchSubscriber = pubsub_websocketAdmin_matchSubscriber;
-        psaSvc->matchDiscoveredEndpoint = pubsub_websocketAdmin_matchDiscoveredEndpoint;
-        psaSvc->setupTopicSender = pubsub_websocketAdmin_setupTopicSender;
-        psaSvc->teardownTopicSender = pubsub_websocketAdmin_teardownTopicSender;
-        psaSvc->setupTopicReceiver = pubsub_websocketAdmin_setupTopicReceiver;
-        psaSvc->teardownTopicReceiver = pubsub_websocketAdmin_teardownTopicReceiver;
-        psaSvc->addDiscoveredEndpoint = pubsub_websocketAdmin_addDiscoveredEndpoint;
-        psaSvc->removeDiscoveredEndpoint = pubsub_websocketAdmin_removeDiscoveredEndpoint;
-
-        celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, PUBSUB_ADMIN_SERVICE_TYPE, PUBSUB_WEBSOCKET_ADMIN_TYPE);
-
-        act->adminSvcId = celix_bundleContext_registerService(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props);
-    }
-
-    //register shell command service
-    {
-        act->cmdSvc.handle = act->admin;
-        act->cmdSvc.executeCommand = pubsub_websocketAdmin_executeCommand;
-        celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psa_websocket");
-        celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psa_websocket");
-        celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the websocket PSA");
-        act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props);
-    }
-
-    return status;
-}
-
-int psa_websocket_stop(psa_websocket_activator_t *act, celix_bundle_context_t *ctx) {
-    celix_bundleContext_unregisterService(ctx, act->adminSvcId);
-    celix_bundleContext_unregisterService(ctx, act->cmdSvcId);
-    celix_bundleContext_stopTracker(ctx, act->serializersTrackerId);
-    pubsub_websocketAdmin_destroy(act->admin);
-
-    celix_logHelper_destroy(act->logHelper);
-
-    return CELIX_SUCCESS;
-}
-
-CELIX_GEN_BUNDLE_ACTIVATOR(psa_websocket_activator_t, psa_websocket_start, psa_websocket_stop);
diff --git a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_psa_websocket_constants.h b/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_psa_websocket_constants.h
deleted file mode 100644
index ada218b..0000000
--- a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_psa_websocket_constants.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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 PUBSUB_PSA_WEBSOCKET_CONSTANTS_H_
-#define PUBSUB_PSA_WEBSOCKET_CONSTANTS_H_
-
-#define PSA_WEBSOCKET_DEFAULT_QOS_SAMPLE_SCORE        30
-#define PSA_WEBSOCKET_DEFAULT_QOS_CONTROL_SCORE       70
-#define PSA_WEBSOCKET_DEFAULT_SCORE                   30
-
-#define PSA_WEBSOCKET_QOS_SAMPLE_SCORE_KEY            "PSA_WEBSOCKET_QOS_SAMPLE_SCORE"
-#define PSA_WEBSOCKET_QOS_CONTROL_SCORE_KEY           "PSA_WEBSOCKET_QOS_CONTROL_SCORE"
-#define PSA_WEBSOCKET_DEFAULT_SCORE_KEY               "PSA_WEBSOCKET_DEFAULT_SCORE"
-
-
-#define PSA_WEBSOCKET_METRICS_ENABLED                 "PSA_WEBSOCKET_METRICS_ENABLED"
-#define PSA_WEBSOCKET_DEFAULT_METRICS_ENABLED         true
-
-#define PUBSUB_WEBSOCKET_VERBOSE_KEY                  "PSA_WEBSOCKET_VERBOSE"
-#define PUBSUB_WEBSOCKET_VERBOSE_DEFAULT              true
-
-#define PUBSUB_WEBSOCKET_ADMIN_TYPE                   "websocket"
-#define PUBSUB_WEBSOCKET_ADDRESS_KEY                  "websocket.socket_address"
-#define PUBSUB_WEBSOCKET_PORT_KEY                     "websocket.socket_port"
-
-/**
- * The static url which a subscriber should try to connect to.
- * The urls are space separated
- */
-#define PUBSUB_WEBSOCKET_STATIC_CONNECT_SOCKET_ADDRESSES    "websocket.static.connect.socket_addresses"
-
-/**
- * Name of environment variable with space-separated list of ips/urls to connect to
- * e.g. PUBSUB_WEBSOCKET_STATIC_CONNECT_SOCKET_ADDRESSES_FOR_topic_scope="tcp://127.0.0.1:4444 tcp://127.0.0.2:4444"
- */
-#define PUBSUB_WEBSOCKET_STATIC_CONNECT_SOCKET_ADDRESSES_FOR "PUBSUB_WEBSOCKET_STATIC_CONNECT_SOCKET_ADDRESSES_FOR_"
-
-#endif /* PUBSUB_PSA_WEBSOCKET_CONSTANTS_H_ */
diff --git a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_admin.c b/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_admin.c
deleted file mode 100644
index 9c4633a..0000000
--- a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_admin.c
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * 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 <memory.h>
-#include <pubsub_endpoint.h>
-#include <pubsub_serializer.h>
-#include <ip_utils.h>
-
-#include "pubsub_utils.h"
-#include "pubsub_websocket_admin.h"
-#include "pubsub_psa_websocket_constants.h"
-#include "pubsub_websocket_topic_sender.h"
-#include "pubsub_websocket_topic_receiver.h"
-#include "pubsub_websocket_common.h"
-
-#define L_DEBUG(...) \
-    celix_logHelper_log(psa->log, CELIX_LOG_LEVEL_DEBUG, __VA_ARGS__)
-#define L_INFO(...) \
-    celix_logHelper_log(psa->log, CELIX_LOG_LEVEL_INFO, __VA_ARGS__)
-#define L_WARN(...) \
-    celix_logHelper_log(psa->log, CELIX_LOG_LEVEL_WARNING, __VA_ARGS__)
-#define L_ERROR(...) \
-    celix_logHelper_log(psa->log, CELIX_LOG_LEVEL_ERROR, __VA_ARGS__)
-
-struct pubsub_websocket_admin {
-    celix_bundle_context_t *ctx;
-    celix_log_helper_t *log;
-    const char *fwUUID;
-
-    double qosSampleScore;
-    double qosControlScore;
-    double defaultScore;
-
-    bool verbose;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = svcId, value = psa_websocket_serializer_entry_t*
-    } serializers;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = scope:topic key, value = pubsub_websocket_topic_sender_t*
-    } topicSenders;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = scope:topic key, value = pubsub_websocket_topic_sender_t*
-    } topicReceivers;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = endpoint uuid, value = celix_properties_t* (endpoint)
-    } discoveredEndpoints;
-
-};
-
-typedef struct psa_websocket_serializer_entry {
-    const char *serType;
-    long svcId;
-    pubsub_serializer_service_t *svc;
-} psa_websocket_serializer_entry_t;
-
-static celix_status_t pubsub_websocketAdmin_connectEndpointToReceiver(pubsub_websocket_admin_t* psa, pubsub_websocket_topic_receiver_t *receiver, const celix_properties_t *endpoint);
-static celix_status_t pubsub_websocketAdmin_disconnectEndpointFromReceiver(pubsub_websocket_admin_t* psa, pubsub_websocket_topic_receiver_t *receiver, const celix_properties_t *endpoint);
-
-
-pubsub_websocket_admin_t* pubsub_websocketAdmin_create(celix_bundle_context_t *ctx, celix_log_helper_t *logHelper) {
-    pubsub_websocket_admin_t *psa = calloc(1, sizeof(*psa));
-    psa->ctx = ctx;
-    psa->log = logHelper;
-    psa->verbose = celix_bundleContext_getPropertyAsBool(ctx, PUBSUB_WEBSOCKET_VERBOSE_KEY, PUBSUB_WEBSOCKET_VERBOSE_DEFAULT);
-    psa->fwUUID = celix_bundleContext_getProperty(ctx, OSGI_FRAMEWORK_FRAMEWORK_UUID, NULL);
-
-    psa->defaultScore = celix_bundleContext_getPropertyAsDouble(ctx, PSA_WEBSOCKET_DEFAULT_SCORE_KEY, PSA_WEBSOCKET_DEFAULT_SCORE);
-    psa->qosSampleScore = celix_bundleContext_getPropertyAsDouble(ctx, PSA_WEBSOCKET_QOS_SAMPLE_SCORE_KEY, PSA_WEBSOCKET_DEFAULT_QOS_SAMPLE_SCORE);
-    psa->qosControlScore = celix_bundleContext_getPropertyAsDouble(ctx, PSA_WEBSOCKET_QOS_CONTROL_SCORE_KEY, PSA_WEBSOCKET_DEFAULT_QOS_CONTROL_SCORE);
-
-    celixThreadMutex_create(&psa->serializers.mutex, NULL);
-    psa->serializers.map = hashMap_create(NULL, NULL, NULL, NULL);
-
-    celixThreadMutex_create(&psa->topicSenders.mutex, NULL);
-    psa->topicSenders.map = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-
-    celixThreadMutex_create(&psa->topicReceivers.mutex, NULL);
-    psa->topicReceivers.map = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-
-    celixThreadMutex_create(&psa->discoveredEndpoints.mutex, NULL);
-    psa->discoveredEndpoints.map = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-
-    return psa;
-}
-
-void pubsub_websocketAdmin_destroy(pubsub_websocket_admin_t *psa) {
-    if (psa == NULL) {
-        return;
-    }
-
-    //note assuming al psa register services and service tracker are removed.
-
-    celixThreadMutex_lock(&psa->topicSenders.mutex);
-    hash_map_iterator_t iter = hashMapIterator_construct(psa->topicSenders.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        pubsub_websocket_topic_sender_t *sender = hashMapIterator_nextValue(&iter);
-        pubsub_websocketTopicSender_destroy(sender);
-    }
-    celixThreadMutex_unlock(&psa->topicSenders.mutex);
-
-    celixThreadMutex_lock(&psa->topicReceivers.mutex);
-    iter = hashMapIterator_construct(psa->topicReceivers.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        pubsub_websocket_topic_receiver_t *recv = hashMapIterator_nextValue(&iter);
-        pubsub_websocketTopicReceiver_destroy(recv);
-    }
-    celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-
-    celixThreadMutex_lock(&psa->discoveredEndpoints.mutex);
-    iter = hashMapIterator_construct(psa->discoveredEndpoints.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        celix_properties_t *ep = hashMapIterator_nextValue(&iter);
-        celix_properties_destroy(ep);
-    }
-    celixThreadMutex_unlock(&psa->discoveredEndpoints.mutex);
-
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    iter = hashMapIterator_construct(psa->serializers.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_websocket_serializer_entry_t *entry = hashMapIterator_nextValue(&iter);
-        free(entry);
-    }
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-
-    celixThreadMutex_destroy(&psa->topicSenders.mutex);
-    hashMap_destroy(psa->topicSenders.map, true, false);
-
-    celixThreadMutex_destroy(&psa->topicReceivers.mutex);
-    hashMap_destroy(psa->topicReceivers.map, true, false);
-
-    celixThreadMutex_destroy(&psa->discoveredEndpoints.mutex);
-    hashMap_destroy(psa->discoveredEndpoints.map, false, false);
-
-    celixThreadMutex_destroy(&psa->serializers.mutex);
-    hashMap_destroy(psa->serializers.map, false, false);
-
-    free(psa);
-}
-
-void pubsub_websocketAdmin_addSerializerSvc(void *handle, void *svc, const celix_properties_t *props) {
-    pubsub_websocket_admin_t *psa = handle;
-
-    const char *serType = celix_properties_get(props, PUBSUB_SERIALIZER_TYPE_KEY, NULL);
-    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L);
-
-    if (serType == NULL) {
-        L_INFO("[PSA_WEBSOCKET] Ignoring serializer service without %s property", PUBSUB_SERIALIZER_TYPE_KEY);
-        return;
-    }
-
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    psa_websocket_serializer_entry_t *entry = hashMap_get(psa->serializers.map, (void*)svcId);
-    if (entry == NULL) {
-        entry = calloc(1, sizeof(*entry));
-        entry->serType = serType;
-        entry->svcId = svcId;
-        entry->svc = svc;
-        hashMap_put(psa->serializers.map, (void*)svcId, entry);
-    }
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-}
-
-void pubsub_websocketAdmin_removeSerializerSvc(void *handle, void *svc, const celix_properties_t *props) {
-    pubsub_websocket_admin_t *psa = handle;
-    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L);
-
-    //remove serializer
-    // 1) First find entry and
-    // 2) loop and destroy all topic sender using the serializer and
-    // 3) loop and destroy all topic receivers using the serializer
-    // Note that it is the responsibility of the topology manager to create new topic senders/receivers
-
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    psa_websocket_serializer_entry_t *entry = hashMap_remove(psa->serializers.map, (void*)svcId);
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-
-    if (entry != NULL) {
-        celixThreadMutex_lock(&psa->topicSenders.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(psa->topicSenders.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            hash_map_entry_t *senderEntry = hashMapIterator_nextEntry(&iter);
-            pubsub_websocket_topic_sender_t *sender = hashMapEntry_getValue(senderEntry);
-            if (sender != NULL && entry->svcId == pubsub_websocketTopicSender_serializerSvcId(sender)) {
-                char *key = hashMapEntry_getKey(senderEntry);
-                hashMapIterator_remove(&iter);
-                pubsub_websocketTopicSender_destroy(sender);
-                free(key);
-            }
-        }
-        celixThreadMutex_unlock(&psa->topicSenders.mutex);
-
-        celixThreadMutex_lock(&psa->topicReceivers.mutex);
-        iter = hashMapIterator_construct(psa->topicReceivers.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            hash_map_entry_t *senderEntry = hashMapIterator_nextEntry(&iter);
-            pubsub_websocket_topic_receiver_t *receiver = hashMapEntry_getValue(senderEntry);
-            if (receiver != NULL && entry->svcId == pubsub_websocketTopicReceiver_serializerSvcId(receiver)) {
-                char *key = hashMapEntry_getKey(senderEntry);
-                hashMapIterator_remove(&iter);
-                pubsub_websocketTopicReceiver_destroy(receiver);
-                free(key);
-            }
-        }
-        celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-
-        free(entry);
-    }
-}
-
-celix_status_t pubsub_websocketAdmin_matchPublisher(void *handle, long svcRequesterBndId, const celix_filter_t *svcFilter, celix_properties_t **topicProperties, double *outScore, long *outSerializerSvcId, long *outProtocolSvcId) {
-    pubsub_websocket_admin_t *psa = handle;
-    L_DEBUG("[PSA_WEBSOCKET] pubsub_websocketAdmin_matchPublisher");
-    celix_status_t  status = CELIX_SUCCESS;
-    double score = pubsubEndpoint_matchPublisher(psa->ctx, svcRequesterBndId, svcFilter->filterStr, PUBSUB_WEBSOCKET_ADMIN_TYPE,
-                                               psa->qosSampleScore, psa->qosControlScore, psa->defaultScore,
-                                               false, topicProperties, outSerializerSvcId, outProtocolSvcId);
-    *outScore = score;
-
-    return status;
-}
-
-celix_status_t pubsub_websocketAdmin_matchSubscriber(void *handle, long svcProviderBndId, const celix_properties_t *svcProperties, celix_properties_t **topicProperties, double *outScore, long *outSerializerSvcId, long *outProtocolSvcId) {
-    pubsub_websocket_admin_t *psa = handle;
-    L_DEBUG("[PSA_WEBSOCKET] pubsub_websocketAdmin_matchSubscriber");
-    celix_status_t  status = CELIX_SUCCESS;
-    double score = pubsubEndpoint_matchSubscriber(psa->ctx, svcProviderBndId, svcProperties, PUBSUB_WEBSOCKET_ADMIN_TYPE,
-                                                psa->qosSampleScore, psa->qosControlScore, psa->defaultScore,
-                                                false, topicProperties, outSerializerSvcId, outProtocolSvcId);
-    if (outScore != NULL) {
-        *outScore = score;
-    }
-    return status;
-}
-
-celix_status_t pubsub_websocketAdmin_matchDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint, bool *outMatch) {
-    pubsub_websocket_admin_t *psa = handle;
-    L_DEBUG("[PSA_WEBSOCKET] pubsub_websocketAdmin_matchEndpoint");
-    celix_status_t  status = CELIX_SUCCESS;
-    bool match = pubsubEndpoint_match(psa->ctx, psa->log, endpoint, PUBSUB_WEBSOCKET_ADMIN_TYPE, false, NULL, NULL);
-    if (outMatch != NULL) {
-        *outMatch = match;
-    }
-    return status;
-}
-
-celix_status_t pubsub_websocketAdmin_setupTopicSender(void *handle, const char *scope, const char *topic, const celix_properties_t *topicProperties, long serializerSvcId, long protocolSvcId, celix_properties_t **outPublisherEndpoint) {
-    pubsub_websocket_admin_t *psa = handle;
-    celix_status_t  status = CELIX_SUCCESS;
-
-    //1) Create TopicSender
-    //2) Store TopicSender
-    //3) Connect existing endpoints
-    //4) set outPublisherEndpoint
-
-    celix_properties_t *newEndpoint = NULL;
-
-    char *key = pubsubEndpoint_createScopeTopicKey(scope, topic);
-
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    celixThreadMutex_lock(&psa->topicSenders.mutex);
-    pubsub_websocket_topic_sender_t *sender = hashMap_get(psa->topicSenders.map, key);
-    if (sender == NULL) {
-        psa_websocket_serializer_entry_t *serEntry = hashMap_get(psa->serializers.map, (void*)serializerSvcId);
-        if (serEntry != NULL) {
-            sender = pubsub_websocketTopicSender_create(psa->ctx, psa->log, scope, topic, serializerSvcId, serEntry->svc);
-        }
-        if (sender != NULL) {
-            const char *psaType = PUBSUB_WEBSOCKET_ADMIN_TYPE;
-            const char *serType = serEntry->serType;
-            newEndpoint = pubsubEndpoint_create(psa->fwUUID, scope, topic, PUBSUB_PUBLISHER_ENDPOINT_TYPE, psaType,
-                                                serType, NULL, NULL);
-
-            //Set endpoint visibility to local because the http server handles discovery
-            celix_properties_set(newEndpoint, PUBSUB_ENDPOINT_VISIBILITY, PUBSUB_ENDPOINT_LOCAL_VISIBILITY);
-
-            //if available also set container name
-            const char *cn = celix_bundleContext_getProperty(psa->ctx, "CELIX_CONTAINER_NAME", NULL);
-            if (cn != NULL) {
-                celix_properties_set(newEndpoint, "container_name", cn);
-            }
-            hashMap_put(psa->topicSenders.map, key, sender);
-        } else {
-            L_ERROR("[PSA_WEBSOCKET] Error creating a TopicSender");
-            free(key);
-        }
-    } else {
-        free(key);
-        L_ERROR("[PSA_WEBSOCKET] Cannot setup already existing TopicSender for scope/topic %s/%s!", scope == NULL ? "(null)" : scope, topic);
-    }
-    celixThreadMutex_unlock(&psa->topicSenders.mutex);
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-
-    if (newEndpoint != NULL && outPublisherEndpoint != NULL) {
-        *outPublisherEndpoint = newEndpoint;
-    }
-
-    return status;
-}
-
-celix_status_t pubsub_websocketAdmin_teardownTopicSender(void *handle, const char *scope, const char *topic) {
-    pubsub_websocket_admin_t *psa = handle;
-    celix_status_t  status = CELIX_SUCCESS;
-
-    //1) Find and remove TopicSender from map
-    //2) destroy topic sender
-
-    char *key = pubsubEndpoint_createScopeTopicKey(scope, topic);
-    celixThreadMutex_lock(&psa->topicSenders.mutex);
-    hash_map_entry_t *entry = hashMap_getEntry(psa->topicSenders.map, key);
-    if (entry != NULL) {
-        char *mapKey = hashMapEntry_getKey(entry);
-        pubsub_websocket_topic_sender_t *sender = hashMap_remove(psa->topicSenders.map, key);
-        free(mapKey);
-        pubsub_websocketTopicSender_destroy(sender);
-    } else {
-        L_ERROR("[PSA_WEBSOCKET] Cannot teardown TopicSender with scope/topic %s/%s. Does not exists", scope == NULL ? "(null)" : scope, topic);
-    }
-    celixThreadMutex_unlock(&psa->topicSenders.mutex);
-    free(key);
-
-    return status;
-}
-
-celix_status_t pubsub_websocketAdmin_setupTopicReceiver(void *handle, const char *scope, const char *topic, const celix_properties_t *topicProperties, long serializerSvcId, long protocolSvcId, celix_properties_t **outSubscriberEndpoint) {
-    pubsub_websocket_admin_t *psa = handle;
-
-    celix_properties_t *newEndpoint = NULL;
-
-    char *key = pubsubEndpoint_createScopeTopicKey(scope, topic);
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    celixThreadMutex_lock(&psa->topicReceivers.mutex);
-    pubsub_websocket_topic_receiver_t *receiver = hashMap_get(psa->topicReceivers.map, key);
-    if (receiver == NULL) {
-        psa_websocket_serializer_entry_t *serEntry = hashMap_get(psa->serializers.map, (void*)serializerSvcId);
-        if (serEntry != NULL) {
-            receiver = pubsub_websocketTopicReceiver_create(psa->ctx, psa->log, scope, topic, topicProperties, serializerSvcId, serEntry->svc);
-        } else {
-            L_ERROR("[PSA_WEBSOCKET] Cannot find serializer for TopicSender %s/%s", scope == NULL ? "(null)" : scope, topic);
-        }
-        if (receiver != NULL) {
-            const char *psaType = PUBSUB_WEBSOCKET_ADMIN_TYPE;
-            const char *serType = serEntry->serType;
-            newEndpoint = pubsubEndpoint_create(psa->fwUUID, scope, topic,
-                                                PUBSUB_SUBSCRIBER_ENDPOINT_TYPE, psaType, serType, NULL, NULL);
-
-            //Set endpoint visibility to local because the http server handles discovery
-            celix_properties_set(newEndpoint, PUBSUB_ENDPOINT_VISIBILITY, PUBSUB_ENDPOINT_LOCAL_VISIBILITY);
-
-            //if available also set container name
-            const char *cn = celix_bundleContext_getProperty(psa->ctx, "CELIX_CONTAINER_NAME", NULL);
-            if (cn != NULL) {
-                celix_properties_set(newEndpoint, "container_name", cn);
-            }
-            hashMap_put(psa->topicReceivers.map, key, receiver);
-        } else {
-            L_ERROR("[PSA_WEBSOCKET] Error creating a TopicReceiver.");
-            free(key);
-        }
-    } else {
-        free(key);
-        L_ERROR("[PSA_WEBSOCKET] Cannot setup already existing TopicReceiver for scope/topic %s/%s!", scope == NULL ? "(null)" : scope, topic);
-    }
-    celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-
-    if (receiver != NULL && newEndpoint != NULL) {
-        celixThreadMutex_lock(&psa->discoveredEndpoints.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(psa->discoveredEndpoints.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            celix_properties_t *endpoint = hashMapIterator_nextValue(&iter);
-            const char *type = celix_properties_get(endpoint, PUBSUB_ENDPOINT_TYPE, NULL);
-            if (type != NULL && strncmp(PUBSUB_PUBLISHER_ENDPOINT_TYPE, type, strlen(PUBSUB_PUBLISHER_ENDPOINT_TYPE)) == 0 && pubsubEndpoint_matchWithTopicAndScope(endpoint, topic, scope)) {
-                pubsub_websocketAdmin_connectEndpointToReceiver(psa, receiver, endpoint);
-            }
-        }
-        celixThreadMutex_unlock(&psa->discoveredEndpoints.mutex);
-    }
-
-    if (newEndpoint != NULL && outSubscriberEndpoint != NULL) {
-        *outSubscriberEndpoint = newEndpoint;
-    }
-
-    celix_status_t status = CELIX_SUCCESS;
-    return status;
-}
-
-celix_status_t pubsub_websocketAdmin_teardownTopicReceiver(void *handle, const char *scope, const char *topic) {
-    pubsub_websocket_admin_t *psa = handle;
-
-    char *key = pubsubEndpoint_createScopeTopicKey(scope, topic);
-    celixThreadMutex_lock(&psa->topicReceivers.mutex);
-    hash_map_entry_t *entry = hashMap_getEntry(psa->topicReceivers.map, key);
-    free(key);
-    if (entry != NULL) {
-        char *receiverKey = hashMapEntry_getKey(entry);
-        pubsub_websocket_topic_receiver_t *receiver = hashMapEntry_getValue(entry);
-        hashMap_remove(psa->topicReceivers.map, receiverKey);
-
-        free(receiverKey);
-        pubsub_websocketTopicReceiver_destroy(receiver);
-    }
-    celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-
-    celix_status_t  status = CELIX_SUCCESS;
-    return status;
-}
-
-static celix_status_t pubsub_websocketAdmin_connectEndpointToReceiver(pubsub_websocket_admin_t* psa, pubsub_websocket_topic_receiver_t *receiver, const celix_properties_t *endpoint) {
-    //note can be called with discoveredEndpoint.mutex lock
-    celix_status_t status = CELIX_SUCCESS;
-
-    const char *type = celix_properties_get(endpoint, PUBSUB_ENDPOINT_TYPE, NULL);
-    const char *sockAddress = celix_properties_get(endpoint, PUBSUB_WEBSOCKET_ADDRESS_KEY, NULL);
-    long sockPort = celix_properties_getAsLong(endpoint, PUBSUB_WEBSOCKET_PORT_KEY, -1L);
-
-    bool publisher = type != NULL && strncmp(PUBSUB_PUBLISHER_ENDPOINT_TYPE, type, strlen(PUBSUB_PUBLISHER_ENDPOINT_TYPE)) == 0;
-
-    if (publisher && (sockAddress == NULL || sockPort < 0)) {
-        L_WARN("[PSA WEBSOCKET] Error got endpoint without websocket address/port or endpoint type. Properties:");
-        const char *key = NULL;
-        CELIX_PROPERTIES_FOR_EACH(endpoint, key) {
-            L_WARN("[PSA WEBSOCKET] |- %s=%s\n", key, celix_properties_get(endpoint, key, NULL));
-        }
-        status = CELIX_BUNDLE_EXCEPTION;
-    } else {
-        pubsub_websocketTopicReceiver_connectTo(receiver, sockAddress, sockPort);
-    }
-
-    return status;
-}
-
-celix_status_t pubsub_websocketAdmin_addDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint) {
-    pubsub_websocket_admin_t *psa = handle;
-
-    const char *type = celix_properties_get(endpoint, PUBSUB_ENDPOINT_TYPE, NULL);
-
-    if (type != NULL && strncmp(PUBSUB_PUBLISHER_ENDPOINT_TYPE, type, strlen(PUBSUB_PUBLISHER_ENDPOINT_TYPE)) == 0) {
-        celixThreadMutex_lock(&psa->topicReceivers.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(psa->topicReceivers.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            pubsub_websocket_topic_receiver_t *receiver = hashMapIterator_nextValue(&iter);
-            if (pubsubEndpoint_matchWithTopicAndScope(endpoint, pubsub_websocketTopicReceiver_topic(receiver), pubsub_websocketTopicReceiver_scope(receiver))) {
-                pubsub_websocketAdmin_connectEndpointToReceiver(psa, receiver, endpoint);
-            }
-        }
-        celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-    }
-
-    celixThreadMutex_lock(&psa->discoveredEndpoints.mutex);
-    celix_properties_t *cpy = celix_properties_copy(endpoint);
-    const char *uuid = celix_properties_get(cpy, PUBSUB_ENDPOINT_UUID, NULL);
-    hashMap_put(psa->discoveredEndpoints.map, (void*)uuid, cpy);
-    celixThreadMutex_unlock(&psa->discoveredEndpoints.mutex);
-
-    celix_status_t  status = CELIX_SUCCESS;
-    return status;
-}
-
-
-static celix_status_t pubsub_websocketAdmin_disconnectEndpointFromReceiver(pubsub_websocket_admin_t* psa, pubsub_websocket_topic_receiver_t *receiver, const celix_properties_t *endpoint) {
-    //note can be called with discoveredEndpoint.mutex lock
-    celix_status_t status = CELIX_SUCCESS;
-
-    const char *scope = pubsub_websocketTopicReceiver_scope(receiver);
-    const char *topic = pubsub_websocketTopicReceiver_topic(receiver);
-
-    const char *type = celix_properties_get(endpoint, PUBSUB_ENDPOINT_TYPE, NULL);
-    const char *eScope = celix_properties_get(endpoint, PUBSUB_ENDPOINT_TOPIC_SCOPE, NULL);
-    const char *eTopic = celix_properties_get(endpoint, PUBSUB_ENDPOINT_TOPIC_NAME, NULL);
-    const char *sockAddress = celix_properties_get(endpoint, PUBSUB_WEBSOCKET_ADDRESS_KEY, NULL);
-    long sockPort = celix_properties_getAsLong(endpoint, PUBSUB_WEBSOCKET_PORT_KEY, -1L);
-
-    bool publisher = type != NULL && strncmp(PUBSUB_PUBLISHER_ENDPOINT_TYPE, type, strlen(PUBSUB_PUBLISHER_ENDPOINT_TYPE)) == 0;
-
-    if (publisher && (sockAddress == NULL || sockPort < 0)) {
-        L_WARN("[PSA WEBSOCKET] Error got endpoint without websocket address/port or endpoint type. Properties:");
-        const char *key = NULL;
-        CELIX_PROPERTIES_FOR_EACH(endpoint, key) {
-            L_WARN("[PSA WEBSOCKET] |- %s=%s\n", key, celix_properties_get(endpoint, key, NULL));
-        }
-        status = CELIX_BUNDLE_EXCEPTION;
-    } else if (eTopic != NULL && strncmp(eTopic, topic, 1024 * 1024) == 0) {
-        if ((scope == NULL && eScope == NULL) || (scope != NULL && eScope != NULL && strncmp(eScope, scope, 1024 * 1024) == 0)) {
-            pubsub_websocketTopicReceiver_disconnectFrom(receiver, sockAddress, sockPort);
-        }
-    }
-
-    return status;
-}
-
-celix_status_t pubsub_websocketAdmin_removeDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint) {
-    pubsub_websocket_admin_t *psa = handle;
-
-    const char *type = celix_properties_get(endpoint, PUBSUB_ENDPOINT_TYPE, NULL);
-
-    if (type != NULL && strncmp(PUBSUB_PUBLISHER_ENDPOINT_TYPE, type, strlen(PUBSUB_PUBLISHER_ENDPOINT_TYPE)) == 0) {
-        celixThreadMutex_lock(&psa->topicReceivers.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(psa->topicReceivers.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            pubsub_websocket_topic_receiver_t *receiver = hashMapIterator_nextValue(&iter);
-            pubsub_websocketAdmin_disconnectEndpointFromReceiver(psa, receiver, endpoint);
-        }
-        celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-    }
-
-    celixThreadMutex_lock(&psa->discoveredEndpoints.mutex);
-    const char *uuid = celix_properties_get(endpoint, PUBSUB_ENDPOINT_UUID, NULL);
-    celix_properties_t *found = hashMap_remove(psa->discoveredEndpoints.map, (void*)uuid);
-    celixThreadMutex_unlock(&psa->discoveredEndpoints.mutex);
-
-    if (found != NULL) {
-        celix_properties_destroy(found);
-    }
-
-    celix_status_t  status = CELIX_SUCCESS;
-    return status;
-}
-
-bool pubsub_websocketAdmin_executeCommand(void *handle, const char *commandLine __attribute__((unused)), FILE *out, FILE *errStream __attribute__((unused))) {
-    pubsub_websocket_admin_t *psa = handle;
-
-    fprintf(out, "\n");
-    fprintf(out, "Topic Senders:\n");
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    celixThreadMutex_lock(&psa->topicSenders.mutex);
-    hash_map_iterator_t iter = hashMapIterator_construct(psa->topicSenders.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        pubsub_websocket_topic_sender_t *sender = hashMapIterator_nextValue(&iter);
-        long serSvcId = pubsub_websocketTopicSender_serializerSvcId(sender);
-        psa_websocket_serializer_entry_t *serEntry = hashMap_get(psa->serializers.map, (void*)serSvcId);
-        const char *serType = serEntry == NULL ? "!Error!" : serEntry->serType;
-        const char *scope = pubsub_websocketTopicSender_scope(sender);
-        const char *topic = pubsub_websocketTopicSender_topic(sender);
-        const char *url = pubsub_websocketTopicSender_url(sender);
-        fprintf(out, "|- Topic Sender %s/%s\n", scope == NULL ? "(null)" : scope, topic);
-        fprintf(out, "   |- serializer type = %s\n", serType);
-        fprintf(out, "   |- url             = %s\n", url);
-    }
-    celixThreadMutex_unlock(&psa->topicSenders.mutex);
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-
-    fprintf(out, "\n");
-    fprintf(out, "\nTopic Receivers:\n");
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    celixThreadMutex_lock(&psa->topicReceivers.mutex);
-    iter = hashMapIterator_construct(psa->topicReceivers.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        pubsub_websocket_topic_receiver_t *receiver = hashMapIterator_nextValue(&iter);
-        long serSvcId = pubsub_websocketTopicReceiver_serializerSvcId(receiver);
-        psa_websocket_serializer_entry_t *serEntry = hashMap_get(psa->serializers.map, (void*)serSvcId);
-        const char *serType = serEntry == NULL ? "!Error!" : serEntry->serType;
-        const char *scope = pubsub_websocketTopicReceiver_scope(receiver);
-        const char *topic = pubsub_websocketTopicReceiver_topic(receiver);
-        const char *urlEndp = pubsub_websocketTopicReceiver_url(receiver);
-
-        celix_array_list_t *connected = celix_arrayList_create();
-        celix_array_list_t *unconnected = celix_arrayList_create();
-        pubsub_websocketTopicReceiver_listConnections(receiver, connected, unconnected);
-
-        fprintf(out, "|- Topic Receiver %s/%s\n", scope == NULL ? "(null)" : scope, topic);
-        fprintf(out, "   |- serializer type      = %s\n", serType);
-        fprintf(out, "   |- url                  = %s\n", urlEndp);
-        for (int i = 0; i < celix_arrayList_size(connected); ++i) {
-            char *url = celix_arrayList_get(connected, i);
-            fprintf(out, "   |- connected endpoint   = %s\n", url);
-            free(url);
-        }
-        for (int i = 0; i < celix_arrayList_size(unconnected); ++i) {
-            char *url = celix_arrayList_get(unconnected, i);
-            fprintf(out, "   |- unconnected endpoint = %s\n", url);
-            free(url);
-        }
-        celix_arrayList_destroy(connected);
-        celix_arrayList_destroy(unconnected);
-    }
-    celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-    fprintf(out, "\n");
-
-    return true;
-}
diff --git a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_admin.h b/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_admin.h
deleted file mode 100644
index bae6333..0000000
--- a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_admin.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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_PUBSUB_WEBSOCKET_ADMIN_H
-#define CELIX_PUBSUB_WEBSOCKET_ADMIN_H
-
-#include <pubsub_admin_metrics.h>
-#include "celix_api.h"
-#include "celix_log_helper.h"
-#include "pubsub_psa_websocket_constants.h"
-
-typedef struct pubsub_websocket_admin pubsub_websocket_admin_t;
-
-pubsub_websocket_admin_t* pubsub_websocketAdmin_create(celix_bundle_context_t *ctx, celix_log_helper_t *logHelper);
-void pubsub_websocketAdmin_destroy(pubsub_websocket_admin_t *psa);
-
-celix_status_t pubsub_websocketAdmin_matchPublisher(void *handle, long svcRequesterBndId, const celix_filter_t *svcFilter, celix_properties_t **topicProperties, double *score, long *serializerSvcId, long *protocolSvcId);
-celix_status_t pubsub_websocketAdmin_matchSubscriber(void *handle, long svcProviderBndId, const celix_properties_t *svcProperties, celix_properties_t **topicProperties, double *score, long *serializerSvcId, long *protocolSvcId);
-celix_status_t pubsub_websocketAdmin_matchDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint, bool *match);
-
-celix_status_t pubsub_websocketAdmin_setupTopicSender(void *handle, const char *scope, const char *topic, const celix_properties_t* topicProperties, long serializerSvcId, long protocolSvcId, celix_properties_t **publisherEndpoint);
-celix_status_t pubsub_websocketAdmin_teardownTopicSender(void *handle, const char *scope, const char *topic);
-
-celix_status_t pubsub_websocketAdmin_setupTopicReceiver(void *handle, const char *scope, const char *topic, const celix_properties_t* topicProperties, long serializerSvcId, long protocolSvcId, celix_properties_t **subscriberEndpoint);
-celix_status_t pubsub_websocketAdmin_teardownTopicReceiver(void *handle, const char *scope, const char *topic);
-
-celix_status_t pubsub_websocketAdmin_addDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint);
-celix_status_t pubsub_websocketAdmin_removeDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint);
-
-void pubsub_websocketAdmin_addSerializerSvc(void *handle, void *svc, const celix_properties_t *props);
-void pubsub_websocketAdmin_removeSerializerSvc(void *handle, void *svc, const celix_properties_t *props);
-
-bool pubsub_websocketAdmin_executeCommand(void *handle, const char *commandLine, FILE *outStream, FILE *errStream);
-
-#endif //CELIX_PUBSUB_WEBSOCKET_ADMIN_H
-
diff --git a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_common.c b/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_common.c
deleted file mode 100644
index fe389bc..0000000
--- a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_common.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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 <memory.h>
-#include <assert.h>
-#include <stdio.h>
-#include "pubsub_websocket_common.h"
-
-bool psa_websocket_checkVersion(version_pt msgVersion, const pubsub_websocket_msg_header_t *hdr) {
-    bool check=false;
-    int major=0,minor=0;
-
-    if (hdr->major == 0 && hdr->minor == 0) {
-        //no check
-        return true;
-    }
-
-    if (msgVersion!=NULL) {
-        version_getMajor(msgVersion,&major);
-        version_getMinor(msgVersion,&minor);
-        if (hdr->major==((unsigned char)major)) { /* Different major means incompatible */
-            check = (hdr->minor>=((unsigned char)minor)); /* Compatible only if the provider has a minor equals or greater (means compatible update) */
-        }
-    }
-
-    return check;
-}
-
-void psa_websocket_setScopeAndTopicFilter(const char* scope, const char *topic, char *filter) {
-    for (int i = 0; i < 5; ++i) {
-        filter[i] = '\0';
-    }
-    if (scope != NULL && strnlen(scope, 3) >= 2)  {
-        filter[0] = scope[0];
-        filter[1] = scope[1];
-    }
-    if (topic != NULL && strnlen(topic, 3) >= 2)  {
-        filter[2] = topic[0];
-        filter[3] = topic[1];
-    }
-}
-
-char *psa_websocket_createURI(const char *scope, const char *topic) {
-    char *uri = NULL;
-    if(scope != NULL && topic != NULL) {
-        asprintf(&uri, "/pubsub/%s/%s", scope, topic);
-    }
-    else if(scope == NULL && topic != NULL) {
-        asprintf(&uri, "/pubsub/default/%s", topic);
-    }
-    return uri;
-}
diff --git a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_common.h b/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_common.h
deleted file mode 100644
index 4c22319..0000000
--- a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_common.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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_PUBSUB_WEBSOCKET_COMMON_H
-#define CELIX_PUBSUB_WEBSOCKET_COMMON_H
-
-#include <utils.h>
-#include <stdint.h>
-
-#include "version.h"
-
-
-struct pubsub_websocket_msg_header {
-    const char *id; //FQN
-    uint8_t major;
-    uint8_t minor;
-    uint32_t seqNr;
-};
-
-typedef struct pubsub_websocket_msg_header pubsub_websocket_msg_header_t;
-
-void psa_websocket_setScopeAndTopicFilter(const char* scope, const char *topic, char *filter);
-char *psa_websocket_createURI(const char *scope, const char *topic);
-
-bool psa_websocket_checkVersion(version_pt msgVersion, const pubsub_websocket_msg_header_t *hdr);
-
-#endif //CELIX_PUBSUB_WEBSOCKET_COMMON_H
diff --git a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_topic_receiver.c b/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_topic_receiver.c
deleted file mode 100644
index 7b2cfcc..0000000
--- a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_topic_receiver.c
+++ /dev/null
@@ -1,774 +0,0 @@
-/*
- * 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 <pubsub_serializer.h>
-#include <stdlib.h>
-#include <pubsub/subscriber.h>
-#include <memory.h>
-#include <pubsub_constants.h>
-#include <assert.h>
-#include <pubsub_endpoint.h>
-#include <arpa/inet.h>
-#include <celix_log_helper.h>
-#include <math.h>
-#include "pubsub_websocket_topic_receiver.h"
-#include "pubsub_psa_websocket_constants.h"
-#include "pubsub_websocket_common.h"
-
-#include <uuid/uuid.h>
-#include <http_admin/api.h>
-#include <jansson.h>
-#include <pubsub_utils.h>
-#include <celix_api.h>
-
-#ifndef UUID_STR_LEN
-#define UUID_STR_LEN 37
-#endif
-
-
-#define L_DEBUG(...) \
-    celix_logHelper_log(receiver->logHelper, CELIX_LOG_LEVEL_DEBUG, __VA_ARGS__)
-#define L_INFO(...) \
-    celix_logHelper_log(receiver->logHelper, CELIX_LOG_LEVEL_INFO, __VA_ARGS__)
-#define L_WARN(...) \
-    celix_logHelper_log(receiver->logHelper, CELIX_LOG_LEVEL_WARNING, __VA_ARGS__)
-#define L_ERROR(...) \
-    celix_logHelper_log(receiver->logHelper, CELIX_LOG_LEVEL_ERROR, __VA_ARGS__)
-
-typedef struct pubsub_websocket_rcv_buffer {
-    celix_thread_mutex_t mutex;
-    celix_array_list_t *list;     //List of received websocket messages (type: pubsub_websocket_msg_entry_t *)
-} pubsub_websocket_rcv_buffer_t;
-
-typedef struct pubsub_websocket_msg_entry {
-    size_t msgSize;
-    const char *msgData;
-} pubsub_websocket_msg_entry_t;
-
-struct pubsub_websocket_topic_receiver {
-    celix_bundle_context_t *ctx;
-    celix_log_helper_t *logHelper;
-    long serializerSvcId;
-    pubsub_serializer_service_t *serializer;
-    char *scope;
-    char *topic;
-    char scopeAndTopicFilter[5];
-    char *uri;
-
-    celix_websocket_service_t sockSvc;
-    long svcId;
-
-    pubsub_websocket_rcv_buffer_t recvBuffer;
-
-    struct {
-        celix_thread_t thread;
-        celix_thread_mutex_t mutex;
-        bool running;
-    } recvThread;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = url (host:port), value = psa_websocket_requested_connection_entry_t*
-        bool allConnected; //true if all requestedConnectection are connected
-    } requestedConnections;
-
-    long subscriberTrackerId;
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = bnd id, value = psa_websocket_subscriber_entry_t
-        bool allInitialized;
-    } subscribers;
-};
-
-typedef struct psa_websocket_requested_connection_entry {
-    char *key; //host:port
-    char *socketAddress;
-    long socketPort;
-    char *uri;
-    struct mg_connection *sockConnection;
-    int connectRetryCount;
-    bool connected;
-    bool statically; //true if the connection is statically configured through the topic properties.
-    bool passive; //true if the connection is initiated by another resource (e.g. webpage)
-} psa_websocket_requested_connection_entry_t;
-
-typedef struct psa_websocket_subscriber_entry {
-    hash_map_t *msgTypes; //key = msg type id, value = pubsub_msg_serializer_t
-    hash_map_t *subscriberServices; //key = servide id, value = pubsub_subscriber_t*
-    bool initialized; //true if the init function is called through the receive thread
-} psa_websocket_subscriber_entry_t;
-
-
-static void pubsub_websocketTopicReceiver_addSubscriber(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *owner);
-static void pubsub_websocketTopicReceiver_removeSubscriber(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *owner);
-static void* psa_websocket_recvThread(void * data);
-static void psa_websocket_connectToAllRequestedConnections(pubsub_websocket_topic_receiver_t *receiver);
-static void psa_websocket_initializeAllSubscribers(pubsub_websocket_topic_receiver_t *receiver);
-static void *psa_websocket_getMsgTypeIdFromFqn(const char *fqn, hash_map_t *msg_type_id_map);
-
-static void psa_websocketTopicReceiver_ready(struct mg_connection *connection, void *handle);
-static int psa_websocketTopicReceiver_data(struct mg_connection *connection, int op_code, char *data, size_t length, void *handle);
-static void psa_websocketTopicReceiver_close(const struct mg_connection *connection, void *handle);
-
-
-pubsub_websocket_topic_receiver_t* pubsub_websocketTopicReceiver_create(celix_bundle_context_t *ctx,
-                                                              celix_log_helper_t *logHelper,
-                                                              const char *scope,
-                                                              const char *topic,
-                                                              const celix_properties_t *topicProperties,
-                                                              long serializerSvcId,
-                                                              pubsub_serializer_service_t *serializer) {
-    pubsub_websocket_topic_receiver_t *receiver = calloc(1, sizeof(*receiver));
-    receiver->ctx = ctx;
-    receiver->logHelper = logHelper;
-    receiver->serializerSvcId = serializerSvcId;
-    receiver->serializer = serializer;
-    receiver->scope = scope == NULL ? NULL : strndup(scope, 1024 * 1024);
-    receiver->topic = strndup(topic, 1024 * 1024);
-    psa_websocket_setScopeAndTopicFilter(scope, topic, receiver->scopeAndTopicFilter);
-
-    receiver->uri = psa_websocket_createURI(scope, topic);
-
-    if (receiver->uri != NULL) {
-        celixThreadMutex_create(&receiver->subscribers.mutex, NULL);
-        celixThreadMutex_create(&receiver->requestedConnections.mutex, NULL);
-        celixThreadMutex_create(&receiver->recvThread.mutex, NULL);
-        celixThreadMutex_create(&receiver->recvBuffer.mutex, NULL);
-
-        receiver->subscribers.map = hashMap_create(NULL, NULL, NULL, NULL);
-        receiver->requestedConnections.map = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-        arrayList_create(&receiver->recvBuffer.list);
-    }
-
-    //track subscribers
-    if (receiver->uri != NULL) {
-        int size = snprintf(NULL, 0, "(%s=%s)", PUBSUB_SUBSCRIBER_TOPIC, topic);
-        char buf[size+1];
-        snprintf(buf, (size_t)size+1, "(%s=%s)", PUBSUB_SUBSCRIBER_TOPIC, topic);
-        celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
-        opts.filter.ignoreServiceLanguage = true;
-        opts.filter.serviceName = PUBSUB_SUBSCRIBER_SERVICE_NAME;
-        opts.filter.filter = buf;
-        opts.callbackHandle = receiver;
-        opts.addWithOwner = pubsub_websocketTopicReceiver_addSubscriber;
-        opts.removeWithOwner = pubsub_websocketTopicReceiver_removeSubscriber;
-
-        receiver->subscriberTrackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts);
-    }
-
-    //Register a websocket endpoint for this topic receiver
-    if(receiver->uri != NULL){
-        //Register a websocket svc first
-        celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, WEBSOCKET_ADMIN_URI, receiver->uri);
-        receiver->sockSvc.handle = receiver;
-        //Set callbacks to monitor any incoming connections (passive), data events or close events
-        receiver->sockSvc.ready = psa_websocketTopicReceiver_ready;
-        receiver->sockSvc.data = psa_websocketTopicReceiver_data;
-        receiver->sockSvc.close = psa_websocketTopicReceiver_close;
-        receiver->svcId = celix_bundleContext_registerService(receiver->ctx, &receiver->sockSvc,
-                                                           WEBSOCKET_ADMIN_SERVICE_NAME, props);
-    }
-
-    const char *staticConnects = pubsub_getEnvironmentVariableWithScopeTopic(ctx, PUBSUB_WEBSOCKET_STATIC_CONNECT_SOCKET_ADDRESSES_FOR, topic, scope);
-    if(staticConnects == NULL) {
-        staticConnects = celix_properties_get(topicProperties, PUBSUB_WEBSOCKET_STATIC_CONNECT_SOCKET_ADDRESSES, NULL);
-    }
-    if (staticConnects != NULL) {
-        char *copy = strndup(staticConnects, 1024*1024);
-        char* addr;
-        char* save = copy;
-
-        while ((addr = strtok_r(save, " ", &save))) {
-            char *colon = strchr(addr, ':');
-            if (colon == NULL) {
-                continue;
-            }
-
-            char *sockAddr = NULL;
-            asprintf(&sockAddr, "%.*s", (int)(colon - addr), addr);
-
-            long sockPort = atol((colon + 1));
-
-            char *key = NULL;
-            asprintf(&key, "%s:%li", sockAddr, sockPort);
-
-
-            if (sockPort > 0) {
-                psa_websocket_requested_connection_entry_t *entry = calloc(1, sizeof(*entry));
-                entry->key = key;
-                entry->uri = strndup(receiver->uri, 1024 * 1024);
-                entry->socketAddress = sockAddr;
-                entry->socketPort = sockPort;
-                entry->connected = false;
-                entry->statically = true;
-                entry->passive = false;
-                hashMap_put(receiver->requestedConnections.map, (void *) entry->key, entry);
-            } else {
-                L_WARN("[PSA_WEBSOCKET_TR] Invalid static socket address %s", addr);
-                free(key);
-                free(sockAddr);
-            }
-        }
-        free(copy);
-    }
-
-
-    if (receiver->uri != NULL) {
-        receiver->recvThread.running = true;
-        celixThread_create(&receiver->recvThread.thread, NULL, psa_websocket_recvThread, receiver);
-        char name[64];
-        snprintf(name, 64, "WEBSOCKET TR %s/%s", scope == NULL ? "(null)" : scope, topic);
-        celixThread_setName(&receiver->recvThread.thread, name);
-    }
-
-    if (receiver->uri == NULL) {
-        free(receiver->scope);
-        free(receiver->topic);
-        free(receiver);
-        receiver = NULL;
-        L_ERROR("[PSA_WEBSOCKET] Cannot create TopicReceiver for %s/%s", scope == NULL ? "(null)" : scope, topic);
-    }
-
-    return receiver;
-}
-
-void pubsub_websocketTopicReceiver_destroy(pubsub_websocket_topic_receiver_t *receiver) {
-    if (receiver != NULL) {
-
-        celixThreadMutex_lock(&receiver->recvThread.mutex);
-        receiver->recvThread.running = false;
-        celixThreadMutex_unlock(&receiver->recvThread.mutex);
-        celixThread_join(receiver->recvThread.thread, NULL);
-
-        celix_bundleContext_stopTracker(receiver->ctx, receiver->subscriberTrackerId);
-
-        celix_bundleContext_unregisterService(receiver->ctx, receiver->svcId);
-
-        celixThreadMutex_lock(&receiver->subscribers.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(receiver->subscribers.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_websocket_subscriber_entry_t *entry = hashMapIterator_nextValue(&iter);
-            if (entry != NULL)  {
-                receiver->serializer->destroySerializerMap(receiver->serializer->handle, entry->msgTypes);
-                hashMap_destroy(entry->subscriberServices, false, false);
-                free(entry);
-            }
-
-        }
-        hashMap_destroy(receiver->subscribers.map, false, false);
-
-
-        celixThreadMutex_unlock(&receiver->subscribers.mutex);
-
-        celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-        iter = hashMapIterator_construct(receiver->requestedConnections.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_websocket_requested_connection_entry_t *entry = hashMapIterator_nextValue(&iter);
-            if (entry != NULL) {
-                if(entry->connected) {
-                    mg_close_connection(entry->sockConnection);
-                }
-                free(entry->uri);
-                free(entry->socketAddress);
-                free(entry->key);
-                free(entry);
-            }
-        }
-        hashMap_destroy(receiver->requestedConnections.map, false, false);
-        celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-
-        celixThreadMutex_destroy(&receiver->subscribers.mutex);
-        celixThreadMutex_destroy(&receiver->requestedConnections.mutex);
-        celixThreadMutex_destroy(&receiver->recvThread.mutex);
-
-        celixThreadMutex_destroy(&receiver->recvBuffer.mutex);
-        int msgBufSize = celix_arrayList_size(receiver->recvBuffer.list);
-        while(msgBufSize > 0) {
-            pubsub_websocket_msg_entry_t *msg = celix_arrayList_get(receiver->recvBuffer.list, msgBufSize - 1);
-            free((void *) msg->msgData);
-            free(msg);
-            msgBufSize--;
-        }
-        celix_arrayList_destroy(receiver->recvBuffer.list);
-
-        free(receiver->uri);
-        free(receiver->scope);
-        free(receiver->topic);
-    }
-    free(receiver);
-}
-
-const char* pubsub_websocketTopicReceiver_scope(pubsub_websocket_topic_receiver_t *receiver) {
-    return receiver->scope;
-}
-const char* pubsub_websocketTopicReceiver_topic(pubsub_websocket_topic_receiver_t *receiver) {
-    return receiver->topic;
-}
-const char* pubsub_websocketTopicReceiver_url(pubsub_websocket_topic_receiver_t *receiver) {
-    return receiver->uri;
-}
-
-long pubsub_websocketTopicReceiver_serializerSvcId(pubsub_websocket_topic_receiver_t *receiver) {
-    return receiver->serializerSvcId;
-}
-
-void pubsub_websocketTopicReceiver_listConnections(pubsub_websocket_topic_receiver_t *receiver, celix_array_list_t *connectedUrls, celix_array_list_t *unconnectedUrls) {
-    celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-    hash_map_iterator_t iter = hashMapIterator_construct(receiver->requestedConnections.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_websocket_requested_connection_entry_t *entry = hashMapIterator_nextValue(&iter);
-        char *url = NULL;
-        asprintf(&url, "%s:%li%s%s", entry->socketAddress, entry->socketPort, entry->statically ? " (static)" : "", entry->passive ? " (passive)" : "");
-        if (entry->connected) {
-            celix_arrayList_add(connectedUrls, url);
-        } else {
-            celix_arrayList_add(unconnectedUrls, url);
-        }
-    }
-    celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-}
-
-
-void pubsub_websocketTopicReceiver_connectTo(pubsub_websocket_topic_receiver_t *receiver, const char *socketAddress, long socketPort) {
-    L_DEBUG("[PSA_WEBSOCKET] TopicReceiver %s/%s ('%s') connecting to websocket address %s:li", receiver->scope == NULL ? "(null)" : receiver->scope, receiver->topic, receiver->uri, socketAddress, socketPort);
-
-    char *key = NULL;
-    asprintf(&key, "%s:%li", socketAddress, socketPort);
-
-    celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-    psa_websocket_requested_connection_entry_t *entry = hashMap_get(receiver->requestedConnections.map, key);
-    if (entry == NULL) {
-        entry = calloc(1, sizeof(*entry));
-        entry->key = key;
-        entry->uri = strndup(receiver->uri, 1024 * 1024);
-        entry->socketAddress = strndup(socketAddress, 1024 * 1024);
-        entry->socketPort = socketPort;
-        entry->connected = false;
-        entry->statically = false;
-        entry->passive = false;
-        hashMap_put(receiver->requestedConnections.map, (void*)entry->key, entry);
-        receiver->requestedConnections.allConnected = false;
-    } else {
-        free(key);
-    }
-    celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-
-    psa_websocket_connectToAllRequestedConnections(receiver);
-}
-
-void pubsub_websocketTopicReceiver_disconnectFrom(pubsub_websocket_topic_receiver_t *receiver, const char *socketAddress, long socketPort) {
-    L_DEBUG("[PSA_WEBSOCKET] TopicReceiver %s/%s ('%s') disconnect from websocket address %s:%li", receiver->scope == NULL ? "(null)" : receiver->scope, receiver->topic, receiver->uri, socketAddress, socketPort);
-
-    char *key = NULL;
-    asprintf(&key, "%s:%li", socketAddress, socketPort);
-
-    celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-
-    psa_websocket_requested_connection_entry_t *entry = hashMap_remove(receiver->requestedConnections.map, key);
-    if (entry != NULL && entry->connected) {
-        mg_close_connection(entry->sockConnection);
-    }
-    if (entry != NULL) {
-        free(entry->socketAddress);
-        free(entry->uri);
-        free(entry->key);
-        free(entry);
-    }
-    celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-    free(key);
-}
-
-static void pubsub_websocketTopicReceiver_addSubscriber(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *bnd) {
-    pubsub_websocket_topic_receiver_t *receiver = handle;
-
-    long bndId = celix_bundle_getId(bnd);
-    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1);
-    const char *subScope = celix_properties_get(props, PUBSUB_SUBSCRIBER_SCOPE, NULL);
-    if (receiver->scope == NULL){
-        if (subScope != NULL){
-            return;
-        }
-    } else if (subScope != NULL) {
-        if (strncmp(subScope, receiver->scope, strlen(receiver->scope)) != 0) {
-            //not the same scope. ignore
-            return;
-        }
-    } else {
-        //receiver scope is not NULL, but subScope is NULL -> ignore
-        return;
-    }
-
-    celixThreadMutex_lock(&receiver->subscribers.mutex);
-    psa_websocket_subscriber_entry_t *entry = hashMap_get(receiver->subscribers.map, (void*)bndId);
-    if (entry != NULL) {
-        hashMap_put(entry->subscriberServices, (void*)svcId, svc);
-    } else {
-        //new create entry
-        entry = calloc(1, sizeof(*entry));
-        entry->subscriberServices = hashMap_create(NULL, NULL, NULL, NULL);
-        entry->initialized = false;
-        hashMap_put(entry->subscriberServices, (void*)svcId, svc);
-
-        int rc = receiver->serializer->createSerializerMap(receiver->serializer->handle, (celix_bundle_t*)bnd, &entry->msgTypes);
-
-        if (rc == 0) {
-            hashMap_put(receiver->subscribers.map, (void*)bndId, entry);
-        } else {
-            L_ERROR("[PSA_WEBSOCKET] Cannot create msg serializer map for TopicReceiver %s/%s", receiver->scope == NULL ? "(null)" : receiver->scope, receiver->topic);
-            free(entry);
-        }
-    }
-    celixThreadMutex_unlock(&receiver->subscribers.mutex);
-}
-
-static void pubsub_websocketTopicReceiver_removeSubscriber(void *handle, void *svc __attribute__((unused)), const celix_properties_t *props __attribute__((unused)), const celix_bundle_t *bnd) {
-    pubsub_websocket_topic_receiver_t *receiver = handle;
-
-    long bndId = celix_bundle_getId(bnd);
-    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1);
-
-
-    celixThreadMutex_lock(&receiver->subscribers.mutex);
-    psa_websocket_subscriber_entry_t *entry = hashMap_get(receiver->subscribers.map, (void*)bndId);
-    if (entry != NULL) {
-        hashMap_remove(entry->subscriberServices, (void*)svcId);
-    }
-    if (entry != NULL && hashMap_size(entry->subscriberServices) == 0) {
-        //remove entry
-        hashMap_remove(receiver->subscribers.map, (void*)bndId);
-        int rc = receiver->serializer->destroySerializerMap(receiver->serializer->handle, entry->msgTypes);
-        if (rc != 0) {
-            L_ERROR("[PSA_WEBSOCKET] Cannot destroy msg serializers map for TopicReceiver %s/%s", receiver->scope == NULL ? "(null)" : receiver->scope, receiver->topic);
-        }
-        hashMap_destroy(entry->subscriberServices, false, false);
-        free(entry);
-    }
-    celixThreadMutex_unlock(&receiver->subscribers.mutex);
-}
-
-static void * psa_websocket_getMsgTypeIdFromFqn(const char *fqn, hash_map_t *msg_type_id_map) {
-    void *msgTypeId = NULL;
-    if(fqn != NULL && msg_type_id_map != NULL) {
-        hash_map_iterator_t iter = hashMapIterator_construct(msg_type_id_map);
-        while (hashMapIterator_hasNext(&iter)) {
-            hash_map_entry_t *entry = hashMapIterator_nextEntry(&iter);
-            pubsub_msg_serializer_t *serializer = hashMapEntry_getValue(entry);
-            if(strcmp(serializer->msgName, fqn) == 0) {
-                msgTypeId =  hashMapEntry_getKey(entry);
-                return msgTypeId;
-            }
-        }
-    }
-
-    return msgTypeId;
-}
-
-static inline void processMsgForSubscriberEntry(pubsub_websocket_topic_receiver_t *receiver, psa_websocket_subscriber_entry_t* entry, pubsub_websocket_msg_header_t *hdr, const char* payload, size_t payloadSize) {
-    //NOTE receiver->subscribers.mutex locked
-    void *msgTypeId = psa_websocket_getMsgTypeIdFromFqn(hdr->id, entry->msgTypes);
-    pubsub_msg_serializer_t* msgSer = hashMap_get(entry->msgTypes, msgTypeId);
-
-    if (msgSer!= NULL && msgTypeId != 0) {
-        void *deSerializedMsg = NULL;
-        bool validVersion = psa_websocket_checkVersion(msgSer->msgVersion, hdr);
-        if (validVersion) {
-            struct iovec deSerializeBuffer;
-            deSerializeBuffer.iov_base = (void *)payload;
-            deSerializeBuffer.iov_len  = payloadSize;
-            celix_status_t status = msgSer->deserialize(msgSer->handle, &deSerializeBuffer, 0, &deSerializedMsg);
-
-            if (status == CELIX_SUCCESS) {
-                hash_map_iterator_t iter = hashMapIterator_construct(entry->subscriberServices);
-                bool release = true;
-                while (hashMapIterator_hasNext(&iter)) {
-                    pubsub_subscriber_t *svc = hashMapIterator_nextValue(&iter);
-                    svc->receive(svc->handle, msgSer->msgName, msgSer->msgId, deSerializedMsg, NULL, &release);
-                    if (!release) {
-                        //receive function has taken ownership, deserialize again for new message
-                        status = msgSer->deserialize(msgSer->handle, &deSerializeBuffer, 0, &deSerializedMsg);
-                        if (status != CELIX_SUCCESS) {
-                            L_WARN("[PSA_WEBSOCKET_TR] Cannot deserialize msg type %s for scope/topic %s/%s", msgSer->msgName, receiver->scope == NULL ? "(null)" : receiver->scope, receiver->topic);
-                            break;
-                        }
-                        release = true;
-                    }
-                }
-                if (release) {
-                    msgSer->freeDeserializeMsg(msgSer->handle, deSerializedMsg);
-                }
-            } else {
-                L_WARN("[PSA_WEBSOCKET_TR] Cannot deserialize msg type %s for scope/topic %s/%s", msgSer->msgName, receiver->scope == NULL ? "(null)" : receiver->scope, receiver->topic);
-            }
-        }
-    } else {
-        L_WARN("[PSA_WEBSOCKET_TR] Cannot find serializer for type id 0x%X, fqn %s", msgTypeId, hdr->id);
-    }
-}
-
-static inline void processMsg(pubsub_websocket_topic_receiver_t *receiver, const char *msg, size_t msgSize) {
-    json_error_t error;
-    json_t *jsMsg = json_loadb(msg, msgSize, 0, &error);
-    if(jsMsg != NULL) {
-        json_t *jsId = json_object_get(jsMsg, "id");
-        json_t *jsMajor = json_object_get(jsMsg, "major");
-        json_t *jsMinor = json_object_get(jsMsg, "minor");
-        json_t *jsSeqNr = json_object_get(jsMsg, "seqNr");
-        json_t *jsData = json_object_get(jsMsg, "data");
-
-        if (jsId && jsMajor && jsMinor && jsSeqNr && jsData) {
-            pubsub_websocket_msg_header_t hdr;
-            hdr.id = json_string_value(jsId);
-            hdr.major = (uint8_t) json_integer_value(jsMajor);
-            hdr.minor = (uint8_t) json_integer_value(jsMinor);
-            hdr.seqNr = (uint32_t) json_integer_value(jsSeqNr);
-            const char *payload = json_dumps(jsData, 0);
-            size_t payloadSize = strlen(payload);
-            printf("Received msg: id %s\tmajor %u\tminor %u\tseqNr %u\tdata %s\n", hdr.id, hdr.major, hdr.minor, hdr.seqNr, payload);
-
-            celixThreadMutex_lock(&receiver->subscribers.mutex);
-            hash_map_iterator_t iter = hashMapIterator_construct(receiver->subscribers.map);
-            while (hashMapIterator_hasNext(&iter)) {
-                psa_websocket_subscriber_entry_t *entry = hashMapIterator_nextValue(&iter);
-                if (entry != NULL) {
-                    processMsgForSubscriberEntry(receiver, entry, &hdr, payload, payloadSize);
-                }
-            }
-            celixThreadMutex_unlock(&receiver->subscribers.mutex);
-            free((void *) payload);
-        } else {
-            L_WARN("[PSA_WEBSOCKET_TR] Received unsupported message: "
-                   "ID = %s, major = %d, minor = %d, seqNr = %d, data valid? %s",
-                   (jsId ? json_string_value(jsId) : "ERROR"),
-                   json_integer_value(jsMajor), json_integer_value(jsMinor),
-                   json_integer_value(jsSeqNr), (jsData ? "TRUE" : "FALSE"));
-        }
-        json_decref(jsMsg);
-    } else {
-        L_WARN("[PSA_WEBSOCKET_TR] Failed to load websocket JSON message, error line: %d, error message: %s", error.line, error.text);
-        return;
-    }
-
-}
-
-static void* psa_websocket_recvThread(void * data) {
-    pubsub_websocket_topic_receiver_t *receiver = data;
-
-    celixThreadMutex_lock(&receiver->recvThread.mutex);
-    bool running = receiver->recvThread.running;
-    celixThreadMutex_unlock(&receiver->recvThread.mutex);
-
-    celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-    bool allConnected = receiver->requestedConnections.allConnected;
-    celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-
-    celixThreadMutex_lock(&receiver->subscribers.mutex);
-    bool allInitialized = receiver->subscribers.allInitialized;
-    celixThreadMutex_unlock(&receiver->subscribers.mutex);
-
-
-    while (running) {
-        if (!allConnected) {
-            psa_websocket_connectToAllRequestedConnections(receiver);
-        }
-        if (!allInitialized) {
-            psa_websocket_initializeAllSubscribers(receiver);
-        }
-
-        while(celix_arrayList_size(receiver->recvBuffer.list) > 0) {
-            celixThreadMutex_lock(&receiver->recvBuffer.mutex);
-            pubsub_websocket_msg_entry_t *msg = (pubsub_websocket_msg_entry_t *) celix_arrayList_get(receiver->recvBuffer.list, 0);
-            celix_arrayList_removeAt(receiver->recvBuffer.list, 0);
-            celixThreadMutex_unlock(&receiver->recvBuffer.mutex);
-
-            processMsg(receiver, msg->msgData, msg->msgSize);
-            free((void *)msg->msgData);
-            free(msg);
-        }
-
-        celixThreadMutex_lock(&receiver->recvThread.mutex);
-        running = receiver->recvThread.running;
-        celixThreadMutex_unlock(&receiver->recvThread.mutex);
-
-        celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-        allConnected = receiver->requestedConnections.allConnected;
-        celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-
-        celixThreadMutex_lock(&receiver->subscribers.mutex);
-        allInitialized = receiver->subscribers.allInitialized;
-        celixThreadMutex_unlock(&receiver->subscribers.mutex);
-    } // while
-
-    return NULL;
-}
-
-static void psa_websocketTopicReceiver_ready(struct mg_connection *connection, void *handle) {
-    if (handle != NULL) {
-        pubsub_websocket_topic_receiver_t *receiver = (pubsub_websocket_topic_receiver_t *) handle;
-
-        //Get request info with host, port and uri information
-        const struct mg_request_info *ri = mg_get_request_info(connection);
-        if (ri != NULL && strcmp(receiver->uri, ri->request_uri) == 0) {
-            char *key = NULL;
-            asprintf(&key, "%s:%i", ri->remote_addr, ri->remote_port);
-
-            celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-            psa_websocket_requested_connection_entry_t *entry = hashMap_get(receiver->requestedConnections.map, key);
-            if (entry == NULL) {
-                entry = calloc(1, sizeof(*entry));
-                entry->key = key;
-                entry->uri = strndup(ri->request_uri, 1024 * 1024);
-                entry->socketAddress = strndup(ri->remote_addr, 1024 * 1024);
-                entry->socketPort = ri->remote_port;
-                entry->connected = true;
-                entry->statically = false;
-                entry->passive = true;
-                hashMap_put(receiver->requestedConnections.map, (void *) entry->key, entry);
-                receiver->requestedConnections.allConnected = false;
-            } else {
-                free(key);
-            }
-
-            celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-        }
-    }
-}
-
-
-static int psa_websocketTopicReceiver_data(struct mg_connection *connection __attribute__((unused)),
-                                            int op_code __attribute__((unused)),
-                                            char *data,
-                                            size_t length,
-                                            void *handle) {
-    //Received a websocket message, append this message to the buffer of the receiver.
-    if (handle != NULL) {
-        pubsub_websocket_topic_receiver_t *receiver = (pubsub_websocket_topic_receiver_t *) handle;
-
-        celixThreadMutex_lock(&receiver->recvBuffer.mutex);
-        pubsub_websocket_msg_entry_t *msg = malloc(sizeof(*msg));
-        const char *rcvdMsgData = malloc(length);
-        memcpy((void *) rcvdMsgData, data, length);
-        msg->msgData = rcvdMsgData;
-        msg->msgSize = length;
-        celix_arrayList_add(receiver->recvBuffer.list, msg);
-        celixThreadMutex_unlock(&receiver->recvBuffer.mutex);
-    }
-
-    return 1; //keep open (non-zero), 0 to close the socket
-}
-
-static void psa_websocketTopicReceiver_close(const struct mg_connection *connection, void *handle) {
-    //Reset connection for this receiver entry
-    if (handle != NULL) {
-        pubsub_websocket_topic_receiver_t *receiver = (pubsub_websocket_topic_receiver_t *) handle;
-
-        //Get request info with host, port and uri information
-        const struct mg_request_info *ri = mg_get_request_info(connection);
-        if (ri != NULL && strcmp(receiver->uri, ri->request_uri) == 0) {
-            char *key = NULL;
-            asprintf(&key, "%s:%i", ri->remote_addr, ri->remote_port);
-
-            celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-            psa_websocket_requested_connection_entry_t *entry = hashMap_get(receiver->requestedConnections.map, key);
-            if (entry != NULL) {
-                entry->connected = false;
-                entry->sockConnection = NULL;
-                if(entry->passive) {
-                    hashMap_remove(receiver->requestedConnections.map, key);
-                    free(entry->key);
-                    free(entry->uri);
-                    free(entry->socketAddress);
-                    free(entry);
-                }
-            }
-            celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-            free(key);
-        }
-    }
-}
-
-
-static void psa_websocket_connectToAllRequestedConnections(pubsub_websocket_topic_receiver_t *receiver) {
-    celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-    if (!receiver->requestedConnections.allConnected) {
-        bool allConnected = true;
-        hash_map_iterator_t iter = hashMapIterator_construct(receiver->requestedConnections.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_websocket_requested_connection_entry_t *entry = hashMapIterator_nextValue(&iter);
-            if (!entry->connected && !entry->passive) {
-                char errBuf[100] = {0};
-                entry->sockConnection = mg_connect_websocket_client(entry->socketAddress,
-                                                                    (int) entry->socketPort,
-                                                                    0, // No ssl
-                                                                    errBuf,
-                                                                    (size_t) sizeof(errBuf),
-                                                                    entry->uri,
-                                                                    NULL,
-                                                                    psa_websocketTopicReceiver_data,
-                                                                    psa_websocketTopicReceiver_close,
-                                                                    receiver);
-                if(entry->sockConnection != NULL) {
-                    entry->connected = true;
-                    entry->connectRetryCount = 0;
-                } else {
-                    entry->connectRetryCount += 1;
-                    allConnected = false;
-                    if((entry->connectRetryCount % 10) == 0) {
-                        L_WARN("[PSA_WEBSOCKET] Error connecting to websocket %s:%li/%s. Error: %s",
-                               entry->socketAddress,
-                               entry->socketPort,
-                               entry->uri, errBuf);
-                    }
-                }
-            }
-        }
-        receiver->requestedConnections.allConnected = allConnected;
-    }
-    celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-}
-
-static void psa_websocket_initializeAllSubscribers(pubsub_websocket_topic_receiver_t *receiver) {
-    celixThreadMutex_lock(&receiver->subscribers.mutex);
-    if (!receiver->subscribers.allInitialized) {
-        bool allInitialized = true;
-        hash_map_iterator_t iter = hashMapIterator_construct(receiver->subscribers.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_websocket_subscriber_entry_t *entry = hashMapIterator_nextValue(&iter);
-            if (!entry->initialized) {
-                hash_map_iterator_t iter2 = hashMapIterator_construct(entry->subscriberServices);
-                while (hashMapIterator_hasNext(&iter2)) {
-                    pubsub_subscriber_t *svc = hashMapIterator_nextValue(&iter2);
-                    int rc = 0;
-                    if (svc != NULL && svc->init != NULL) {
-                        rc = svc->init(svc->handle);
-                    }
-                    if (rc == 0) {
-                        //note now only initialized on first subscriber entries added.
-                        entry->initialized = true;
-                    } else {
-                        L_WARN("Cannot initialize subscriber svc. Got rc %i", rc);
-                        allInitialized = false;
-                    }
-                }
-            }
-        }
-        receiver->subscribers.allInitialized = allInitialized;
-    }
-    celixThreadMutex_unlock(&receiver->subscribers.mutex);
-}
diff --git a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_topic_receiver.h b/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_topic_receiver.h
deleted file mode 100644
index 4df42a0..0000000
--- a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_topic_receiver.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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_PUBSUB_WEBSOCKET_TOPIC_RECEIVER_H
-#define CELIX_PUBSUB_WEBSOCKET_TOPIC_RECEIVER_H
-
-#include <pubsub_admin_metrics.h>
-#include "celix_bundle_context.h"
-
-typedef struct pubsub_websocket_topic_receiver pubsub_websocket_topic_receiver_t;
-
-pubsub_websocket_topic_receiver_t* pubsub_websocketTopicReceiver_create(celix_bundle_context_t *ctx,
-        celix_log_helper_t *logHelper,
-        const char *scope,
-        const char *topic,
-        const celix_properties_t *topicProperties,
-        long serializerSvcId,
-        pubsub_serializer_service_t *serializer);
-void pubsub_websocketTopicReceiver_destroy(pubsub_websocket_topic_receiver_t *receiver);
-
-const char* pubsub_websocketTopicReceiver_scope(pubsub_websocket_topic_receiver_t *receiver);
-const char* pubsub_websocketTopicReceiver_topic(pubsub_websocket_topic_receiver_t *receiver);
-const char* pubsub_websocketTopicReceiver_url(pubsub_websocket_topic_receiver_t *receiver);
-
-long pubsub_websocketTopicReceiver_serializerSvcId(pubsub_websocket_topic_receiver_t *receiver);
-void pubsub_websocketTopicReceiver_listConnections(pubsub_websocket_topic_receiver_t *receiver, celix_array_list_t *connectedUrls, celix_array_list_t *unconnectedUrls);
-
-void pubsub_websocketTopicReceiver_connectTo(pubsub_websocket_topic_receiver_t *receiver, const char *socketAddress, long socketPort);
-void pubsub_websocketTopicReceiver_disconnectFrom(pubsub_websocket_topic_receiver_t *receiver, const char *socketAddress, long socketPort);
-
-#endif //CELIX_PUBSUB_WEBSOCKET_TOPIC_RECEIVER_H
diff --git a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_topic_sender.c b/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_topic_sender.c
deleted file mode 100644
index ac3108c..0000000
--- a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_topic_sender.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * 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 <pubsub_serializer.h>
-#include <stdlib.h>
-#include <memory.h>
-#include <pubsub_constants.h>
-#include <pubsub/publisher.h>
-#include <utils.h>
-#include <zconf.h>
-#include <celix_log_helper.h>
-#include "pubsub_websocket_topic_sender.h"
-#include "pubsub_psa_websocket_constants.h"
-#include "pubsub_websocket_common.h"
-#include <uuid/uuid.h>
-#include <jansson.h>
-#include "celix_constants.h"
-#include "http_admin/api.h"
-#include "civetweb.h"
-
-#define FIRST_SEND_DELAY_IN_SECONDS             2
-
-#define L_DEBUG(...) \
-    celix_logHelper_log(sender->logHelper, CELIX_LOG_LEVEL_DEBUG, __VA_ARGS__)
-#define L_INFO(...) \
-    celix_logHelper_log(sender->logHelper, CELIX_LOG_LEVEL_INFO, __VA_ARGS__)
-#define L_WARN(...) \
-    celix_logHelper_log(sender->logHelper, CELIX_LOG_LEVEL_WARNING, __VA_ARGS__)
-#define L_ERROR(...) \
-    celix_logHelper_log(sender->logHelper, CELIX_LOG_LEVEL_ERROR, __VA_ARGS__)
-
-struct pubsub_websocket_topic_sender {
-    celix_bundle_context_t *ctx;
-    celix_log_helper_t *logHelper;
-    long serializerSvcId;
-    pubsub_serializer_service_t *serializer;
-
-    char *scope;
-    char *topic;
-    char scopeAndTopicFilter[5];
-    char *uri;
-
-    celix_websocket_service_t websockSvc;
-    long websockSvcId;
-    struct mg_connection *sockConnection;
-
-    struct {
-        long svcId;
-        celix_service_factory_t factory;
-    } publisher;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map;  //key = bndId, value = psa_websocket_bounded_service_entry_t
-    } boundedServices;
-};
-
-typedef struct psa_websocket_send_msg_entry {
-    pubsub_websocket_msg_header_t header; //partially filled header (only seqnr and time needs to be updated per send)
-    pubsub_msg_serializer_t *msgSer;
-    celix_thread_mutex_t sendLock; //protects send & header(.seqNr)
-} psa_websocket_send_msg_entry_t;
-
-typedef struct psa_websocket_bounded_service_entry {
-    pubsub_websocket_topic_sender_t *parent;
-    pubsub_publisher_t service;
-    long bndId;
-    hash_map_t *msgTypes; //key = msg type id, value = pubsub_msg_serializer_t
-    hash_map_t *msgTypeIds; //key = msg name, value = msg type id
-    hash_map_t *msgEntries; //key = msg type id, value = psa_websocket_send_msg_entry_t
-    int getCount;
-} psa_websocket_bounded_service_entry_t;
-
-static int psa_websocket_localMsgTypeIdForMsgType(void* handle __attribute__((unused)), const char* msgType, unsigned int* msgTypeId);
-static void* psa_websocket_getPublisherService(void *handle, const celix_bundle_t *requestingBundle, const celix_properties_t *svcProperties);
-static void psa_websocket_ungetPublisherService(void *handle, const celix_bundle_t *requestingBundle, const celix_properties_t *svcProperties);
-static void delay_first_send_for_late_joiners(pubsub_websocket_topic_sender_t *sender);
-
-static int psa_websocket_topicPublicationSend(void* handle, unsigned int msgTypeId, const void *msg, celix_properties_t *metadata);
-
-static void psa_websocketTopicSender_ready(struct mg_connection *connection, void *handle);
-static void psa_websocketTopicSender_close(const struct mg_connection *connection, void *handle);
-
-pubsub_websocket_topic_sender_t* pubsub_websocketTopicSender_create(
-        celix_bundle_context_t *ctx,
-        celix_log_helper_t *logHelper,
-        const char *scope,
-        const char *topic,
-        long serializerSvcId,
-        pubsub_serializer_service_t *ser) {
-    pubsub_websocket_topic_sender_t *sender = calloc(1, sizeof(*sender));
-    sender->ctx = ctx;
-    sender->logHelper = logHelper;
-    sender->serializerSvcId = serializerSvcId;
-    sender->serializer = ser;
-    psa_websocket_setScopeAndTopicFilter(scope, topic, sender->scopeAndTopicFilter);
-    sender->uri = psa_websocket_createURI(scope, topic);
-
-    if (sender->uri != NULL) {
-        celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, WEBSOCKET_ADMIN_URI, sender->uri);
-
-        sender->websockSvc.handle = sender;
-        sender->websockSvc.ready = psa_websocketTopicSender_ready;
-        sender->websockSvc.close = psa_websocketTopicSender_close;
-        sender->websockSvcId = celix_bundleContext_registerService(ctx, &sender->websockSvc,
-                                                                   WEBSOCKET_ADMIN_SERVICE_NAME, props);
-    } else {
-        sender->websockSvcId = -1;
-    }
-
-    if (sender->websockSvcId > 0) {
-        sender->scope = scope == NULL ? NULL : strndup(scope, 1024 * 1024);
-        sender->topic = strndup(topic, 1024 * 1024);
-
-        celixThreadMutex_create(&sender->boundedServices.mutex, NULL);
-        sender->boundedServices.map = hashMap_create(NULL, NULL, NULL, NULL);
-    }
-
-    //register publisher services using a service factory
-    if (sender->websockSvcId > 0) {
-        sender->publisher.factory.handle = sender;
-        sender->publisher.factory.getService = psa_websocket_getPublisherService;
-        sender->publisher.factory.ungetService = psa_websocket_ungetPublisherService;
-
-        celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, PUBSUB_PUBLISHER_TOPIC, sender->topic);
-        if (sender->scope != NULL) {
-            celix_properties_set(props, PUBSUB_PUBLISHER_SCOPE, sender->scope);
-        }
-
-        celix_service_registration_options_t opts = CELIX_EMPTY_SERVICE_REGISTRATION_OPTIONS;
-        opts.factory = &sender->publisher.factory;
-        opts.serviceName = PUBSUB_PUBLISHER_SERVICE_NAME;
-        opts.serviceVersion = PUBSUB_PUBLISHER_SERVICE_VERSION;
-        opts.properties = props;
-
-        sender->publisher.svcId = celix_bundleContext_registerServiceWithOptions(ctx, &opts);
-    }
-
-    if (sender->websockSvcId < 0) {
-        free(sender);
-        sender = NULL;
-    }
-
-    return sender;
-}
-
-void pubsub_websocketTopicSender_destroy(pubsub_websocket_topic_sender_t *sender) {
-    if (sender != NULL) {
-        celix_bundleContext_unregisterService(sender->ctx, sender->publisher.svcId);
-
-        celixThreadMutex_lock(&sender->boundedServices.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(sender->boundedServices.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_websocket_bounded_service_entry_t *entry = hashMapIterator_nextValue(&iter);
-            if (entry != NULL) {
-                sender->serializer->destroySerializerMap(sender->serializer->handle, entry->msgTypes);
-
-                hash_map_iterator_t iter2 = hashMapIterator_construct(entry->msgEntries);
-                while (hashMapIterator_hasNext(&iter2)) {
-                    psa_websocket_send_msg_entry_t *msgEntry = hashMapIterator_nextValue(&iter2);
-                    free(msgEntry);
-
-                }
-                hashMap_destroy(entry->msgEntries, false, false);
-
-                free(entry);
-            }
-        }
-        hashMap_destroy(sender->boundedServices.map, false, false);
-        celixThreadMutex_unlock(&sender->boundedServices.mutex);
-
-        celixThreadMutex_destroy(&sender->boundedServices.mutex);
-
-        celix_bundleContext_unregisterService(sender->ctx, sender->websockSvcId);
-
-        if (sender->scope != NULL) {
-            free(sender->scope);
-        }
-        free(sender->topic);
-        free(sender->uri);
-        free(sender);
-    }
-}
-
-long pubsub_websocketTopicSender_serializerSvcId(pubsub_websocket_topic_sender_t *sender) {
-    return sender->serializerSvcId;
-}
-
-const char* pubsub_websocketTopicSender_scope(pubsub_websocket_topic_sender_t *sender) {
-    return sender->scope;
-}
-
-const char* pubsub_websocketTopicSender_topic(pubsub_websocket_topic_sender_t *sender) {
-    return sender->topic;
-}
-
-const char* pubsub_websocketTopicSender_url(pubsub_websocket_topic_sender_t *sender) {
-    return sender->uri;
-}
-
-static int psa_websocket_localMsgTypeIdForMsgType(void* handle, const char* msgType, unsigned int* msgTypeId) {
-    psa_websocket_bounded_service_entry_t *entry = (psa_websocket_bounded_service_entry_t *) handle;
-    *msgTypeId = (unsigned int)(uintptr_t) hashMap_get(entry->msgTypeIds, msgType);
-    return 0;
-}
-
-static void* psa_websocket_getPublisherService(void *handle, const celix_bundle_t *requestingBundle, const celix_properties_t *svcProperties __attribute__((unused))) {
-    pubsub_websocket_topic_sender_t *sender = handle;
-    long bndId = celix_bundle_getId(requestingBundle);
-
-    celixThreadMutex_lock(&sender->boundedServices.mutex);
-    psa_websocket_bounded_service_entry_t *entry = hashMap_get(sender->boundedServices.map, (void*)bndId);
-    if (entry != NULL) {
-        entry->getCount += 1;
-    } else {
-        entry = calloc(1, sizeof(*entry));
-        entry->getCount = 1;
-        entry->parent = sender;
-        entry->bndId = bndId;
-        entry->msgEntries = hashMap_create(NULL, NULL, NULL, NULL);
-        entry->msgTypeIds = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-
-        int rc = sender->serializer->createSerializerMap(sender->serializer->handle, (celix_bundle_t*)requestingBundle, &entry->msgTypes);
-        if (rc == 0) {
-            hash_map_iterator_t iter = hashMapIterator_construct(entry->msgTypes);
-            while (hashMapIterator_hasNext(&iter)) {
-                hash_map_entry_t *hashMapEntry = hashMapIterator_nextEntry(&iter);
-                void *key = hashMapEntry_getKey(hashMapEntry);
-                psa_websocket_send_msg_entry_t *sendEntry = calloc(1, sizeof(*sendEntry));
-                sendEntry->msgSer = hashMapEntry_getValue(hashMapEntry);
-                sendEntry->header.id = sendEntry->msgSer->msgName;
-                int major;
-                int minor;
-                version_getMajor(sendEntry->msgSer->msgVersion, &major);
-                version_getMinor(sendEntry->msgSer->msgVersion, &minor);
-                sendEntry->header.major = (uint8_t)major;
-                sendEntry->header.minor = (uint8_t)minor;
-                hashMap_put(entry->msgEntries, key, sendEntry);
-                hashMap_put(entry->msgTypeIds, strndup(sendEntry->msgSer->msgName, 1024), (void *)(uintptr_t) sendEntry->msgSer->msgId);
-            }
-            entry->service.handle = entry;
-            entry->service.localMsgTypeIdForMsgType = psa_websocket_localMsgTypeIdForMsgType;
-            entry->service.send = psa_websocket_topicPublicationSend;
-            hashMap_put(sender->boundedServices.map, (void*)bndId, entry);
-        } else {
-            L_ERROR("Error creating serializer map for websocket TopicSender %s/%s", sender->scope == NULL ? "(null)" : sender->scope, sender->topic);
-        }
-    }
-    celixThreadMutex_unlock(&sender->boundedServices.mutex);
-
-    return &entry->service;
-}
-
-static void psa_websocket_ungetPublisherService(void *handle, const celix_bundle_t *requestingBundle, const celix_properties_t *svcProperties __attribute__((unused))) {
-    pubsub_websocket_topic_sender_t *sender = handle;
-    long bndId = celix_bundle_getId(requestingBundle);
-
-    celixThreadMutex_lock(&sender->boundedServices.mutex);
-    psa_websocket_bounded_service_entry_t *entry = hashMap_get(sender->boundedServices.map, (void*)bndId);
-    if (entry != NULL) {
-        entry->getCount -= 1;
-    }
-    if (entry != NULL && entry->getCount == 0) {
-        //free entry
-        hashMap_remove(sender->boundedServices.map, (void*)bndId);
-        int rc = sender->serializer->destroySerializerMap(sender->serializer->handle, entry->msgTypes);
-        if (rc != 0) {
-            L_ERROR("Error destroying publisher service, serializer not available / cannot get msg serializer map\n");
-        }
-
-        hash_map_iterator_t iter = hashMapIterator_construct(entry->msgEntries);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_websocket_send_msg_entry_t *msgEntry = hashMapIterator_nextValue(&iter);
-            free(msgEntry);
-        }
-        hashMap_destroy(entry->msgEntries, false, false);
-
-        hashMap_destroy(entry->msgTypeIds, true, false);
-        free(entry);
-    }
-    celixThreadMutex_unlock(&sender->boundedServices.mutex);
-}
-
-static int psa_websocket_topicPublicationSend(void* handle, unsigned int msgTypeId, const void *inMsg, celix_properties_t *metadata) {
-    int status = CELIX_SERVICE_EXCEPTION;
-    psa_websocket_bounded_service_entry_t *bound = handle;
-    pubsub_websocket_topic_sender_t *sender = bound->parent;
-    psa_websocket_send_msg_entry_t *entry = hashMap_get(bound->msgEntries, (void *) (uintptr_t) (msgTypeId));
-
-    if (sender->sockConnection != NULL && entry != NULL) {
-        delay_first_send_for_late_joiners(sender);
-        size_t serializedOutputLen = 0;
-        struct iovec* serializedOutput = NULL;
-        status = entry->msgSer->serialize(entry->msgSer->handle, inMsg, &serializedOutput, &serializedOutputLen);
-
-        if (status == CELIX_SUCCESS /*ser ok*/) {
-            json_error_t jsError;
-            unsigned char *hdrEncoded = calloc(sizeof(pubsub_websocket_msg_header_t), sizeof(unsigned char));
-
-            celixThreadMutex_lock(&entry->sendLock);
-
-            json_t *jsMsg = json_object();
-            json_object_set_new_nocheck(jsMsg, "id", json_string(entry->header.id));
-            json_object_set_new_nocheck(jsMsg, "major", json_integer(entry->header.major));
-            json_object_set_new_nocheck(jsMsg, "minor", json_integer(entry->header.minor));
-            json_object_set_new_nocheck(jsMsg, "seqNr", json_integer(entry->header.seqNr++));
-
-            json_t *jsData;
-            jsData = json_loadb((const char *)serializedOutput->iov_base, serializedOutput->iov_len, 0, &jsError);
-            if(jsData != NULL) {
-                json_object_set_new_nocheck(jsMsg, "data", jsData);
-                const char *msg = json_dumps(jsMsg, 0);
-                size_t bytes_to_write = strlen(msg);
-                int bytes_written = mg_websocket_write(sender->sockConnection, MG_WEBSOCKET_OPCODE_TEXT, msg,
-                                                              bytes_to_write);
-                free((void *) msg);
-                json_decref(jsData); //Decrease ref count means freeing the object
-                if (bytes_written != (int) bytes_to_write) {
-                    L_WARN("[PSA_WEBSOCKET_TS] Error sending websocket, written %d of total %lu bytes", bytes_written, bytes_to_write);
-                }
-            } else {
-                L_WARN("[PSA_WEBSOCKET_TS] Error sending websocket, serialized data corrupt. Error(%d;%d;%d): %s", jsError.column, jsError.line, jsError.position, jsError.text);
-            }
-            celixThreadMutex_unlock(&entry->sendLock);
-
-            json_decref(jsMsg); //Decrease ref count means freeing the object
-            free(hdrEncoded);
-            entry->msgSer->freeSerializeMsg(entry->msgSer->handle, serializedOutput, serializedOutputLen);
-        } else {
-            L_WARN("[PSA_WEBSOCKET_TS] Error serialize message of type %s for scope/topic %s/%s",
-                   entry->msgSer->msgName, sender->scope == NULL ? "(null)" : sender->scope, sender->topic);
-        }
-    } else if (entry == NULL){
-        L_WARN("[PSA_WEBSOCKET_TS] Error sending message with msg type id %i for scope/topic %s/%s", msgTypeId, sender->scope == NULL ? "(null)" : sender->scope, sender->topic);
-    } else { // when (sender->sockConnection == NULL) we dont have a client, but we do have a valid entry
-    	status = CELIX_SUCCESS; // Not an error, just nothing to do
-    }
-
-    return status;
-}
-
-static void psa_websocketTopicSender_ready(struct mg_connection *connection, void *handle) {
-    //Connection succeeded so save connection to use for sending the messages
-    pubsub_websocket_topic_sender_t *sender = (pubsub_websocket_topic_sender_t *) handle;
-    sender->sockConnection = connection;
-}
-
-static void psa_websocketTopicSender_close(const struct mg_connection *connection __attribute__((unused)), void *handle) {
-    //Connection closed so reset connection
-    pubsub_websocket_topic_sender_t *sender = (pubsub_websocket_topic_sender_t *) handle;
-    sender->sockConnection = NULL;
-}
-
-static void delay_first_send_for_late_joiners(pubsub_websocket_topic_sender_t *sender) {
-
-    static bool firstSend = true;
-
-    if (firstSend) {
-        L_INFO("PSA_WEBSOCKET_TP: Delaying first send for late joiners...\n");
-        sleep(FIRST_SEND_DELAY_IN_SECONDS);
-        firstSend = false;
-    }
-}
diff --git a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_topic_sender.h b/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_topic_sender.h
deleted file mode 100644
index 7a839d1..0000000
--- a/bundles/pubsub/pubsub_admin_websocket/v1/src/pubsub_websocket_topic_sender.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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_PUBSUB_WEBSOCKET_TOPIC_SENDER_H
-#define CELIX_PUBSUB_WEBSOCKET_TOPIC_SENDER_H
-
-#include "celix_bundle_context.h"
-#include "pubsub_admin_metrics.h"
-
-typedef struct pubsub_websocket_topic_sender pubsub_websocket_topic_sender_t;
-
-pubsub_websocket_topic_sender_t* pubsub_websocketTopicSender_create(
-        celix_bundle_context_t *ctx,
-        celix_log_helper_t *logHelper,
-        const char *scope,
-        const char *topic,
-        long serializerSvcId,
-        pubsub_serializer_service_t *ser);
-void pubsub_websocketTopicSender_destroy(pubsub_websocket_topic_sender_t *sender);
-
-const char* pubsub_websocketTopicSender_scope(pubsub_websocket_topic_sender_t *sender);
-const char* pubsub_websocketTopicSender_topic(pubsub_websocket_topic_sender_t *sender);
-const char* pubsub_websocketTopicSender_url(pubsub_websocket_topic_sender_t *sender);
-
-long pubsub_websocketTopicSender_serializerSvcId(pubsub_websocket_topic_sender_t *sender);
-
-#endif //CELIX_PUBSUB_WEBSOCKET_TOPIC_SENDER_H
diff --git a/bundles/pubsub/pubsub_admin_zmq/v2/CMakeLists.txt b/bundles/pubsub/pubsub_admin_zmq/CMakeLists.txt
similarity index 100%
rename from bundles/pubsub/pubsub_admin_zmq/v2/CMakeLists.txt
rename to bundles/pubsub/pubsub_admin_zmq/CMakeLists.txt
diff --git a/bundles/pubsub/pubsub_admin_zmq/v2/src/psa_activator.c b/bundles/pubsub/pubsub_admin_zmq/src/psa_activator.c
similarity index 100%
rename from bundles/pubsub/pubsub_admin_zmq/v2/src/psa_activator.c
rename to bundles/pubsub/pubsub_admin_zmq/src/psa_activator.c
diff --git a/bundles/pubsub/pubsub_admin_zmq/v2/src/pubsub_psa_zmq_constants.h b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_psa_zmq_constants.h
similarity index 100%
rename from bundles/pubsub/pubsub_admin_zmq/v2/src/pubsub_psa_zmq_constants.h
rename to bundles/pubsub/pubsub_admin_zmq/src/pubsub_psa_zmq_constants.h
diff --git a/bundles/pubsub/pubsub_admin_zmq/v2/src/pubsub_zmq_admin.c b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.c
similarity index 100%
rename from bundles/pubsub/pubsub_admin_zmq/v2/src/pubsub_zmq_admin.c
rename to bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.c
diff --git a/bundles/pubsub/pubsub_admin_zmq/v2/src/pubsub_zmq_admin.h b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.h
similarity index 100%
rename from bundles/pubsub/pubsub_admin_zmq/v2/src/pubsub_zmq_admin.h
rename to bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.h
diff --git a/bundles/pubsub/pubsub_admin_zmq/v2/src/pubsub_zmq_topic_receiver.c b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_receiver.c
similarity index 100%
rename from bundles/pubsub/pubsub_admin_zmq/v2/src/pubsub_zmq_topic_receiver.c
rename to bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_receiver.c
diff --git a/bundles/pubsub/pubsub_admin_zmq/v2/src/pubsub_zmq_topic_receiver.h b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_receiver.h
similarity index 100%
rename from bundles/pubsub/pubsub_admin_zmq/v2/src/pubsub_zmq_topic_receiver.h
rename to bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_receiver.h
diff --git a/bundles/pubsub/pubsub_admin_zmq/v2/src/pubsub_zmq_topic_sender.c b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_sender.c
similarity index 100%
rename from bundles/pubsub/pubsub_admin_zmq/v2/src/pubsub_zmq_topic_sender.c
rename to bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_sender.c
diff --git a/bundles/pubsub/pubsub_admin_zmq/v2/src/pubsub_zmq_topic_sender.h b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_sender.h
similarity index 100%
rename from bundles/pubsub/pubsub_admin_zmq/v2/src/pubsub_zmq_topic_sender.h
rename to bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_sender.h
diff --git a/bundles/pubsub/pubsub_admin_zmq/v2/src/zmq_crypto.c b/bundles/pubsub/pubsub_admin_zmq/src/zmq_crypto.c
similarity index 100%
rename from bundles/pubsub/pubsub_admin_zmq/v2/src/zmq_crypto.c
rename to bundles/pubsub/pubsub_admin_zmq/src/zmq_crypto.c
diff --git a/bundles/pubsub/pubsub_admin_zmq/v2/src/zmq_crypto.h b/bundles/pubsub/pubsub_admin_zmq/src/zmq_crypto.h
similarity index 100%
rename from bundles/pubsub/pubsub_admin_zmq/v2/src/zmq_crypto.h
rename to bundles/pubsub/pubsub_admin_zmq/src/zmq_crypto.h
diff --git a/bundles/pubsub/pubsub_admin_zmq/v1/CMakeLists.txt b/bundles/pubsub/pubsub_admin_zmq/v1/CMakeLists.txt
deleted file mode 100644
index 2427425..0000000
--- a/bundles/pubsub/pubsub_admin_zmq/v1/CMakeLists.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-# 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.
-
-message(STATUS "PubSub ZMQ Admin V1 is deprecated, and will eventually be replaced with PubSub ZMQ Admin v2")
-
-find_package(ZMQ REQUIRED)
-find_package(CZMQ REQUIRED)
-find_package(Jansson REQUIRED)
-find_package(UUID REQUIRED)
-
-set(OPTIONAL_OPENSSL_LIB )
-if (BUILD_ZMQ_SECURITY)
-    add_definitions(-DBUILD_WITH_ZMQ_SECURITY=1)
-
-    find_package(OpenSSL 1.1.0 REQUIRED)
-    include_directories("${OPENSSL_INCLUDE_DIR}")
-    set(OPTIONAL_OPENSSL_LIB OpenSSL::SSL)
-
-    set (ZMQ_CRYPTO_C "src/zmq_crypto.c")
-endif()
-
-add_celix_bundle(celix_pubsub_admin_zmq
-    BUNDLE_SYMBOLICNAME "apache_celix_pubsub_admin_zmq"
-    VERSION "1.1.0"
-    GROUP "Celix/PubSub"
-    SOURCES
-        src/psa_activator.c
-        src/pubsub_zmq_admin.c
-        src/pubsub_zmq_topic_sender.c
-        src/pubsub_zmq_topic_receiver.c
-        ${ZMQ_CRYPTO_C}
-)
-
-set_target_properties(celix_pubsub_admin_zmq PROPERTIES INSTALL_RPATH "$ORIGIN")
-target_link_libraries(celix_pubsub_admin_zmq PRIVATE
-
-        Celix::framework Celix::dfi Celix::log_helper Celix::utils
-        ZMQ::lib CZMQ::lib ${OPTIONAL_OPENSSL_LIB}
-)
-target_link_libraries(celix_pubsub_admin_zmq PRIVATE Celix::pubsub_spi Celix::pubsub_utils )
-target_include_directories(celix_pubsub_admin_zmq PRIVATE
-    src
-)
-
-install_celix_bundle(celix_pubsub_admin_zmq EXPORT celix COMPONENT pubsub)
-target_link_libraries(celix_pubsub_admin_zmq PRIVATE Celix::shell_api)
-add_library(Celix::celix_pubsub_admin_zmq ALIAS celix_pubsub_admin_zmq)
diff --git a/bundles/pubsub/pubsub_admin_zmq/v1/src/psa_activator.c b/bundles/pubsub/pubsub_admin_zmq/v1/src/psa_activator.c
deleted file mode 100644
index cb9dac2..0000000
--- a/bundles/pubsub/pubsub_admin_zmq/v1/src/psa_activator.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * 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 <stdlib.h>
-
-#include "celix_api.h"
-#include "pubsub_serializer.h"
-#include "pubsub_protocol.h"
-#include "celix_log_helper.h"
-
-#include "pubsub_admin.h"
-#include "pubsub_admin_metrics.h"
-#include "pubsub_zmq_admin.h"
-#include "celix_shell_command.h"
-
-typedef struct psa_zmq_activator {
-    celix_log_helper_t *logHelper;
-
-    pubsub_zmq_admin_t *admin;
-
-    long serializersTrackerId;
-
-    long protocolsTrackerId;
-
-    pubsub_admin_service_t adminService;
-    long adminSvcId;
-
-    pubsub_admin_metrics_service_t adminMetricsService;
-    long adminMetricsSvcId;
-
-    celix_shell_command_t cmdSvc;
-    long cmdSvcId;
-} psa_zmq_activator_t;
-
-int psa_zmq_start(psa_zmq_activator_t *act, celix_bundle_context_t *ctx) {
-    act->adminSvcId = -1L;
-    act->cmdSvcId = -1L;
-    act->serializersTrackerId = -1L;
-    act->protocolsTrackerId = -1L;
-
-    act->logHelper = celix_logHelper_create(ctx, "celix_psa_zmq");
-
-    act->admin = pubsub_zmqAdmin_create(ctx, act->logHelper);
-    celix_status_t status = act->admin != NULL ? CELIX_SUCCESS : CELIX_BUNDLE_EXCEPTION;
-
-    //track serializers
-    if (status == CELIX_SUCCESS) {
-        celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
-        opts.filter.serviceName = PUBSUB_SERIALIZER_SERVICE_NAME;
-        opts.filter.ignoreServiceLanguage = true;
-        opts.callbackHandle = act->admin;
-        opts.addWithProperties = pubsub_zmqAdmin_addSerializerSvc;
-        opts.removeWithProperties = pubsub_zmqAdmin_removeSerializerSvc;
-        act->serializersTrackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts);
-    }
-
-    //track protocols
-    if (status == CELIX_SUCCESS) {
-        celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
-        opts.filter.serviceName = PUBSUB_PROTOCOL_SERVICE_NAME;
-        opts.filter.ignoreServiceLanguage = true;
-        opts.callbackHandle = act->admin;
-        opts.addWithProperties = pubsub_zmqAdmin_addProtocolSvc;
-        opts.removeWithProperties = pubsub_zmqAdmin_removeProtocolSvc;
-        act->protocolsTrackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts);
-    }
-
-    //register pubsub admin service
-    if (status == CELIX_SUCCESS) {
-        pubsub_admin_service_t *psaSvc = &act->adminService;
-        psaSvc->handle = act->admin;
-        psaSvc->matchPublisher = pubsub_zmqAdmin_matchPublisher;
-        psaSvc->matchSubscriber = pubsub_zmqAdmin_matchSubscriber;
-        psaSvc->matchDiscoveredEndpoint = pubsub_zmqAdmin_matchDiscoveredEndpoint;
-        psaSvc->setupTopicSender = pubsub_zmqAdmin_setupTopicSender;
-        psaSvc->teardownTopicSender = pubsub_zmqAdmin_teardownTopicSender;
-        psaSvc->setupTopicReceiver = pubsub_zmqAdmin_setupTopicReceiver;
-        psaSvc->teardownTopicReceiver = pubsub_zmqAdmin_teardownTopicReceiver;
-        psaSvc->addDiscoveredEndpoint = pubsub_zmqAdmin_addDiscoveredEndpoint;
-        psaSvc->removeDiscoveredEndpoint = pubsub_zmqAdmin_removeDiscoveredEndpoint;
-
-        celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, PUBSUB_ADMIN_SERVICE_TYPE, PUBSUB_ZMQ_ADMIN_TYPE);
-
-        act->adminSvcId = celix_bundleContext_registerService(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props);
-    }
-
-    if (status == CELIX_SUCCESS) {
-        act->adminMetricsService.handle = act->admin;
-        act->adminMetricsService.metrics = pubsub_zmqAdmin_metrics;
-
-        celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, PUBSUB_ADMIN_SERVICE_TYPE, PUBSUB_ZMQ_ADMIN_TYPE);
-
-        act->adminMetricsSvcId = celix_bundleContext_registerService(ctx, &act->adminMetricsService, PUBSUB_ADMIN_METRICS_SERVICE_NAME, props);
-    }
-
-    //register shell command service
-    {
-        act->cmdSvc.handle = act->admin;
-        act->cmdSvc.executeCommand = pubsub_zmqAdmin_executeCommand;
-        celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psa_zmq");
-        celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psa_zmq");
-        celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the ZMQ PSA");
-        act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props);
-    }
-
-    return status;
-}
-
-int psa_zmq_stop(psa_zmq_activator_t *act, celix_bundle_context_t *ctx) {
-    celix_bundleContext_unregisterService(ctx, act->adminSvcId);
-    celix_bundleContext_unregisterService(ctx, act->cmdSvcId);
-    celix_bundleContext_unregisterService(ctx, act->adminMetricsSvcId);
-    celix_bundleContext_stopTracker(ctx, act->serializersTrackerId);
-    celix_bundleContext_stopTracker(ctx, act->protocolsTrackerId);
-    pubsub_zmqAdmin_destroy(act->admin);
-
-    celix_logHelper_destroy(act->logHelper);
-
-    return CELIX_SUCCESS;
-}
-
-CELIX_GEN_BUNDLE_ACTIVATOR(psa_zmq_activator_t, psa_zmq_start, psa_zmq_stop);
diff --git a/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_psa_zmq_constants.h b/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_psa_zmq_constants.h
deleted file mode 100644
index c50006a..0000000
--- a/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_psa_zmq_constants.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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 PUBSUB_PSA_ZMQ_CONSTANTS_H_
-#define PUBSUB_PSA_ZMQ_CONSTANTS_H_
-
-
-#define PSA_ZMQ_BASE_PORT                       "PSA_ZMQ_BASE_PORT"
-#define PSA_ZMQ_MAX_PORT                        "PSA_ZMQ_MAX_PORT"
-
-#define PSA_ZMQ_DEFAULT_BASE_PORT               5501
-#define PSA_ZMQ_DEFAULT_MAX_PORT                6000
-
-#define PSA_ZMQ_DEFAULT_QOS_SAMPLE_SCORE        30
-#define PSA_ZMQ_DEFAULT_QOS_CONTROL_SCORE       70
-#define PSA_ZMQ_DEFAULT_SCORE                   30
-
-#define PSA_ZMQ_QOS_SAMPLE_SCORE_KEY            "PSA_ZMQ_QOS_SAMPLE_SCORE"
-#define PSA_ZMQ_QOS_CONTROL_SCORE_KEY           "PSA_ZMQ_QOS_CONTROL_SCORE"
-#define PSA_ZMQ_DEFAULT_SCORE_KEY               "PSA_ZMQ_DEFAULT_SCORE"
-
-
-#define PSA_ZMQ_METRICS_ENABLED "PSA_ZMQ_METRICS_ENABLED"
-#define PSA_ZMQ_DEFAULT_METRICS_ENABLED true
-
-#define PSA_ZMQ_ZEROCOPY_ENABLED "PSA_ZMQ_ZEROCOPY_ENABLED"
-#define PSA_ZMQ_DEFAULT_ZEROCOPY_ENABLED false
-
-
-#define PUBSUB_ZMQ_VERBOSE_KEY      "PSA_ZMQ_VERBOSE"
-#define PUBSUB_ZMQ_VERBOSE_DEFAULT  true
-
-#define PUBSUB_ZMQ_PSA_IP_KEY       "PSA_IP"
-#define PUBSUB_ZMQ_PSA_ITF_KEY      "PSA_INTERFACE"
-#define PUBSUB_ZMQ_NR_THREADS_KEY   "PSA_ZMQ_NR_THREADS"
-
-#define PUBSUB_ZMQ_DEFAULT_IP       "127.0.0.1"
-
-#define PUBSUB_ZMQ_ADMIN_TYPE       "zmq"
-
-/**
- * The ZMQ url key for the topic sender endpoints
- */
-#define PUBSUB_ZMQ_URL_KEY          "zmq.url"
-
-
-
-/**
- * Can be set in the topic properties to fix a static bind url
- */
-#define PUBSUB_ZMQ_STATIC_BIND_URL       "zmq.static.bind.url"
-
-/**
- * Name of environment variable with ip/url to bind to
- * e.g. PSA_ZMQ_STATIC_BIND_FOR_topic_scope="ipc:///tmp/pubsub-pingtest"
- */
-#define PUBSUB_ZMQ_STATIC_BIND_URL_FOR "PSA_ZMQ_STATIC_BIND_URL_FOR_"
-
-/**
- * Can be set in the topic properties to fix a static url used for discovery
- */
-#define PUBSUB_ZMQ_STATIC_DISCOVER_URL       "zmq.static.bind.url"
-
-/**
- * If set true on the endpoint, the zmq TopicSender bind and/or discovery url is statically configured.
- */
-#define PUBSUB_ZMQ_STATIC_CONFIGURED       "zmq.static.configured"
-
-/**
- * The static url which a subscriber should try to connect to.
- * The urls are space separated.
- * Can be set in the topic properties.
- */
-#define PUBSUB_ZMQ_STATIC_CONNECT_URLS    "zmq.static.connect.urls"
-
-/**
- * Name of environment variable with space-separated list of ips/urls to connect to
- * e.g. PSA_ZMQ_STATIC_CONNECT_FOR_topic_scope="ipc:///tmp/pubsub-pingtest ipc:///tmp/pubsub-pongtest"
- */
-#define PUBSUB_ZMQ_STATIC_CONNECT_URLS_FOR "PSA_ZMQ_STATIC_CONNECT_URL_FOR_"
-
-/**
- * Realtime thread prio and scheduling information. This is used to setup the thread prio/sched of the
- * internal ZMQ threads.
- * Can be set in the topic properties.
- */
-#define PUBSUB_ZMQ_THREAD_REALTIME_PRIO    "thread.realtime.prio"
-#define PUBSUB_ZMQ_THREAD_REALTIME_SCHED   "thread.realtime.sched"
-
-/**
- * High Water Mark option. See ZMQ doc for more information
- * Note expected type is longs
- */
-#define PUBSUB_ZMQ_HWM                      "zmq.hwm"
-
-#endif /* PUBSUB_PSA_ZMQ_CONSTANTS_H_ */
diff --git a/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_zmq_admin.c b/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_zmq_admin.c
deleted file mode 100644
index 09c7ae5..0000000
--- a/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_zmq_admin.c
+++ /dev/null
@@ -1,885 +0,0 @@
-/*
- * 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 <memory.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <ifaddrs.h>
-#include <pubsub_endpoint.h>
-#include <czmq.h>
-#include <pubsub_serializer.h>
-#include <pubsub_protocol.h>
-#include <ip_utils.h>
-
-#include "pubsub_utils.h"
-#include "pubsub_zmq_admin.h"
-#include "pubsub_psa_zmq_constants.h"
-#include "pubsub_zmq_topic_sender.h"
-#include "pubsub_zmq_topic_receiver.h"
-
-#define L_DEBUG(...) \
-    celix_logHelper_log(psa->log, CELIX_LOG_LEVEL_DEBUG, __VA_ARGS__)
-#define L_INFO(...) \
-    celix_logHelper_log(psa->log, CELIX_LOG_LEVEL_INFO, __VA_ARGS__)
-#define L_WARN(...) \
-    celix_logHelper_log(psa->log, CELIX_LOG_LEVEL_WARNING, __VA_ARGS__)
-#define L_ERROR(...) \
-    celix_logHelper_log(psa->log, CELIX_LOG_LEVEL_ERROR, __VA_ARGS__)
-
-struct pubsub_zmq_admin {
-    celix_bundle_context_t *ctx;
-    celix_log_helper_t *log;
-    const char *fwUUID;
-
-    char *ipAddress;
-    zactor_t *zmq_auth;
-
-    unsigned int basePort;
-    unsigned int maxPort;
-
-    double qosSampleScore;
-    double qosControlScore;
-    double defaultScore;
-
-    bool verbose;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = svcId, value = psa_zmq_serializer_entry_t*
-    } serializers;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = svcId, value = psa_zmq_protocol_entry_t*
-    } protocols;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = scope:topic key, value = pubsub_zmq_topic_sender_t*
-    } topicSenders;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = scope:topic key, value = pubsub_zmq_topic_sender_t*
-    } topicReceivers;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = endpoint uuid, value = celix_properties_t* (endpoint)
-    } discoveredEndpoints;
-
-};
-
-typedef struct psa_zmq_serializer_entry {
-    const char *serType;
-    long svcId;
-    pubsub_serializer_service_t *svc;
-} psa_zmq_serializer_entry_t;
-
-typedef struct psa_zmq_protocol_entry {
-    const char *protType;
-    long svcId;
-    pubsub_protocol_service_t *svc;
-} psa_zmq_protocol_entry_t;
-
-static celix_status_t zmq_getIpAddress(const char* interface, char** ip);
-static celix_status_t pubsub_zmqAdmin_connectEndpointToReceiver(pubsub_zmq_admin_t* psa, pubsub_zmq_topic_receiver_t *receiver, const celix_properties_t *endpoint);
-static celix_status_t pubsub_zmqAdmin_disconnectEndpointFromReceiver(pubsub_zmq_admin_t* psa, pubsub_zmq_topic_receiver_t *receiver, const celix_properties_t *endpoint);
-
-static bool pubsub_zmqAdmin_endpointIsPublisher(const celix_properties_t *endpoint) {
-    const char *type = celix_properties_get(endpoint, PUBSUB_ENDPOINT_TYPE, NULL);
-    return type != NULL && strncmp(PUBSUB_PUBLISHER_ENDPOINT_TYPE, type, strlen(PUBSUB_PUBLISHER_ENDPOINT_TYPE)) == 0;
-}
-
-pubsub_zmq_admin_t* pubsub_zmqAdmin_create(celix_bundle_context_t *ctx, celix_log_helper_t *logHelper) {
-    pubsub_zmq_admin_t *psa = calloc(1, sizeof(*psa));
-    psa->ctx = ctx;
-    psa->log = logHelper;
-    psa->verbose = celix_bundleContext_getPropertyAsBool(ctx, PUBSUB_ZMQ_VERBOSE_KEY, PUBSUB_ZMQ_VERBOSE_DEFAULT);
-    psa->fwUUID = celix_bundleContext_getProperty(ctx, OSGI_FRAMEWORK_FRAMEWORK_UUID, NULL);
-
-    char *ip = NULL;
-    const char *confIp = celix_bundleContext_getProperty(ctx, PUBSUB_ZMQ_PSA_IP_KEY , NULL);
-    if (confIp != NULL) {
-        if (strchr(confIp, '/') != NULL) {
-            // IP with subnet prefix specified
-            ip = ipUtils_findIpBySubnet(confIp);
-            if (ip == NULL) {
-                L_WARN("[PSA_ZMQ] Could not find interface for requested subnet %s", confIp);
-            }
-        } else {
-            // IP address specified
-            ip = strndup(confIp, 1024);
-        }
-    }
-
-    if (ip == NULL) {
-        //try to get ip from itf
-        const char *interface = celix_bundleContext_getProperty(ctx, PUBSUB_ZMQ_PSA_ITF_KEY, NULL);
-        zmq_getIpAddress(interface, &ip);
-    }
-
-    if (ip == NULL) {
-        L_WARN("[PSA_ZMQ] Could not determine IP address for PSA, using default ip (%s)", PUBSUB_ZMQ_DEFAULT_IP);
-        ip = strndup(PUBSUB_ZMQ_DEFAULT_IP, 1024);
-    }
-
-    psa->ipAddress = ip;
-    if (psa->verbose) {
-        L_INFO("[PSA_ZMQ] Using %s for service annunciation", ip);
-    }
-
-
-    long basePort = celix_bundleContext_getPropertyAsLong(ctx, PSA_ZMQ_BASE_PORT, PSA_ZMQ_DEFAULT_BASE_PORT);
-    long maxPort = celix_bundleContext_getPropertyAsLong(ctx, PSA_ZMQ_MAX_PORT, PSA_ZMQ_DEFAULT_MAX_PORT);
-    psa->basePort = (unsigned int)basePort;
-    psa->maxPort = (unsigned int)maxPort;
-    if (psa->verbose) {
-        L_INFO("[PSA_ZMQ] Using base till max port: %i till %i", psa->basePort, psa->maxPort);
-    }
-
-    // Disable Signal Handling by CZMQ
-    setenv("ZSYS_SIGHANDLER", "false", true);
-
-    long nrThreads = celix_bundleContext_getPropertyAsLong(ctx, PUBSUB_ZMQ_NR_THREADS_KEY, 0);
-    if (nrThreads > 0) {
-        zsys_set_io_threads((size_t)nrThreads);
-        L_INFO("[PSA_ZMQ] Using %d threads for ZMQ", (size_t)nrThreads);
-    }
-
-
-#ifdef BUILD_WITH_ZMQ_SECURITY
-    // Setup authenticator
-    zactor_t* auth = zactor_new (zauth, NULL);
-    zstr_sendx(auth, "VERBOSE", NULL);
-
-    // Load all public keys of subscribers into the application
-    // This step is done for authenticating subscribers
-    char curve_folder_path[MAX_KEY_FOLDER_PATH_LENGTH];
-    char* keys_bundle_dir = pubsub_getKeysBundleDir(context);
-    snprintf(curve_folder_path, MAX_KEY_FOLDER_PATH_LENGTH, "%s/META-INF/keys/subscriber/public", keys_bundle_dir);
-    zstr_sendx (auth, "CURVE", curve_folder_path, NULL);
-    free(keys_bundle_dir);
-
-    (*admin)->zmq_auth = auth;
-#endif
-
-    psa->defaultScore = celix_bundleContext_getPropertyAsDouble(ctx, PSA_ZMQ_DEFAULT_SCORE_KEY, PSA_ZMQ_DEFAULT_SCORE);
-    psa->qosSampleScore = celix_bundleContext_getPropertyAsDouble(ctx, PSA_ZMQ_QOS_SAMPLE_SCORE_KEY, PSA_ZMQ_DEFAULT_QOS_SAMPLE_SCORE);
-    psa->qosControlScore = celix_bundleContext_getPropertyAsDouble(ctx, PSA_ZMQ_QOS_CONTROL_SCORE_KEY, PSA_ZMQ_DEFAULT_QOS_CONTROL_SCORE);
-
-    celixThreadMutex_create(&psa->serializers.mutex, NULL);
-    psa->serializers.map = hashMap_create(NULL, NULL, NULL, NULL);
-
-    celixThreadMutex_create(&psa->protocols.mutex, NULL);
-    psa->protocols.map = hashMap_create(NULL, NULL, NULL, NULL);
-
-    celixThreadMutex_create(&psa->topicSenders.mutex, NULL);
-    psa->topicSenders.map = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-
-    celixThreadMutex_create(&psa->topicReceivers.mutex, NULL);
-    psa->topicReceivers.map = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-
-    celixThreadMutex_create(&psa->discoveredEndpoints.mutex, NULL);
-    psa->discoveredEndpoints.map = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-
-    return psa;
-}
-
-void pubsub_zmqAdmin_destroy(pubsub_zmq_admin_t *psa) {
-    if (psa == NULL) {
-        return;
-    }
-
-    //note assuming al psa register services and service tracker are removed.
-
-    celixThreadMutex_lock(&psa->topicSenders.mutex);
-    hash_map_iterator_t iter = hashMapIterator_construct(psa->topicSenders.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        pubsub_zmq_topic_sender_t *sender = hashMapIterator_nextValue(&iter);
-        pubsub_zmqTopicSender_destroy(sender);
-    }
-    celixThreadMutex_unlock(&psa->topicSenders.mutex);
-
-    celixThreadMutex_lock(&psa->topicReceivers.mutex);
-    iter = hashMapIterator_construct(psa->topicReceivers.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        pubsub_zmq_topic_receiver_t *recv = hashMapIterator_nextValue(&iter);
-        pubsub_zmqTopicReceiver_destroy(recv);
-    }
-    celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-
-    celixThreadMutex_lock(&psa->discoveredEndpoints.mutex);
-    iter = hashMapIterator_construct(psa->discoveredEndpoints.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        celix_properties_t *ep = hashMapIterator_nextValue(&iter);
-        celix_properties_destroy(ep);
-    }
-    celixThreadMutex_unlock(&psa->discoveredEndpoints.mutex);
-
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    iter = hashMapIterator_construct(psa->serializers.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_zmq_serializer_entry_t *entry = hashMapIterator_nextValue(&iter);
-        free(entry);
-    }
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-
-    celixThreadMutex_lock(&psa->protocols.mutex);
-    iter = hashMapIterator_construct(psa->protocols.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_zmq_protocol_entry_t *entry = hashMapIterator_nextValue(&iter);
-        free(entry);
-    }
-    celixThreadMutex_unlock(&psa->protocols.mutex);
-
-    celixThreadMutex_destroy(&psa->topicSenders.mutex);
-    hashMap_destroy(psa->topicSenders.map, true, false);
-
-    celixThreadMutex_destroy(&psa->topicReceivers.mutex);
-    hashMap_destroy(psa->topicReceivers.map, true, false);
-
-    celixThreadMutex_destroy(&psa->discoveredEndpoints.mutex);
-    hashMap_destroy(psa->discoveredEndpoints.map, false, false);
-
-    celixThreadMutex_destroy(&psa->serializers.mutex);
-    hashMap_destroy(psa->serializers.map, false, false);
-
-    celixThreadMutex_destroy(&psa->protocols.mutex);
-    hashMap_destroy(psa->protocols.map, false, false);
-
-    if (psa->zmq_auth != NULL) {
-        zactor_destroy(&psa->zmq_auth);
-    }
-
-    free(psa->ipAddress);
-
-    free(psa);
-}
-
-void pubsub_zmqAdmin_addSerializerSvc(void *handle, void *svc, const celix_properties_t *props) {
-    pubsub_zmq_admin_t *psa = handle;
-
-    const char *serType = celix_properties_get(props, PUBSUB_SERIALIZER_TYPE_KEY, NULL);
-    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L);
-
-    if (serType == NULL) {
-        L_INFO("[PSA_ZMQ] Ignoring serializer service without %s property", PUBSUB_SERIALIZER_TYPE_KEY);
-        return;
-    }
-
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    psa_zmq_serializer_entry_t *entry = hashMap_get(psa->serializers.map, (void*)svcId);
-    if (entry == NULL) {
-        entry = calloc(1, sizeof(*entry));
-        entry->serType = serType;
-        entry->svcId = svcId;
-        entry->svc = svc;
-        hashMap_put(psa->serializers.map, (void*)svcId, entry);
-    }
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-}
-
-void pubsub_zmqAdmin_removeSerializerSvc(void *handle, void *svc, const celix_properties_t *props) {
-    pubsub_zmq_admin_t *psa = handle;
-    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L);
-
-    //remove serializer
-    // 1) First find entry and
-    // 2) loop and destroy all topic sender using the serializer and
-    // 3) loop and destroy all topic receivers using the serializer
-    // Note that it is the responsibility of the topology manager to create new topic senders/receivers
-
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    psa_zmq_serializer_entry_t *entry = hashMap_remove(psa->serializers.map, (void*)svcId);
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-
-    if (entry != NULL) {
-        celixThreadMutex_lock(&psa->topicSenders.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(psa->topicSenders.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            hash_map_entry_t *senderEntry = hashMapIterator_nextEntry(&iter);
-            pubsub_zmq_topic_sender_t *sender = hashMapEntry_getValue(senderEntry);
-            if (sender != NULL && entry->svcId == pubsub_zmqTopicSender_serializerSvcId(sender)) {
-                char *key = hashMapEntry_getKey(senderEntry);
-                hashMapIterator_remove(&iter);
-                pubsub_zmqTopicSender_destroy(sender);
-                free(key);
-            }
-        }
-        celixThreadMutex_unlock(&psa->topicSenders.mutex);
-
-        celixThreadMutex_lock(&psa->topicReceivers.mutex);
-        iter = hashMapIterator_construct(psa->topicReceivers.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            hash_map_entry_t *senderEntry = hashMapIterator_nextEntry(&iter);
-            pubsub_zmq_topic_receiver_t *receiver = hashMapEntry_getValue(senderEntry);
-            if (receiver != NULL && entry->svcId == pubsub_zmqTopicReceiver_serializerSvcId(receiver)) {
-                char *key = hashMapEntry_getKey(senderEntry);
-                hashMapIterator_remove(&iter);
-                pubsub_zmqTopicReceiver_destroy(receiver);
-                free(key);
-            }
-        }
-        celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-
-        free(entry);
-    }
-}
-
-void pubsub_zmqAdmin_addProtocolSvc(void *handle, void *svc, const celix_properties_t *props) {
-    pubsub_zmq_admin_t *psa = handle;
-
-    const char *protType = celix_properties_get(props, PUBSUB_PROTOCOL_TYPE_KEY, NULL);
-    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L);
-
-    if (protType == NULL) {
-        L_INFO("[PSA_ZMQ] Ignoring protocol service without %s property", PUBSUB_PROTOCOL_TYPE_KEY);
-        return;
-    }
-
-    celixThreadMutex_lock(&psa->protocols.mutex);
-    psa_zmq_protocol_entry_t *entry = hashMap_get(psa->protocols.map, (void*)svcId);
-    if (entry == NULL) {
-        entry = calloc(1, sizeof(*entry));
-        entry->protType = protType;
-        entry->svcId = svcId;
-        entry->svc = svc;
-        hashMap_put(psa->protocols.map, (void*)svcId, entry);
-    }
-    celixThreadMutex_unlock(&psa->protocols.mutex);
-}
-
-void pubsub_zmqAdmin_removeProtocolSvc(void *handle, void *svc, const celix_properties_t *props) {
-    pubsub_zmq_admin_t *psa = handle;
-    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L);
-
-    //remove protocol
-    // 1) First find entry and
-    // 2) loop and destroy all topic sender using the protocol and
-    // 3) loop and destroy all topic receivers using the protocol
-    // Note that it is the responsibility of the topology manager to create new topic senders/receivers
-
-    celixThreadMutex_lock(&psa->protocols.mutex);
-    psa_zmq_protocol_entry_t *entry = hashMap_remove(psa->protocols.map, (void*)svcId);
-    celixThreadMutex_unlock(&psa->protocols.mutex);
-
-    if (entry != NULL) {
-        celixThreadMutex_lock(&psa->topicSenders.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(psa->topicSenders.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            hash_map_entry_t *senderEntry = hashMapIterator_nextEntry(&iter);
-            pubsub_zmq_topic_sender_t *sender = hashMapEntry_getValue(senderEntry);
-            if (sender != NULL && entry->svcId == pubsub_zmqTopicSender_protocolSvcId(sender)) {
-                char *key = hashMapEntry_getKey(senderEntry);
-                hashMapIterator_remove(&iter);
-                pubsub_zmqTopicSender_destroy(sender);
-                free(key);
-            }
-        }
-        celixThreadMutex_unlock(&psa->topicSenders.mutex);
-
-        celixThreadMutex_lock(&psa->topicReceivers.mutex);
-        iter = hashMapIterator_construct(psa->topicReceivers.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            hash_map_entry_t *senderEntry = hashMapIterator_nextEntry(&iter);
-            pubsub_zmq_topic_receiver_t *receiver = hashMapEntry_getValue(senderEntry);
-            if (receiver != NULL && entry->svcId == pubsub_zmqTopicReceiver_protocolSvcId(receiver)) {
-                char *key = hashMapEntry_getKey(senderEntry);
-                hashMapIterator_remove(&iter);
-                pubsub_zmqTopicReceiver_destroy(receiver);
-                free(key);
-            }
-        }
-        celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-
-        free(entry);
-    }
-}
-
-celix_status_t pubsub_zmqAdmin_matchPublisher(void *handle, long svcRequesterBndId, const celix_filter_t *svcFilter, celix_properties_t **topicProperties, double *outScore, long *outSerializerSvcId, long *outProtocolSvcId) {
-    pubsub_zmq_admin_t *psa = handle;
-    L_DEBUG("[PSA_ZMQ] pubsub_zmqAdmin_matchPublisher");
-    celix_status_t  status = CELIX_SUCCESS;
-    double score = pubsubEndpoint_matchPublisher(psa->ctx, svcRequesterBndId, svcFilter->filterStr, PUBSUB_ZMQ_ADMIN_TYPE,
-                                                psa->qosSampleScore, psa->qosControlScore, psa->defaultScore, true, topicProperties, outSerializerSvcId, outProtocolSvcId);
-    *outScore = score;
-
-    return status;
-}
-
-celix_status_t pubsub_zmqAdmin_matchSubscriber(void *handle, long svcProviderBndId, const celix_properties_t *svcProperties, celix_properties_t **topicProperties, double *outScore, long *outSerializerSvcId, long *outProtocolSvcId) {
-    pubsub_zmq_admin_t *psa = handle;
-    L_DEBUG("[PSA_ZMQ] pubsub_zmqAdmin_matchSubscriber");
-    celix_status_t  status = CELIX_SUCCESS;
-    double score = pubsubEndpoint_matchSubscriber(psa->ctx, svcProviderBndId, svcProperties, PUBSUB_ZMQ_ADMIN_TYPE,
-            psa->qosSampleScore, psa->qosControlScore, psa->defaultScore, true, topicProperties, outSerializerSvcId, outProtocolSvcId);
-    if (outScore != NULL) {
-        *outScore = score;
-    }
-    return status;
-}
-
-celix_status_t pubsub_zmqAdmin_matchDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint, bool *outMatch) {
-    pubsub_zmq_admin_t *psa = handle;
-    L_DEBUG("[PSA_ZMQ] pubsub_zmqAdmin_matchEndpoint");
-    celix_status_t  status = CELIX_SUCCESS;
-    bool match = pubsubEndpoint_match(psa->ctx, psa->log, endpoint, PUBSUB_ZMQ_ADMIN_TYPE, true, NULL, NULL);
-    if (outMatch != NULL) {
-        *outMatch = match;
-    }
-    return status;
-}
-
-celix_status_t pubsub_zmqAdmin_setupTopicSender(void *handle, const char *scope, const char *topic, const celix_properties_t *topicProperties, long serializerSvcId, long protocolSvcId, celix_properties_t **outPublisherEndpoint) {
-    pubsub_zmq_admin_t *psa = handle;
-    celix_status_t  status = CELIX_SUCCESS;
-
-    //1) Create TopicSender
-    //2) Store TopicSender
-    //3) Connect existing endpoints
-    //4) set outPublisherEndpoint
-
-    celix_properties_t *newEndpoint = NULL;
-
-    const char *staticBindUrl = pubsub_getEnvironmentVariableWithScopeTopic(psa->ctx, PUBSUB_ZMQ_STATIC_BIND_URL_FOR, topic, scope);
-    if(staticBindUrl == NULL && topicProperties != NULL) {
-        staticBindUrl = celix_properties_get(topicProperties, PUBSUB_ZMQ_STATIC_BIND_URL, NULL);
-    }
-    char *key = pubsubEndpoint_createScopeTopicKey(scope, topic);
-
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    celixThreadMutex_lock(&psa->protocols.mutex);
-    celixThreadMutex_lock(&psa->topicSenders.mutex);
-    pubsub_zmq_topic_sender_t *sender = hashMap_get(psa->topicSenders.map, key);
-    if (sender == NULL) {
-        psa_zmq_serializer_entry_t *serEntry = hashMap_get(psa->serializers.map, (void*)serializerSvcId);
-        psa_zmq_protocol_entry_t *protEntry = hashMap_get(psa->protocols.map, (void*)protocolSvcId);
-        if (serEntry != NULL && protEntry != NULL) {
-            sender = pubsub_zmqTopicSender_create(psa->ctx, psa->log, scope, topic, serializerSvcId, serEntry->svc,
-                    protocolSvcId, protEntry->svc, psa->ipAddress, staticBindUrl, psa->basePort, psa->maxPort);
-        }
-        if (sender != NULL) {
-            const char *psaType = PUBSUB_ZMQ_ADMIN_TYPE;
-            const char *serType = serEntry->serType;
-            const char *protType = protEntry->protType;
-            newEndpoint = pubsubEndpoint_create(psa->fwUUID, scope, topic, PUBSUB_PUBLISHER_ENDPOINT_TYPE, psaType,
-                                                serType, protType, NULL);
-            celix_properties_set(newEndpoint, PUBSUB_ZMQ_URL_KEY, pubsub_zmqTopicSender_url(sender));
-
-            //if configured use a static discover url
-            const char *staticDiscUrl = celix_properties_get(topicProperties, PUBSUB_ZMQ_STATIC_DISCOVER_URL, NULL);
-            if (staticDiscUrl != NULL) {
-                celix_properties_set(newEndpoint, PUBSUB_ZMQ_URL_KEY, staticDiscUrl);
-            }
-            celix_properties_setBool(newEndpoint, PUBSUB_ZMQ_STATIC_CONFIGURED, staticBindUrl != NULL || staticDiscUrl != NULL);
-
-            //if url starts with ipc:// constrain discovery to host visibility, else use system visibility
-            const char *u = celix_properties_get(newEndpoint, PUBSUB_ZMQ_URL_KEY, "");
-            if (strncmp("ipc://", u, strlen("ipc://")) == 0) {
-                celix_properties_set(newEndpoint, PUBSUB_ENDPOINT_VISIBILITY, PUBSUB_ENDPOINT_HOST_VISIBILITY);
-            } else {
-                celix_properties_set(newEndpoint, PUBSUB_ENDPOINT_VISIBILITY, PUBSUB_ENDPOINT_SYSTEM_VISIBILITY);
-            }
-
-            //if available also set container name
-            const char *cn = celix_bundleContext_getProperty(psa->ctx, "CELIX_CONTAINER_NAME", NULL);
-            if (cn != NULL) {
-                celix_properties_set(newEndpoint, "container_name", cn);
-            }
-            hashMap_put(psa->topicSenders.map, key, sender);
-        } else {
-            L_ERROR("[PSA ZMQ] Error creating a TopicSender");
-            free(key);
-        }
-    } else {
-        free(key);
-        L_ERROR("[PSA_ZMQ] Cannot setup already existing TopicSender for scope/topic %s/%s!", scope == NULL ? "(null)" : scope, topic);
-    }
-    celixThreadMutex_unlock(&psa->topicSenders.mutex);
-    celixThreadMutex_unlock(&psa->protocols.mutex);
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-
-    if (sender != NULL && newEndpoint != NULL) {
-        //TODO connect endpoints to sender, NOTE is this needed for a zmq topic sender?
-    }
-
-    if (newEndpoint != NULL && outPublisherEndpoint != NULL) {
-        *outPublisherEndpoint = newEndpoint;
-    }
-
-    return status;
-}
-
-celix_status_t pubsub_zmqAdmin_teardownTopicSender(void *handle, const char *scope, const char *topic) {
-    pubsub_zmq_admin_t *psa = handle;
-    celix_status_t  status = CELIX_SUCCESS;
-
-    //1) Find and remove TopicSender from map
-    //2) destroy topic sender
-
-    char *key = pubsubEndpoint_createScopeTopicKey(scope, topic);
-    celixThreadMutex_lock(&psa->topicSenders.mutex);
-    hash_map_entry_t *entry = hashMap_getEntry(psa->topicSenders.map, key);
-    if (entry != NULL) {
-        char *mapKey = hashMapEntry_getKey(entry);
-        pubsub_zmq_topic_sender_t *sender = hashMap_remove(psa->topicSenders.map, key);
-        free(mapKey);
-        //TODO disconnect endpoints to sender. note is this needed for a zmq topic sender?
-        pubsub_zmqTopicSender_destroy(sender);
-    } else {
-        L_ERROR("[PSA ZMQ] Cannot teardown TopicSender with scope/topic %s/%s. Does not exists", scope == NULL ? "(null)" : scope, topic);
-    }
-    celixThreadMutex_unlock(&psa->topicSenders.mutex);
-    free(key);
-
-    return status;
-}
-
-celix_status_t pubsub_zmqAdmin_setupTopicReceiver(void *handle, const char *scope, const char *topic, const celix_properties_t *topicProperties, long serializerSvcId, long protocolSvcId, celix_properties_t **outSubscriberEndpoint) {
-    pubsub_zmq_admin_t *psa = handle;
-
-    celix_properties_t *newEndpoint = NULL;
-
-    char *key = pubsubEndpoint_createScopeTopicKey(scope, topic);
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    celixThreadMutex_lock(&psa->protocols.mutex);
-    celixThreadMutex_lock(&psa->topicReceivers.mutex);
-    pubsub_zmq_topic_receiver_t *receiver = hashMap_get(psa->topicReceivers.map, key);
-    if (receiver == NULL) {
-        psa_zmq_serializer_entry_t *serEntry = hashMap_get(psa->serializers.map, (void*)serializerSvcId);
-        psa_zmq_protocol_entry_t *protEntry = hashMap_get(psa->protocols.map, (void*)protocolSvcId);
-        if (serEntry != NULL && protEntry != NULL) {
-            receiver = pubsub_zmqTopicReceiver_create(psa->ctx, psa->log, scope, topic, topicProperties, serializerSvcId, serEntry->svc, protocolSvcId, protEntry->svc);
-        } else {
-            L_ERROR("[PSA_ZMQ] Cannot find serializer or protocol for TopicSender %s/%s", scope == NULL ? "(null)" : scope, topic);
-        }
-        if (receiver != NULL) {
-            const char *psaType = PUBSUB_ZMQ_ADMIN_TYPE;
-            const char *serType = serEntry->serType;
-            const char *protType = protEntry->protType;
-            newEndpoint = pubsubEndpoint_create(psa->fwUUID, scope, topic,
-                                                PUBSUB_SUBSCRIBER_ENDPOINT_TYPE, psaType, serType, protType, NULL);
-            //if available also set container name
-            const char *cn = celix_bundleContext_getProperty(psa->ctx, "CELIX_CONTAINER_NAME", NULL);
-            if (cn != NULL) {
-                celix_properties_set(newEndpoint, "container_name", cn);
-            }
-            hashMap_put(psa->topicReceivers.map, key, receiver);
-        } else {
-            L_ERROR("[PSA ZMQ] Error creating a TopicReceiver.");
-            free(key);
-        }
-    } else {
-        free(key);
-        L_ERROR("[PSA_ZMQ] Cannot setup already existing TopicReceiver for scope/topic %s/%s!", scope == NULL ? "(null)" : scope, topic);
-    }
-    celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-    celixThreadMutex_unlock(&psa->protocols.mutex);
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-
-    if (receiver != NULL && newEndpoint != NULL) {
-        celixThreadMutex_lock(&psa->discoveredEndpoints.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(psa->discoveredEndpoints.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            celix_properties_t *endpoint = hashMapIterator_nextValue(&iter);
-            if (pubsub_zmqAdmin_endpointIsPublisher(endpoint) && pubsubEndpoint_matchWithTopicAndScope(endpoint, topic, scope)) {
-                pubsub_zmqAdmin_connectEndpointToReceiver(psa, receiver, endpoint);
-            }
-        }
-        celixThreadMutex_unlock(&psa->discoveredEndpoints.mutex);
-    }
-
-    if (newEndpoint != NULL && outSubscriberEndpoint != NULL) {
-        *outSubscriberEndpoint = newEndpoint;
-    }
-
-    celix_status_t  status = CELIX_SUCCESS;
-    return status;
-}
-
-celix_status_t pubsub_zmqAdmin_teardownTopicReceiver(void *handle, const char *scope, const char *topic) {
-    pubsub_zmq_admin_t *psa = handle;
-
-    char *key = pubsubEndpoint_createScopeTopicKey(scope, topic);
-    celixThreadMutex_lock(&psa->topicReceivers.mutex);
-    hash_map_entry_t *entry = hashMap_getEntry(psa->topicReceivers.map, key);
-    free(key);
-    if (entry != NULL) {
-        char *receiverKey = hashMapEntry_getKey(entry);
-        pubsub_zmq_topic_receiver_t *receiver = hashMapEntry_getValue(entry);
-        hashMap_remove(psa->topicReceivers.map, receiverKey);
-
-        free(receiverKey);
-        pubsub_zmqTopicReceiver_destroy(receiver);
-    }
-    celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-
-    celix_status_t  status = CELIX_SUCCESS;
-    return status;
-}
-
-static celix_status_t pubsub_zmqAdmin_connectEndpointToReceiver(pubsub_zmq_admin_t* psa, pubsub_zmq_topic_receiver_t *receiver, const celix_properties_t *endpoint) {
-    //note can be called with discoveredEndpoint.mutex lock
-    celix_status_t status = CELIX_SUCCESS;
-
-    const char *url = celix_properties_get(endpoint, PUBSUB_ZMQ_URL_KEY, NULL);
-
-    if (url == NULL) {
-        const char *admin = celix_properties_get(endpoint, PUBSUB_ENDPOINT_ADMIN_TYPE, NULL);
-        const char *type = celix_properties_get(endpoint, PUBSUB_ENDPOINT_TYPE, NULL);
-        L_WARN("[PSA ZMQ] Error got endpoint without a zmq url (admin: %s, type: %s)", admin , type);
-        status = CELIX_BUNDLE_EXCEPTION;
-    } else {
-        pubsub_zmqTopicReceiver_connectTo(receiver, url);
-    }
-
-    return status;
-}
-
-celix_status_t pubsub_zmqAdmin_addDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint) {
-    pubsub_zmq_admin_t *psa = handle;
-
-    if (pubsub_zmqAdmin_endpointIsPublisher(endpoint)) {
-        celixThreadMutex_lock(&psa->topicReceivers.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(psa->topicReceivers.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            pubsub_zmq_topic_receiver_t *receiver = hashMapIterator_nextValue(&iter);
-            if (pubsubEndpoint_matchWithTopicAndScope(endpoint, pubsub_zmqTopicReceiver_topic(receiver), pubsub_zmqTopicReceiver_scope(receiver))) {
-                pubsub_zmqAdmin_connectEndpointToReceiver(psa, receiver, endpoint);
-            }
-        }
-        celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-    }
-
-    celixThreadMutex_lock(&psa->discoveredEndpoints.mutex);
-    celix_properties_t *cpy = celix_properties_copy(endpoint);
-    const char *uuid = celix_properties_get(cpy, PUBSUB_ENDPOINT_UUID, NULL);
-    hashMap_put(psa->discoveredEndpoints.map, (void*)uuid, cpy);
-    celixThreadMutex_unlock(&psa->discoveredEndpoints.mutex);
-
-    celix_status_t  status = CELIX_SUCCESS;
-    return status;
-}
-
-
-static celix_status_t pubsub_zmqAdmin_disconnectEndpointFromReceiver(pubsub_zmq_admin_t* psa, pubsub_zmq_topic_receiver_t *receiver, const celix_properties_t *endpoint) {
-    //note can be called with discoveredEndpoint.mutex lock
-    celix_status_t status = CELIX_SUCCESS;
-
-    const char *url = celix_properties_get(endpoint, PUBSUB_ZMQ_URL_KEY, NULL);
-
-    if (url == NULL) {
-        L_WARN("[PSA ZMQ] Error got endpoint without zmq url");
-        status = CELIX_BUNDLE_EXCEPTION;
-    } else {
-        pubsub_zmqTopicReceiver_disconnectFrom(receiver, url);
-    }
-
-    return status;
-}
-
-celix_status_t pubsub_zmqAdmin_removeDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint) {
-    pubsub_zmq_admin_t *psa = handle;
-
-    if (pubsub_zmqAdmin_endpointIsPublisher(endpoint)) {
-        celixThreadMutex_lock(&psa->topicReceivers.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(psa->topicReceivers.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            pubsub_zmq_topic_receiver_t *receiver = hashMapIterator_nextValue(&iter);
-            pubsub_zmqAdmin_disconnectEndpointFromReceiver(psa, receiver, endpoint);
-        }
-        celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-    }
-
-    celixThreadMutex_lock(&psa->discoveredEndpoints.mutex);
-    const char *uuid = celix_properties_get(endpoint, PUBSUB_ENDPOINT_UUID, NULL);
-    celix_properties_t *found = hashMap_remove(psa->discoveredEndpoints.map, (void*)uuid);
-    celixThreadMutex_unlock(&psa->discoveredEndpoints.mutex);
-
-    if (found != NULL) {
-        celix_properties_destroy(found);
-    }
-
-    celix_status_t  status = CELIX_SUCCESS;
-    return status;
-}
-
-bool pubsub_zmqAdmin_executeCommand(void *handle, const char *commandLine, FILE *out, FILE *errStream __attribute__((unused))) {
-    pubsub_zmq_admin_t *psa = handle;
-    celix_status_t  status = CELIX_SUCCESS;
-
-
-    char *line = celix_utils_strdup(commandLine);
-    char *token = line;
-    strtok_r(line, " ", &token); //first token is command name
-    strtok_r(NULL, " ", &token); //second token is sub command
-
-    if (celix_utils_stringEquals(token, "nr_of_receivers")) {
-        celixThreadMutex_lock(&psa->topicReceivers.mutex);
-        fprintf(out,"%i\n", hashMap_size(psa->topicReceivers.map));
-        celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-    }
-    if (celix_utils_stringEquals(token, "nr_of_senders")) {
-        celixThreadMutex_lock(&psa->topicSenders.mutex);
-        fprintf(out, "%i\n", hashMap_size(psa->topicSenders.map));
-        celixThreadMutex_unlock(&psa->topicSenders.mutex);
-    }
-
-    fprintf(out, "\n");
-    fprintf(out, "Topic Senders:\n");
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    celixThreadMutex_lock(&psa->protocols.mutex);
-    celixThreadMutex_lock(&psa->topicSenders.mutex);
-    hash_map_iterator_t iter = hashMapIterator_construct(psa->topicSenders.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        pubsub_zmq_topic_sender_t *sender = hashMapIterator_nextValue(&iter);
-
-        long serSvcId = pubsub_zmqTopicSender_serializerSvcId(sender);
-        psa_zmq_serializer_entry_t *serEntry = hashMap_get(psa->serializers.map, (void*)serSvcId);
-
-        long protSvcId = pubsub_zmqTopicSender_protocolSvcId(sender);
-        psa_zmq_protocol_entry_t *protEntry = hashMap_get(psa->protocols.map, (void*)protSvcId);
-
-        const char *serType = serEntry == NULL ? "!Error!" : serEntry->serType;
-        const char *protType = protEntry == NULL ? "!Error!" : protEntry->protType;
-        const char *scope = pubsub_zmqTopicSender_scope(sender);
-        const char *topic = pubsub_zmqTopicSender_topic(sender);
-        const char *url = pubsub_zmqTopicSender_url(sender);
-        const char *postUrl = pubsub_zmqTopicSender_isStatic(sender) ? " (static)" : "";
-        fprintf(out, "|- Topic Sender %s/%s\n", scope == NULL ? "(null)" : scope, topic);
-        fprintf(out, "   |- serializer type = %s\n", serType);
-        fprintf(out, "   |- protocol type = %s\n", protType);
-        fprintf(out, "   |- url            = %s%s\n", url, postUrl);
-    }
-    celixThreadMutex_unlock(&psa->topicSenders.mutex);
-    celixThreadMutex_unlock(&psa->protocols.mutex);
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-
-    fprintf(out, "\n");
-    fprintf(out, "\nTopic Receivers:\n");
-    celixThreadMutex_lock(&psa->serializers.mutex);
-    celixThreadMutex_lock(&psa->protocols.mutex);
-    celixThreadMutex_lock(&psa->topicReceivers.mutex);
-    iter = hashMapIterator_construct(psa->topicReceivers.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        pubsub_zmq_topic_receiver_t *receiver = hashMapIterator_nextValue(&iter);
-        long serSvcId = pubsub_zmqTopicReceiver_serializerSvcId(receiver);
-        psa_zmq_serializer_entry_t *serEntry = hashMap_get(psa->serializers.map, (void*)serSvcId);
-
-        long protSvcId = pubsub_zmqTopicReceiver_protocolSvcId(receiver);
-        psa_zmq_protocol_entry_t *protEntry = hashMap_get(psa->protocols.map, (void*)protSvcId);
-
-
-        const char *serType = serEntry == NULL ? "!Error!" : serEntry->serType;
-        const char *protType = protEntry == NULL ? "!Error!" : protEntry->protType;
-        const char *scope = pubsub_zmqTopicReceiver_scope(receiver);
-        const char *topic = pubsub_zmqTopicReceiver_topic(receiver);
-
-        celix_array_list_t *connected = celix_arrayList_create();
-        celix_array_list_t *unconnected = celix_arrayList_create();
-        pubsub_zmqTopicReceiver_listConnections(receiver, connected, unconnected);
-
-        fprintf(out, "|- Topic Receiver %s/%s\n", scope == NULL ? "(null)" : scope, topic);
-        fprintf(out, "   |- serializer type = %s\n", serType);
-        fprintf(out, "   |- protocol type = %s\n", protType);
-        for (int i = 0; i < celix_arrayList_size(connected); ++i) {
-            char *url = celix_arrayList_get(connected, i);
-            fprintf(out, "   |- connected url   = %s\n", url);
-            free(url);
-        }
-        for (int i = 0; i < celix_arrayList_size(unconnected); ++i) {
-            char *url = celix_arrayList_get(unconnected, i);
-            fprintf(out, "   |- unconnected url = %s\n", url);
-            free(url);
-        }
-        celix_arrayList_destroy(connected);
-        celix_arrayList_destroy(unconnected);
-    }
-    celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-    celixThreadMutex_unlock(&psa->protocols.mutex);
-    celixThreadMutex_unlock(&psa->serializers.mutex);
-    fprintf(out, "\n");
-    free(line);
-
-    return status;
-}
-
-pubsub_admin_metrics_t* pubsub_zmqAdmin_metrics(void *handle) {
-    pubsub_zmq_admin_t *psa = handle;
-    pubsub_admin_metrics_t *result = calloc(1, sizeof(*result));
-    snprintf(result->psaType, PUBSUB_AMDIN_METRICS_NAME_MAX, "%s", PUBSUB_ZMQ_ADMIN_TYPE);
-    result->senders = celix_arrayList_create();
-    result->receivers = celix_arrayList_create();
-
-    celixThreadMutex_lock(&psa->topicSenders.mutex);
-    hash_map_iterator_t iter = hashMapIterator_construct(psa->topicSenders.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        pubsub_zmq_topic_sender_t *sender = hashMapIterator_nextValue(&iter);
-        pubsub_admin_sender_metrics_t *metrics = pubsub_zmqTopicSender_metrics(sender);
-        celix_arrayList_add(result->senders, metrics);
-    }
-    celixThreadMutex_unlock(&psa->topicSenders.mutex);
-
-    celixThreadMutex_lock(&psa->topicReceivers.mutex);
-    iter = hashMapIterator_construct(psa->topicReceivers.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        pubsub_zmq_topic_receiver_t *receiver = hashMapIterator_nextValue(&iter);
-        pubsub_admin_receiver_metrics_t *metrics = pubsub_zmqTopicReceiver_metrics(receiver);
-        celix_arrayList_add(result->receivers, metrics);
-    }
-    celixThreadMutex_unlock(&psa->topicReceivers.mutex);
-
-    return result;
-}
-
-#ifndef ANDROID
-static celix_status_t zmq_getIpAddress(const 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;
-}
-#endif
\ No newline at end of file
diff --git a/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_zmq_admin.h b/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_zmq_admin.h
deleted file mode 100644
index d241f1f..0000000
--- a/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_zmq_admin.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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_PUBSUB_ZMQ_ADMIN_H
-#define CELIX_PUBSUB_ZMQ_ADMIN_H
-
-#include <pubsub_admin_metrics.h>
-#include "celix_api.h"
-#include "celix_log_helper.h"
-#include "pubsub_psa_zmq_constants.h"
-
-typedef struct pubsub_zmq_admin pubsub_zmq_admin_t;
-
-pubsub_zmq_admin_t* pubsub_zmqAdmin_create(celix_bundle_context_t *ctx, celix_log_helper_t *logHelper);
-void pubsub_zmqAdmin_destroy(pubsub_zmq_admin_t *psa);
-
-celix_status_t pubsub_zmqAdmin_matchPublisher(void *handle, long svcRequesterBndId, const celix_filter_t *svcFilter, celix_properties_t **topicProperties, double *score, long *serializerSvcId, long *ProtocolSvcId);
-celix_status_t pubsub_zmqAdmin_matchSubscriber(void *handle, long svcProviderBndId, const celix_properties_t *svcProperties, celix_properties_t **topicProperties, double *score, long *serializerSvcId, long *ProtocolSvcId);
-celix_status_t pubsub_zmqAdmin_matchDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint, bool *match);
-
-celix_status_t pubsub_zmqAdmin_setupTopicSender(void *handle, const char *scope, const char *topic, const celix_properties_t* topicProperties, long serializerSvcId, long protocolSvcId, celix_properties_t **publisherEndpoint);
-celix_status_t pubsub_zmqAdmin_teardownTopicSender(void *handle, const char *scope, const char *topic);
-
-celix_status_t pubsub_zmqAdmin_setupTopicReceiver(void *handle, const char *scope, const char *topic, const celix_properties_t* topicProperties, long serializerSvcId, long protocolSvcId, celix_properties_t **subscriberEndpoint);
-celix_status_t pubsub_zmqAdmin_teardownTopicReceiver(void *handle, const char *scope, const char *topic);
-
-celix_status_t pubsub_zmqAdmin_addDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint);
-celix_status_t pubsub_zmqAdmin_removeDiscoveredEndpoint(void *handle, const celix_properties_t *endpoint);
-
-void pubsub_zmqAdmin_addSerializerSvc(void *handle, void *svc, const celix_properties_t *props);
-void pubsub_zmqAdmin_removeSerializerSvc(void *handle, void *svc, const celix_properties_t *props);
-
-void pubsub_zmqAdmin_addProtocolSvc(void *handle, void *svc, const celix_properties_t *props);
-void pubsub_zmqAdmin_removeProtocolSvc(void *handle, void *svc, const celix_properties_t *props);
-
-bool pubsub_zmqAdmin_executeCommand(void *handle, const char *commandLine, FILE *outStream, FILE *errStream);
-
-pubsub_admin_metrics_t* pubsub_zmqAdmin_metrics(void *handle);
-
-#endif //CELIX_PUBSUB_ZMQ_ADMIN_H
-
diff --git a/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_zmq_topic_receiver.c b/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_zmq_topic_receiver.c
deleted file mode 100644
index 28146af..0000000
--- a/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_zmq_topic_receiver.c
+++ /dev/null
@@ -1,855 +0,0 @@
-/*
- * 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 <pubsub_serializer.h>
-#include <pubsub_protocol.h>
-#include <stdlib.h>
-#include <pubsub/subscriber.h>
-#include <memory.h>
-#include <pubsub_constants.h>
-#if !defined(__APPLE__)
-    #include <sys/epoll.h>
-#endif
-#include <assert.h>
-#include <pubsub_endpoint.h>
-#include <arpa/inet.h>
-#include <czmq.h>
-#include <celix_log_helper.h>
-#include "pubsub_zmq_topic_receiver.h"
-#include "pubsub_psa_zmq_constants.h"
-
-#include <uuid/uuid.h>
-#include <pubsub_admin_metrics.h>
-#include <pubsub_utils.h>
-#include <celix_api.h>
-
-#include "celix_utils_api.h"
-
-#define PSA_ZMQ_RECV_TIMEOUT 1000
-
-#ifndef UUID_STR_LEN
-#define UUID_STR_LEN 37
-#endif
-
-
-#define L_DEBUG(...) \
-    celix_logHelper_log(receiver->logHelper, CELIX_LOG_LEVEL_DEBUG, __VA_ARGS__)
-#define L_INFO(...) \
-    celix_logHelper_log(receiver->logHelper, CELIX_LOG_LEVEL_INFO, __VA_ARGS__)
-#define L_WARN(...) \
-    celix_logHelper_log(receiver->logHelper, CELIX_LOG_LEVEL_WARNING, __VA_ARGS__)
-#define L_ERROR(...) \
-    celix_logHelper_log(receiver->logHelper, CELIX_LOG_LEVEL_ERROR, __VA_ARGS__)
-
-struct pubsub_zmq_topic_receiver {
-    celix_bundle_context_t *ctx;
-    celix_log_helper_t *logHelper;
-    long serializerSvcId;
-    pubsub_serializer_service_t *serializer;
-    long protocolSvcId;
-    pubsub_protocol_service_t *protocol;
-    char *scope;
-    char *topic;
-    bool metricsEnabled;
-
-    void *zmqCtx;
-    void *zmqSock;
-
-    char sync[8];
-
-    struct {
-        celix_thread_t thread;
-        celix_thread_mutex_t mutex;
-        bool running;
-    } recvThread;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = zmq url, value = psa_zmq_requested_connection_entry_t*
-        bool allConnected; //true if all requestedConnectection are connected
-    } requestedConnections;
-
-    long subscriberTrackerId;
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map; //key = bnd id, value = psa_zmq_subscriber_entry_t
-        bool allInitialized;
-    } subscribers;
-};
-
-typedef struct psa_zmq_requested_connection_entry {
-    char *url;
-    bool connected;
-    bool statically; //true if the connection is statically configured through the topic properties.
-} psa_zmq_requested_connection_entry_t;
-
-typedef struct psa_zmq_subscriber_metrics_entry_t {
-    unsigned int msgTypeId;
-    uuid_t origin;
-
-    unsigned long nrOfMessagesReceived;
-    unsigned long nrOfSerializationErrors;
-    struct timespec lastMessageReceived;
-    double averageTimeBetweenMessagesInSeconds;
-    double averageSerializationTimeInSeconds;
-    double averageDelayInSeconds;
-    double maxDelayInSeconds;
-    double minDelayInSeconds;
-    unsigned int lastSeqNr;
-    unsigned long nrOfMissingSeqNumbers;
-} psa_zmq_subscriber_metrics_entry_t;
-
-typedef struct psa_zmq_subscriber_entry {
-    hash_map_t *msgTypes; //map from serializer svc
-    hash_map_t *metrics; //key = msg type id, value = hash_map (key = origin uuid, value = psa_zmq_subscriber_metrics_entry_t*
-    hash_map_t *subscriberServices; //key = servide id, value = pubsub_subscriber_t*
-    bool initialized; //true if the init function is called through the receive thread
-} psa_zmq_subscriber_entry_t;
-
-
-static void pubsub_zmqTopicReceiver_addSubscriber(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *owner);
-static void pubsub_zmqTopicReceiver_removeSubscriber(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *owner);
-static void* psa_zmq_recvThread(void * data);
-static void psa_zmq_connectToAllRequestedConnections(pubsub_zmq_topic_receiver_t *receiver);
-static void psa_zmq_initializeAllSubscribers(pubsub_zmq_topic_receiver_t *receiver);
-static void psa_zmq_setupZmqContext(pubsub_zmq_topic_receiver_t *receiver, const celix_properties_t *topicProperties);
-static void psa_zmq_setupZmqSocket(pubsub_zmq_topic_receiver_t *receiver, const celix_properties_t *topicProperties);
-static bool psa_zmq_checkVersion(version_pt msgVersion, uint16_t major, uint16_t minor);
-
-
-pubsub_zmq_topic_receiver_t* pubsub_zmqTopicReceiver_create(celix_bundle_context_t *ctx,
-                                                              celix_log_helper_t *logHelper,
-                                                              const char *scope,
-                                                              const char *topic,
-                                                              const celix_properties_t *topicProperties,
-                                                              long serializerSvcId,
-                                                              pubsub_serializer_service_t *serializer,
-                                                              long protocolSvcId,
-                                                              pubsub_protocol_service_t *protocol) {
-    pubsub_zmq_topic_receiver_t *receiver = calloc(1, sizeof(*receiver));
-    receiver->ctx = ctx;
-    receiver->logHelper = logHelper;
-    receiver->serializerSvcId = serializerSvcId;
-    receiver->serializer = serializer;
-    receiver->protocolSvcId = protocolSvcId;
-    receiver->protocol = protocol;
-    receiver->scope = scope == NULL ? NULL : strndup(scope, 1024 * 1024);
-    receiver->topic = strndup(topic, 1024 * 1024);
-    receiver->metricsEnabled = celix_bundleContext_getPropertyAsBool(ctx, PSA_ZMQ_METRICS_ENABLED, PSA_ZMQ_DEFAULT_METRICS_ENABLED);
-
-#ifdef BUILD_WITH_ZMQ_SECURITY
-    char* keys_bundle_dir = pubsub_getKeysBundleDir(bundle_context);
-    if (keys_bundle_dir == NULL) {
-        return CELIX_SERVICE_EXCEPTION;
-    }
-
-    const char* keys_file_path = NULL;
-    const char* keys_file_name = NULL;
-    bundleContext_getProperty(bundle_context, PROPERTY_KEYS_FILE_PATH, &keys_file_path);
-    bundleContext_getProperty(bundle_context, PROPERTY_KEYS_FILE_NAME, &keys_file_name);
-
-    char sub_cert_path[MAX_CERT_PATH_LENGTH];
-    char pub_cert_path[MAX_CERT_PATH_LENGTH];
-
-    //certificate path ".cache/bundle{id}/version0.0/./META-INF/keys/subscriber/private/sub_{topic}.key.enc"
-    snprintf(sub_cert_path, MAX_CERT_PATH_LENGTH, "%s/META-INF/keys/subscriber/private/sub_%s.key.enc", keys_bundle_dir, topic);
-    snprintf(pub_cert_path, MAX_CERT_PATH_LENGTH, "%s/META-INF/keys/publisher/public/pub_%s.pub", keys_bundle_dir, topic);
-    free(keys_bundle_dir);
-
-    printf("PSA_ZMQ_PSA_ZMQ_TS: Loading subscriber key '%s'\n", sub_cert_path);
-    printf("PSA_ZMQ_PSA_ZMQ_TS: Loading publisher key '%s'\n", pub_cert_path);
-
-    zcert_t* sub_cert = get_zcert_from_encoded_file((char *) keys_file_path, (char *) keys_file_name, sub_cert_path);
-    if (sub_cert == NULL) {
-        printf("PSA_ZMQ_PSA_ZMQ_TS: Cannot load key '%s'\n", sub_cert_path);
-        return CELIX_SERVICE_EXCEPTION;
-    }
-
-    zcert_t* pub_cert = zcert_load(pub_cert_path);
-    if (pub_cert == NULL) {
-        zcert_destroy(&sub_cert);
-        printf("PSA_ZMQ_PSA_ZMQ_TS: Cannot load key '%s'\n", pub_cert_path);
-        return CELIX_SERVICE_EXCEPTION;
-    }
-
-    const char* pub_key = zcert_public_txt(pub_cert);
-#endif
-    receiver->zmqCtx = zmq_ctx_new();
-    if (receiver->zmqCtx != NULL) {
-        psa_zmq_setupZmqContext(receiver, topicProperties);
-        receiver->zmqSock = zmq_socket(receiver->zmqCtx, ZMQ_SUB);
-    } else {
-        //LOG ctx problem
-    }
-    if (receiver->zmqSock != NULL) {
-        psa_zmq_setupZmqSocket(receiver, topicProperties);
-    } else if (receiver->zmqCtx != NULL) {
-        //LOG sock problem
-    }
-
-    if (receiver->zmqSock == NULL) {
-#ifdef BUILD_WITH_ZMQ_SECURITY
-        zcert_destroy(&sub_cert);
-        zcert_destroy(&pub_cert);
-#endif
-    }
-
-
-    if (receiver->zmqSock != NULL) {
-        celixThreadMutex_create(&receiver->subscribers.mutex, NULL);
-        celixThreadMutex_create(&receiver->requestedConnections.mutex, NULL);
-        celixThreadMutex_create(&receiver->recvThread.mutex, NULL);
-
-        receiver->subscribers.map = hashMap_create(NULL, NULL, NULL, NULL);
-        receiver->requestedConnections.map = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-    }
-
-    const char *staticConnectUrls = pubsub_getEnvironmentVariableWithScopeTopic(ctx, PUBSUB_ZMQ_STATIC_CONNECT_URLS_FOR, topic, scope);
-    if(staticConnectUrls == NULL) {
-        staticConnectUrls = celix_properties_get(topicProperties, PUBSUB_ZMQ_STATIC_CONNECT_URLS, NULL);
-    }
-    if (receiver->zmqSock != NULL && staticConnectUrls != NULL) {
-        char *urlsCopy = strndup(staticConnectUrls, 1024*1024);
-        char* url;
-        char* save = urlsCopy;
-
-        while ((url = strtok_r(save, " ", &save))) {
-            psa_zmq_requested_connection_entry_t *entry = calloc(1, sizeof(*entry));
-            entry->statically = true;
-            entry->connected = false;
-            entry->url = strndup(url, 1024*1024);
-            hashMap_put(receiver->requestedConnections.map, entry->url, entry);
-            receiver->requestedConnections.allConnected = false;
-        }
-        free(urlsCopy);
-    }
-
-    //track subscribers
-    if (receiver->zmqSock != NULL ) {
-        int size = snprintf(NULL, 0, "(%s=%s)", PUBSUB_SUBSCRIBER_TOPIC, topic);
-        char buf[size+1];
-        snprintf(buf, (size_t)size+1, "(%s=%s)", PUBSUB_SUBSCRIBER_TOPIC, topic);
-        celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
-        opts.filter.ignoreServiceLanguage = true;
-        opts.filter.serviceName = PUBSUB_SUBSCRIBER_SERVICE_NAME;
-        opts.filter.filter = buf;
-        opts.callbackHandle = receiver;
-        opts.addWithOwner = pubsub_zmqTopicReceiver_addSubscriber;
-        opts.removeWithOwner = pubsub_zmqTopicReceiver_removeSubscriber;
-
-        receiver->subscriberTrackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts);
-    }
-
-    if (receiver->zmqSock != NULL ) {
-        receiver->recvThread.running = true;
-        celixThread_create(&receiver->recvThread.thread, NULL, psa_zmq_recvThread, receiver);
-        char name[64];
-        snprintf(name, 64, "ZMQ TR %s/%s", scope == NULL ? "(null)" : scope, topic);
-        celixThread_setName(&receiver->recvThread.thread, name);
-    }
-
-    if (receiver->zmqSock == NULL) {
-        if (receiver->scope != NULL) {
-            free(receiver->scope);
-        }
-        free(receiver->topic);
-        free(receiver);
-        receiver = NULL;
-        L_ERROR("[PSA_ZMQ] Cannot create TopicReceiver for %s/%s", scope == NULL ? "(null)" : scope, topic);
-    }
-
-    return receiver;
-}
-
-void pubsub_zmqTopicReceiver_destroy(pubsub_zmq_topic_receiver_t *receiver) {
-    if (receiver != NULL) {
-
-        celixThreadMutex_lock(&receiver->recvThread.mutex);
-        receiver->recvThread.running = false;
-        celixThreadMutex_unlock(&receiver->recvThread.mutex);
-        celixThread_join(receiver->recvThread.thread, NULL);
-
-        celix_bundleContext_stopTracker(receiver->ctx, receiver->subscriberTrackerId);
-
-        celixThreadMutex_lock(&receiver->subscribers.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(receiver->subscribers.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_zmq_subscriber_entry_t *entry = hashMapIterator_nextValue(&iter);
-            if (entry != NULL)  {
-                receiver->serializer->destroySerializerMap(receiver->serializer->handle, entry->msgTypes);
-                hashMap_destroy(entry->subscriberServices, false, false);
-                free(entry);
-            }
-
-            hash_map_iterator_t iter2 = hashMapIterator_construct(entry->metrics);
-            while (hashMapIterator_hasNext(&iter2)) {
-                hash_map_t *origins = hashMapIterator_nextValue(&iter2);
-                hashMap_destroy(origins, true, true);
-            }
-            hashMap_destroy(entry->metrics, false, false);
-        }
-        hashMap_destroy(receiver->subscribers.map, false, false);
-
-
-        celixThreadMutex_unlock(&receiver->subscribers.mutex);
-
-        celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-        iter = hashMapIterator_construct(receiver->requestedConnections.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_zmq_requested_connection_entry_t *entry = hashMapIterator_nextValue(&iter);
-            if (entry != NULL) {
-                free(entry->url);
-                free(entry);
-            }
-        }
-        hashMap_destroy(receiver->requestedConnections.map, false, false);
-        celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-
-        celixThreadMutex_destroy(&receiver->subscribers.mutex);
-        celixThreadMutex_destroy(&receiver->requestedConnections.mutex);
-        celixThreadMutex_destroy(&receiver->recvThread.mutex);
-
-        zmq_close(receiver->zmqSock);
-        zmq_ctx_term(receiver->zmqCtx);
-
-        free(receiver->scope);
-        free(receiver->topic);
-    }
-    free(receiver);
-}
-
-const char* pubsub_zmqTopicReceiver_scope(pubsub_zmq_topic_receiver_t *receiver) {
-    return receiver->scope;
-}
-const char* pubsub_zmqTopicReceiver_topic(pubsub_zmq_topic_receiver_t *receiver) {
-    return receiver->topic;
-}
-
-long pubsub_zmqTopicReceiver_serializerSvcId(pubsub_zmq_topic_receiver_t *receiver) {
-    return receiver->serializerSvcId;
-}
-
-long pubsub_zmqTopicReceiver_protocolSvcId(pubsub_zmq_topic_receiver_t *receiver) {
-    return receiver->protocolSvcId;
-}
-
-void pubsub_zmqTopicReceiver_listConnections(pubsub_zmq_topic_receiver_t *receiver, celix_array_list_t *connectedUrls, celix_array_list_t *unconnectedUrls) {
-    celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-    hash_map_iterator_t iter = hashMapIterator_construct(receiver->requestedConnections.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_zmq_requested_connection_entry_t *entry = hashMapIterator_nextValue(&iter);
-        char *url = NULL;
-        asprintf(&url, "%s%s", entry->url, entry->statically ? " (static)" : "");
-        if (entry->connected) {
-            celix_arrayList_add(connectedUrls, url);
-        } else {
-            celix_arrayList_add(unconnectedUrls, url);
-        }
-    }
-    celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-}
-
-
-void pubsub_zmqTopicReceiver_connectTo(
-        pubsub_zmq_topic_receiver_t *receiver,
-        const char *url) {
-    L_DEBUG("[PSA_ZMQ] TopicReceiver %s/%s connecting to zmq url %s", receiver->scope == NULL ? "(null)" : receiver->scope, receiver->topic, url);
-
-    celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-    psa_zmq_requested_connection_entry_t *entry = hashMap_get(receiver->requestedConnections.map, url);
-    if (entry == NULL) {
-        entry = calloc(1, sizeof(*entry));
-        entry->url = strndup(url, 1024*1024);
-        entry->connected = false;
-        entry->statically = false;
-        hashMap_put(receiver->requestedConnections.map, (void*)entry->url, entry);
-        receiver->requestedConnections.allConnected = false;
-    }
-    celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-
-    psa_zmq_connectToAllRequestedConnections(receiver);
-}
-
-void pubsub_zmqTopicReceiver_disconnectFrom(pubsub_zmq_topic_receiver_t *receiver, const char *url) {
-    L_DEBUG("[PSA ZMQ] TopicReceiver %s/%s disconnect from zmq url %s", receiver->scope == NULL ? "(null)" : receiver->scope, receiver->topic, url);
-
-    celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-    psa_zmq_requested_connection_entry_t *entry = hashMap_remove(receiver->requestedConnections.map, url);
-    if (entry != NULL && entry->connected) {
-        if (zmq_disconnect(receiver->zmqSock, url) == 0) {
-            entry->connected = false;
-        } else {
-            L_WARN("[PSA_ZMQ] Error disconnecting from zmq url %s. (%s)", url, strerror(errno));
-        }
-    }
-    if (entry != NULL) {
-        free(entry->url);
-        free(entry);
-    }
-    celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-}
-
-static void pubsub_zmqTopicReceiver_addSubscriber(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *bnd) {
-    pubsub_zmq_topic_receiver_t *receiver = handle;
-
-    long bndId = celix_bundle_getId(bnd);
-    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1);
-    const char *subScope = celix_properties_get(props, PUBSUB_SUBSCRIBER_SCOPE, NULL);
-    if (receiver->scope == NULL) {
-        if (subScope != NULL) {
-            return;
-        }
-    } else if (subScope != NULL) {
-        if (strncmp(subScope, receiver->scope, strlen(receiver->scope)) != 0) {
-            //not the same scope. ignore
-            return;
-        }
-    } else {
-        //receiver scope is not NULL, but subScope is NULL -> ignore
-        return;
-    }
-
-    celixThreadMutex_lock(&receiver->subscribers.mutex);
-    psa_zmq_subscriber_entry_t *entry = hashMap_get(receiver->subscribers.map, (void*)bndId);
-    if (entry != NULL) {
-        hashMap_put(entry->subscriberServices, (void*)svcId, svc);
-    } else {
-        //new create entry
-        entry = calloc(1, sizeof(*entry));
-        entry->subscriberServices = hashMap_create(NULL, NULL, NULL, NULL);
-        entry->initialized = false;
-        hashMap_put(entry->subscriberServices, (void*)svcId, svc);
-
-        int rc = receiver->serializer->createSerializerMap(receiver->serializer->handle, (celix_bundle_t*)bnd, &entry->msgTypes);
-
-        if (rc == 0) {
-            entry->metrics = hashMap_create(NULL, NULL, NULL, NULL);
-            hash_map_iterator_t iter = hashMapIterator_construct(entry->msgTypes);
-            while (hashMapIterator_hasNext(&iter)) {
-                pubsub_msg_serializer_t *msgSer = hashMapIterator_nextValue(&iter);
-                hash_map_t *origins = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-                hashMap_put(entry->metrics, (void*)(uintptr_t)msgSer->msgId, origins);
-            }
-        }
-
-        if (rc == 0) {
-            hashMap_put(receiver->subscribers.map, (void*)bndId, entry);
-        } else {
-            L_ERROR("[PSA_ZMQ] Cannot create msg serializer map for TopicReceiver %s/%s", receiver->scope == NULL ? "(null)" : receiver->scope, receiver->topic);
-            free(entry);
-        }
-    }
-    celixThreadMutex_unlock(&receiver->subscribers.mutex);
-}
-
-static void pubsub_zmqTopicReceiver_removeSubscriber(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *bnd) {
-    pubsub_zmq_topic_receiver_t *receiver = handle;
-
-    long bndId = celix_bundle_getId(bnd);
-    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1);
-
-    celixThreadMutex_lock(&receiver->subscribers.mutex);
-    psa_zmq_subscriber_entry_t *entry = hashMap_get(receiver->subscribers.map, (void*)bndId);
-    if (entry != NULL) {
-        hashMap_remove(entry->subscriberServices, (void*)svcId);
-    }
-    if (entry != NULL && hashMap_size(entry->subscriberServices) == 0) {
-        //remove entry
-        hashMap_remove(receiver->subscribers.map, (void*)bndId);
-        int rc = receiver->serializer->destroySerializerMap(receiver->serializer->handle, entry->msgTypes);
-        if (rc != 0) {
-            L_ERROR("[PSA_ZMQ] Cannot destroy msg serializers map for TopicReceiver %s/%s", receiver->scope == NULL ? "(null)" : receiver->scope, receiver->topic);
-        }
-        hash_map_iterator_t iter = hashMapIterator_construct(entry->metrics);
-        while (hashMapIterator_hasNext(&iter)) {
-            hash_map_t *origins = hashMapIterator_nextValue(&iter);
-            hashMap_destroy(origins, true, true);
-        }
-        hashMap_destroy(entry->metrics, false, false);
-        hashMap_destroy(entry->subscriberServices, false, false);
-        free(entry);
-    }
-    celixThreadMutex_unlock(&receiver->subscribers.mutex);
-}
-
-static inline void processMsgForSubscriberEntry(pubsub_zmq_topic_receiver_t *receiver, psa_zmq_subscriber_entry_t* entry, pubsub_protocol_message_t *message, struct timespec *receiveTime) {
-    //NOTE receiver->subscribers.mutex locked
-    pubsub_msg_serializer_t* msgSer = hashMap_get(entry->msgTypes, (void*)(uintptr_t)(message->header.msgId));
-    bool monitor = receiver->metricsEnabled;
-
-    //monitoring
-    struct timespec beginSer;
-    struct timespec endSer;
-    int updateReceiveCount = 0;
-    int updateSerError = 0;
-
-    if (msgSer!= NULL) {
-        void *deserializedMsg = NULL;
-        bool validVersion = psa_zmq_checkVersion(msgSer->msgVersion, message->header.msgMajorVersion, message->header.msgMinorVersion);
-        if (validVersion) {
-            if (monitor) {
-                clock_gettime(CLOCK_REALTIME, &beginSer);
-            }
-            struct iovec deSerializeBuffer;
-            deSerializeBuffer.iov_base = message->payload.payload;
-            deSerializeBuffer.iov_len  = message->payload.length;
-            celix_status_t status = msgSer->deserialize(msgSer->handle, &deSerializeBuffer, 0, &deserializedMsg);
-            if (monitor) {
-                clock_gettime(CLOCK_REALTIME, &endSer);
-            }
-            if (status == CELIX_SUCCESS) {
-                celix_properties_t *metadata = message->metadata.metadata;
-                bool release = true;
-                hash_map_iterator_t iter2 = hashMapIterator_construct(entry->subscriberServices);
-                while (hashMapIterator_hasNext(&iter2)) {
-                    pubsub_subscriber_t *svc = hashMapIterator_nextValue(&iter2);
-                    svc->receive(svc->handle, msgSer->msgName, msgSer->msgId, deserializedMsg, metadata, &release);
-                    if (!release) {
-                        //receive function has taken ownership deserialize again for new message
-                        status = msgSer->deserialize(msgSer->handle, &deSerializeBuffer, 0, &deserializedMsg);
-                        if (status != CELIX_SUCCESS) {
-                            L_WARN("[PSA_ZMQ_TR] Cannot deserialize msg type %s for scope/topic %s/%s", msgSer->msgName, receiver->scope == NULL ? "(null)" : receiver->scope, receiver->topic);
-                            break;
-                        }
-                        release = true;
-                    }
-                }
-                if (release) {
-                    msgSer->freeDeserializeMsg(msgSer->handle, deserializedMsg);
-                }
-                updateReceiveCount += 1;
-            } else {
-                updateSerError += 1;
-                L_WARN("[PSA_ZMQ_TR] Cannot deserialize msg type %s for scope/topic %s/%s", msgSer->msgName, receiver->scope == NULL ? "(null)" : receiver->scope, receiver->topic);
-            }
-        }
-    } else {
-        L_WARN("[PSA_ZMQ_TR] Cannot find serializer for type id 0x%X", message->header.msgId);
-    }
-}
-
-static inline void processMsg(pubsub_zmq_topic_receiver_t *receiver, pubsub_protocol_message_t *message, struct timespec *receiveTime) {
-    celixThreadMutex_lock(&receiver->subscribers.mutex);
-    hash_map_iterator_t iter = hashMapIterator_construct(receiver->subscribers.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_zmq_subscriber_entry_t *entry = hashMapIterator_nextValue(&iter);
-        if (entry != NULL) {
-            processMsgForSubscriberEntry(receiver, entry, message, receiveTime);
-        }
-    }
-    celixThreadMutex_unlock(&receiver->subscribers.mutex);
-}
-
-static void* psa_zmq_recvThread(void * data) {
-    pubsub_zmq_topic_receiver_t *receiver = data;
-
-    celixThreadMutex_lock(&receiver->recvThread.mutex);
-    bool running = receiver->recvThread.running;
-    celixThreadMutex_unlock(&receiver->recvThread.mutex);
-
-    celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-    bool allConnected = receiver->requestedConnections.allConnected;
-    celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-
-    celixThreadMutex_lock(&receiver->subscribers.mutex);
-    bool allInitialized = receiver->subscribers.allInitialized;
-    celixThreadMutex_unlock(&receiver->subscribers.mutex);
-
-    while (running) {
-        if (!allConnected) {
-            psa_zmq_connectToAllRequestedConnections(receiver);
-        }
-        if (!allInitialized) {
-            psa_zmq_initializeAllSubscribers(receiver);
-        }
-
-        zmsg_t *zmsg = zmsg_recv(receiver->zmqSock);
-        if (zmsg != NULL) {
-            if (zmsg_size(zmsg) < 2) {
-                L_WARN("[PSA_ZMQ_TR] Always expecting at least frames per zmsg (header + payload (+ metadata) (+ footer)), got %i frames", (int)zmsg_size(zmsg));
-            } else {
-                zframe_t *header = zmsg_pop(zmsg); // header
-                zframe_t *payload = NULL;
-                zframe_t *metadata = NULL;
-                zframe_t *footer = NULL;
-
-                pubsub_protocol_message_t message;
-                size_t footerSize = 0;
-                receiver->protocol->getFooterSize(receiver->protocol->handle, &footerSize);
-                receiver->protocol->decodeHeader(receiver->protocol->handle, zframe_data(header), zframe_size(header), &message);
-                if (message.header.payloadSize > 0) {
-                    payload = zmsg_pop(zmsg);
-                    receiver->protocol->decodePayload(receiver->protocol->handle, zframe_data(payload), zframe_size(payload), &message);
-                } else {
-                    message.payload.payload = NULL;
-                    message.payload.length = 0;
-                }
-                if (message.header.metadataSize > 0) {
-                    metadata = zmsg_pop(zmsg);
-                    receiver->protocol->decodeMetadata(receiver->protocol->handle, zframe_data(metadata), zframe_size(metadata), &message);
-                } else {
-                    message.metadata.metadata = NULL;
-                }
-                if (footerSize > 0) {
-                    footer = zmsg_pop(zmsg); // footer
-                    receiver->protocol->decodeFooter(receiver->protocol->handle, zframe_data(footer), zframe_size(footer), &message);
-                }
-                if (header != NULL && payload != NULL) {
-                    struct timespec receiveTime;
-                    clock_gettime(CLOCK_REALTIME, &receiveTime);
-                    processMsg(receiver, &message, &receiveTime);
-                }
-                celix_properties_destroy(message.metadata.metadata);
-                zframe_destroy(&header);
-                zframe_destroy(&payload);
-                zframe_destroy(&metadata);
-                zframe_destroy(&footer);
-            }
-            zmsg_destroy(&zmsg);
-        } else {
-            if (errno == EAGAIN) {
-                //nop
-            } else if (errno == EINTR) {
-                L_DEBUG("[PSA_ZMQ_TR] zmsg_recv interrupted");
-            } else {
-                L_WARN("[PSA_ZMQ_TR] Error receiving zmq message: %s", strerror(errno));
-            }
-        }
-
-        celixThreadMutex_lock(&receiver->recvThread.mutex);
-        running = receiver->recvThread.running;
-        celixThreadMutex_unlock(&receiver->recvThread.mutex);
-
-        celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-        allConnected = receiver->requestedConnections.allConnected;
-        celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-
-        celixThreadMutex_lock(&receiver->subscribers.mutex);
-        allInitialized = receiver->subscribers.allInitialized;
-        celixThreadMutex_unlock(&receiver->subscribers.mutex);
-    } // while
-
-    return NULL;
-}
-
-pubsub_admin_receiver_metrics_t* pubsub_zmqTopicReceiver_metrics(pubsub_zmq_topic_receiver_t *receiver) {
-    pubsub_admin_receiver_metrics_t *result = calloc(1, sizeof(*result));
-    snprintf(result->scope, PUBSUB_AMDIN_METRICS_NAME_MAX, "%s", receiver->scope == NULL ? PUBSUB_DEFAULT_ENDPOINT_SCOPE : receiver->scope);
-    snprintf(result->topic, PUBSUB_AMDIN_METRICS_NAME_MAX, "%s", receiver->topic);
-
-    int msgTypesCount = 0;
-    celixThreadMutex_lock(&receiver->subscribers.mutex);
-    hash_map_iterator_t iter = hashMapIterator_construct(receiver->subscribers.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_zmq_subscriber_entry_t *entry = hashMapIterator_nextValue(&iter);
-        hash_map_iterator_t iter2 = hashMapIterator_construct(entry->metrics);
-        while (hashMapIterator_hasNext(&iter2)) {
-            hashMapIterator_nextValue(&iter2);
-            msgTypesCount += 1;
-        }
-    }
-
-    result->nrOfMsgTypes = (unsigned long)msgTypesCount;
-    result->msgTypes = calloc(msgTypesCount, sizeof(*result->msgTypes));
-    int i = 0;
-    iter = hashMapIterator_construct(receiver->subscribers.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_zmq_subscriber_entry_t *entry = hashMapIterator_nextValue(&iter);
-        hash_map_iterator_t iter2 = hashMapIterator_construct(entry->metrics);
-        while (hashMapIterator_hasNext(&iter2)) {
-            hash_map_t *origins = hashMapIterator_nextValue(&iter2);
-            result->msgTypes[i].origins = calloc((size_t)hashMap_size(origins), sizeof(*(result->msgTypes[i].origins)));
-            result->msgTypes[i].nrOfOrigins = hashMap_size(origins);
-            int k = 0;
-            hash_map_iterator_t iter3 = hashMapIterator_construct(origins);
-            while (hashMapIterator_hasNext(&iter3)) {
-                psa_zmq_subscriber_metrics_entry_t *metrics = hashMapIterator_nextValue(&iter3);
-                result->msgTypes[i].typeId = metrics->msgTypeId;
-                pubsub_msg_serializer_t *msgSer = hashMap_get(entry->msgTypes, (void*)(uintptr_t)metrics->msgTypeId);
-                if (msgSer) {
-                    snprintf(result->msgTypes[i].typeFqn, PUBSUB_AMDIN_METRICS_NAME_MAX, "%s", msgSer->msgName);
-                    uuid_copy(result->msgTypes[i].origins[k].originUUID, metrics->origin);
-                    result->msgTypes[i].origins[k].nrOfMessagesReceived = metrics->nrOfMessagesReceived;
-                    result->msgTypes[i].origins[k].nrOfSerializationErrors = metrics->nrOfSerializationErrors;
-                    result->msgTypes[i].origins[k].averageDelayInSeconds = metrics->averageDelayInSeconds;
-                    result->msgTypes[i].origins[k].maxDelayInSeconds = metrics->maxDelayInSeconds;
-                    result->msgTypes[i].origins[k].minDelayInSeconds = metrics->minDelayInSeconds;
-                    result->msgTypes[i].origins[k].averageTimeBetweenMessagesInSeconds = metrics->averageTimeBetweenMessagesInSeconds;
-                    result->msgTypes[i].origins[k].averageSerializationTimeInSeconds = metrics->averageSerializationTimeInSeconds;
-                    result->msgTypes[i].origins[k].lastMessageReceived = metrics->lastMessageReceived;
-                    result->msgTypes[i].origins[k].nrOfMissingSeqNumbers = metrics->nrOfMissingSeqNumbers;
-
-                    k += 1;
-                } else {
-                    L_WARN("[PSA_ZMQ]: Error cannot find key 0x%X in msg map during metrics collection!\n", metrics->msgTypeId);
-                }
-            }
-            i +=1 ;
-        }
-    }
-
-    celixThreadMutex_unlock(&receiver->subscribers.mutex);
-
-    return result;
-}
-
-
-static void psa_zmq_connectToAllRequestedConnections(pubsub_zmq_topic_receiver_t *receiver) {
-    celixThreadMutex_lock(&receiver->requestedConnections.mutex);
-    if (!receiver->requestedConnections.allConnected) {
-        bool allConnected = true;
-        hash_map_iterator_t iter = hashMapIterator_construct(receiver->requestedConnections.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_zmq_requested_connection_entry_t *entry = hashMapIterator_nextValue(&iter);
-            if (!entry->connected) {
-                if (zmq_connect(receiver->zmqSock, entry->url) == 0) {
-                    entry->connected = true;
-                } else {
-                    L_WARN("[PSA_ZMQ] Error connecting to zmq url %s. (%s)", entry->url, strerror(errno));
-                    allConnected = false;
-                }
-            }
-        }
-        receiver->requestedConnections.allConnected = allConnected;
-    }
-    celixThreadMutex_unlock(&receiver->requestedConnections.mutex);
-}
-
-static void psa_zmq_initializeAllSubscribers(pubsub_zmq_topic_receiver_t *receiver) {
-    celixThreadMutex_lock(&receiver->subscribers.mutex);
-    if (!receiver->subscribers.allInitialized) {
-        bool allInitialized = true;
-        hash_map_iterator_t iter = hashMapIterator_construct(receiver->subscribers.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_zmq_subscriber_entry_t *entry = hashMapIterator_nextValue(&iter);
-            if (!entry->initialized) {
-                hash_map_iterator_t iter2 = hashMapIterator_construct(entry->subscriberServices);
-                while (hashMapIterator_hasNext(&iter2)) {
-                    pubsub_subscriber_t *svc = hashMapIterator_nextValue(&iter2);
-                    int rc = 0;
-                    if (svc != NULL && svc->init != NULL) {
-                        rc = svc->init(svc->handle);
-                    }
-                    if (rc == 0) {
-                        //note now only initialized on first subscriber entries added.
-                        entry->initialized = true;
-                    } else {
-                        L_WARN("Cannot initialize subscriber svc. Got rc %i", rc);
-                        allInitialized = false;
-                    }
-                }
-            }
-        }
-        receiver->subscribers.allInitialized = allInitialized;
-    }
-    celixThreadMutex_unlock(&receiver->subscribers.mutex);
-}
-
-static void psa_zmq_setupZmqContext(pubsub_zmq_topic_receiver_t *receiver, const celix_properties_t *topicProperties) {
-    //NOTE. ZMQ will abort when performing a sched_setscheduler without permission.
-    //As result permission has to be checked first.
-    //TODO update this to use cap_get_pid and cap-get_flag instead of check user is root (note adds dep to -lcap)
-    bool gotPermission = false;
-    if (getuid() == 0) {
-        gotPermission = true;
-    }
-
-
-    long prio = celix_properties_getAsLong(topicProperties, PUBSUB_ZMQ_THREAD_REALTIME_PRIO, -1L);
-    if (prio > 0 && prio < 100) {
-        if (gotPermission) {
-            zmq_ctx_set(receiver->zmqCtx, ZMQ_THREAD_PRIORITY, (int) prio);
-        } else {
-            L_INFO("Skipping configuration of thread prio to %i. No permission\n", (int)prio);
-        }
-    }
-
-    const char *sched = celix_properties_get(topicProperties, PUBSUB_ZMQ_THREAD_REALTIME_SCHED, NULL);
-    if (sched != NULL) {
-        int policy = ZMQ_THREAD_SCHED_POLICY_DFLT;
-        if (strncmp("SCHED_OTHER", sched, 16) == 0) {
-            policy = SCHED_OTHER;
-#if !defined(__APPLE__)
-        } else if (strncmp("SCHED_BATCH", sched, 16) == 0) {
-            policy = SCHED_BATCH;
-        } else if (strncmp("SCHED_IDLE", sched, 16) == 0) {
-            policy = SCHED_IDLE;
-#endif
-        } else if (strncmp("SCHED_FIFO", sched, 16) == 0) {
-            policy = SCHED_FIFO;
-        } else if (strncmp("SCHED_RR", sched, 16) == 0) {
-            policy = SCHED_RR;
-        }
-        if (gotPermission) {
-            zmq_ctx_set(receiver->zmqCtx, ZMQ_THREAD_SCHED_POLICY, policy);
-        } else {
-            L_INFO("Skipping configuration of thread scheduling to %s. No permission\n", sched);
-        }
-    }
-}
-
-static void psa_zmq_setupZmqSocket(pubsub_zmq_topic_receiver_t *receiver, const celix_properties_t *topicProperties) {
-    int timeout = PSA_ZMQ_RECV_TIMEOUT;
-    int res = zmq_setsockopt(receiver->zmqSock, ZMQ_RCVTIMEO, &timeout, sizeof(timeout));
-    if (res) {
-        L_ERROR("[PSA_ZMQ] Cannot set ZMQ socket option ZMQ_RCVTIMEO errno=%d", errno);
-    }
-
-#ifdef ZMQ_HWM
-    long hwmProp = celix_properties_getAsLong(topicProperties, PUBSUB_ZMQ_HWM, -1L);
-    if (hwmProp >= 0) {
-        unsigned long hwm = (unsigned long)hwmProp;
-        zmq_setsockopt(receiver->zmqSock, ZMQ_HWM, &hwm, sizeof(hwm));
-    }
-#endif
-
-#ifdef BUILD_WITH_ZMQ_SECURITY
-
-    zcert_apply (sub_cert, zmq_s);
-    zsock_set_curve_serverkey (zmq_s, pub_key); //apply key of publisher to socket of subscriber
-#endif
-    receiver->protocol->getSyncHeader(receiver->protocol->handle, receiver->sync);
-    zsock_set_subscribe(receiver->zmqSock, receiver->sync);
-
-#ifdef BUILD_WITH_ZMQ_SECURITY
-    ts->zmq_cert = sub_cert;
-    ts->zmq_pub_cert = pub_cert;
-#endif
-}
-
-static bool psa_zmq_checkVersion(version_pt msgVersion, uint16_t major, uint16_t minor) {
-    bool check=false;
-
-    if (major == 0 && minor == 0) {
-        //no check
-        return true;
-    }
-
-    int versionMajor;
-    int versionMinor;
-    if (msgVersion!=NULL) {
-        version_getMajor(msgVersion, &versionMajor);
-        version_getMinor(msgVersion, &versionMinor);
-        if (major==((unsigned char)versionMajor)) { /* Different major means incompatible */
-            check = (minor>=((unsigned char)versionMinor)); /* Compatible only if the provider has a minor equals or greater (means compatible update) */
-        }
-    }
-
-    return check;
-}
diff --git a/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_zmq_topic_receiver.h b/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_zmq_topic_receiver.h
deleted file mode 100644
index 26330f3..0000000
--- a/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_zmq_topic_receiver.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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_PUBSUB_ZMQ_TOPIC_RECEIVER_H
-#define CELIX_PUBSUB_ZMQ_TOPIC_RECEIVER_H
-
-#include <pubsub_admin_metrics.h>
-#include "celix_bundle_context.h"
-
-typedef struct pubsub_zmq_topic_receiver pubsub_zmq_topic_receiver_t;
-
-pubsub_zmq_topic_receiver_t* pubsub_zmqTopicReceiver_create(celix_bundle_context_t *ctx,
-                                                            celix_log_helper_t *logHelper,
-        const char *scope,
-        const char *topic,
-        const celix_properties_t *topicProperties,
-        long serializerSvcId,
-        pubsub_serializer_service_t *serializer,
-        long protocolSvcId,
-        pubsub_protocol_service_t *protocol);
-void pubsub_zmqTopicReceiver_destroy(pubsub_zmq_topic_receiver_t *receiver);
-
-const char* pubsub_zmqTopicReceiver_scope(pubsub_zmq_topic_receiver_t *receiver);
-const char* pubsub_zmqTopicReceiver_topic(pubsub_zmq_topic_receiver_t *receiver);
-
-long pubsub_zmqTopicReceiver_serializerSvcId(pubsub_zmq_topic_receiver_t *receiver);
-long pubsub_zmqTopicReceiver_protocolSvcId(pubsub_zmq_topic_receiver_t *receiver);
-void pubsub_zmqTopicReceiver_listConnections(pubsub_zmq_topic_receiver_t *receiver, celix_array_list_t *connectedUrls, celix_array_list_t *unconnectedUrls);
-
-void pubsub_zmqTopicReceiver_connectTo(pubsub_zmq_topic_receiver_t *receiver, const char *url);
-void pubsub_zmqTopicReceiver_disconnectFrom(pubsub_zmq_topic_receiver_t *receiver, const char *url);
-
-
-pubsub_admin_receiver_metrics_t* pubsub_zmqTopicReceiver_metrics(pubsub_zmq_topic_receiver_t *receiver);
-
-
-#endif //CELIX_PUBSUB_ZMQ_TOPIC_RECEIVER_H
diff --git a/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_zmq_topic_sender.c b/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_zmq_topic_sender.c
deleted file mode 100644
index 19c4660..0000000
--- a/bundles/pubsub/pubsub_admin_zmq/v1/src/pubsub_zmq_topic_sender.c
+++ /dev/null
@@ -1,748 +0,0 @@
-/*
- * 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 <pubsub_serializer.h>
-#include <pubsub_protocol.h>
-#include <stdlib.h>
-#include <memory.h>
-#include <pubsub_constants.h>
-#include <pubsub/publisher.h>
-#include <utils.h>
-#include <zconf.h>
-#include <arpa/inet.h>
-#include <czmq.h>
-#include <celix_log_helper.h>
-#include "pubsub_zmq_topic_sender.h"
-#include "pubsub_psa_zmq_constants.h"
-#include <uuid/uuid.h>
-#include "celix_constants.h"
-
-#define FIRST_SEND_DELAY_IN_SECONDS             2
-#define ZMQ_BIND_MAX_RETRY                      10
-
-#define L_DEBUG(...) \
-    celix_logHelper_log(sender->logHelper, CELIX_LOG_LEVEL_DEBUG, __VA_ARGS__)
-#define L_INFO(...) \
-    celix_logHelper_log(sender->logHelper, CELIX_LOG_LEVEL_INFO, __VA_ARGS__)
-#define L_WARN(...) \
-    celix_logHelper_log(sender->logHelper, CELIX_LOG_LEVEL_WARNING, __VA_ARGS__)
-#define L_ERROR(...) \
-    celix_logHelper_log(sender->logHelper, CELIX_LOG_LEVEL_ERROR, __VA_ARGS__)
-
-struct pubsub_zmq_topic_sender {
-    celix_bundle_context_t *ctx;
-    celix_log_helper_t *logHelper;
-    long serializerSvcId;
-    pubsub_serializer_service_t *serializer;
-    long protocolSvcId;
-    pubsub_protocol_service_t *protocol;
-    uuid_t fwUUID;
-    bool metricsEnabled;
-    bool zeroCopyEnabled;
-
-    char *scope;
-    char *topic;
-    char *url;
-    bool isStatic;
-
-    struct {
-        zsock_t *socket;
-        zcert_t *cert;
-    } zmq;
-
-    struct {
-        long svcId;
-        celix_service_factory_t factory;
-    } publisher;
-
-    struct {
-        celix_thread_mutex_t mutex;
-        hash_map_t *map;  //key = bndId, value = psa_zmq_bounded_service_entry_t
-    } boundedServices;
-};
-
-typedef struct psa_zmq_send_msg_entry {
-    uint32_t type; //msg type id (hash of fqn)
-    uint8_t major;
-    uint8_t minor;
-    unsigned char originUUID[16];
-    pubsub_msg_serializer_t *msgSer;
-    pubsub_protocol_service_t *protSer;
-    unsigned int seqNr;
-    void *headerBuffer;
-    size_t headerBufferSize;
-    void *metadataBuffer;
-    size_t metadataBufferSize;
-    void *footerBuffer;
-    size_t footerBufferSize;
-    bool dataLocked; // protected ZMQ functions and seqNr
-    struct {
-        celix_thread_mutex_t mutex; //protects entries in struct
-        unsigned long nrOfMessagesSend;
-        unsigned long nrOfMessagesSendFailed;
-        unsigned long nrOfSerializationErrors;
-        struct timespec lastMessageSend;
-        double averageTimeBetweenMessagesInSeconds;
-        double averageSerializationTimeInSeconds;
-    } metrics;
-} psa_zmq_send_msg_entry_t;
-
-typedef struct psa_zmq_bounded_service_entry {
-    pubsub_zmq_topic_sender_t *parent;
-    pubsub_publisher_t service;
-    long bndId;
-    hash_map_t *msgTypes; //key = msg type id, value = pubsub_msg_serializer_t
-    hash_map_t *msgTypeIds; //key = msg name, value = msg type id
-    hash_map_t *msgEntries; //key = msg type id, value = psa_zmq_send_msg_entry_t
-    int getCount;
-} psa_zmq_bounded_service_entry_t;
-
-typedef struct psa_zmq_zerocopy_free_entry {
-    pubsub_msg_serializer_t *msgSer;
-    struct iovec *serializedOutput;
-    size_t serializedOutputLen;
-} psa_zmq_zerocopy_free_entry;
-
-
-static void* psa_zmq_getPublisherService(void *handle, const celix_bundle_t *requestingBundle, const celix_properties_t *svcProperties);
-static void psa_zmq_ungetPublisherService(void *handle, const celix_bundle_t *requestingBundle, const celix_properties_t *svcProperties);
-static unsigned int rand_range(unsigned int min, unsigned int max);
-static void delay_first_send_for_late_joiners(pubsub_zmq_topic_sender_t *sender);
-
-static int psa_zmq_topicPublicationSend(void* handle, unsigned int msgTypeId, const void *msg, celix_properties_t *metadata);
-
-pubsub_zmq_topic_sender_t* pubsub_zmqTopicSender_create(
-        celix_bundle_context_t *ctx,
-        celix_log_helper_t *logHelper,
-        const char *scope,
-        const char *topic,
-        long serializerSvcId,
-        pubsub_serializer_service_t *ser,
-        long protocolSvcId,
-        pubsub_protocol_service_t *prot,
-        const char *bindIP,
-        const char *staticBindUrl,
-        unsigned int basePort,
-        unsigned int maxPort) {
-    pubsub_zmq_topic_sender_t *sender = calloc(1, sizeof(*sender));
-    sender->ctx = ctx;
-    sender->logHelper = logHelper;
-    sender->serializerSvcId = serializerSvcId;
-    sender->serializer = ser;
-    sender->protocolSvcId = protocolSvcId;
-    sender->protocol = prot;
-    const char* uuid = celix_bundleContext_getProperty(ctx, OSGI_FRAMEWORK_FRAMEWORK_UUID, NULL);
-    if (uuid != NULL) {
-        uuid_parse(uuid, sender->fwUUID);
-    }
-    sender->metricsEnabled = celix_bundleContext_getPropertyAsBool(ctx, PSA_ZMQ_METRICS_ENABLED, PSA_ZMQ_DEFAULT_METRICS_ENABLED);
-    sender->zeroCopyEnabled = celix_bundleContext_getPropertyAsBool(ctx, PSA_ZMQ_ZEROCOPY_ENABLED, PSA_ZMQ_DEFAULT_ZEROCOPY_ENABLED);
-
-    //setting up zmq socket for ZMQ TopicSender
-    {
-#ifdef BUILD_WITH_ZMQ_SECURITY
-        char *secure_topics = NULL;
-        bundleContext_getProperty(bundle_context, "SECURE_TOPICS", (const char **) &secure_topics);
-
-        if (secure_topics) {
-            array_list_pt secure_topics_list = pubsub_getTopicsFromString(secure_topics);
-
-            int i;
-            int secure_topics_size = arrayList_size(secure_topics_list);
-            for (i = 0; i < secure_topics_size; i++) {
-                char* top = arrayList_get(secure_topics_list, i);
-                if (strcmp(pubEP->topic, top) == 0) {
-                    printf("PSA_ZMQ_TP: Secure topic: '%s'\n", top);
-                    pubEP->is_secure = true;
-                }
-                free(top);
-                top = NULL;
-            }
-
-            arrayList_destroy(secure_topics_list);
-        }
-
-        zcert_t* pub_cert = NULL;
-        if (pubEP->is_secure) {
-            char* keys_bundle_dir = pubsub_getKeysBundleDir(bundle_context);
-            if (keys_bundle_dir == NULL) {
-                return CELIX_SERVICE_EXCEPTION;
-            }
-
-            const char* keys_file_path = NULL;
-            const char* keys_file_name = NULL;
-            bundleContext_getProperty(bundle_context, PROPERTY_KEYS_FILE_PATH, &keys_file_path);
-            bundleContext_getProperty(bundle_context, PROPERTY_KEYS_FILE_NAME, &keys_file_name);
-
-            char cert_path[MAX_CERT_PATH_LENGTH];
-
-            //certificate path ".cache/bundle{id}/version0.0/./META-INF/keys/publisher/private/pub_{topic}.key"
-            snprintf(cert_path, MAX_CERT_PATH_LENGTH, "%s/META-INF/keys/publisher/private/pub_%s.key.enc", keys_bundle_dir, pubEP->topic);
-            free(keys_bundle_dir);
-            printf("PSA_ZMQ_TP: Loading key '%s'\n", cert_path);
-
-            pub_cert = get_zcert_from_encoded_file((char *) keys_file_path, (char *) keys_file_name, cert_path);
-            if (pub_cert == NULL) {
-                printf("PSA_ZMQ_TP: Cannot load key '%s'\n", cert_path);
-                printf("PSA_ZMQ_TP: Topic '%s' NOT SECURED !\n", pubEP->topic);
-                pubEP->is_secure = false;
-            }
-        }
-#endif
-
-        zsock_t* zmqSocket = zsock_new(ZMQ_PUB);
-        if (zmqSocket==NULL) {
-#ifdef BUILD_WITH_ZMQ_SECURITY
-            if (pubEP->is_secure) {
-                zcert_destroy(&pub_cert);
-            }
-#endif
-            perror("Error for zmq_socket");
-        }
-#ifdef BUILD_WITH_ZMQ_SECURITY
-        if (pubEP->is_secure) {
-            zcert_apply (pub_cert, socket); // apply certificate to socket
-            zsock_set_curve_server (socket, true); // setup the publisher's socket to use the curve functions
-        }
-#endif
-
-        if (zmqSocket != NULL && staticBindUrl != NULL) {
-            int rv = zsock_bind (zmqSocket, "%s", staticBindUrl);
-            if (rv == -1) {
-                L_WARN("Error for zmq_bind using static bind url '%s'. %s", staticBindUrl, strerror(errno));
-            } else {
-                sender->url = strndup(staticBindUrl, 1024*1024);
-                sender->isStatic = true;
-            }
-        } else if (zmqSocket != NULL) {
-
-            int retry = 0;
-            while (sender->url == NULL && retry < ZMQ_BIND_MAX_RETRY) {
-                /* Randomized part due to same bundle publishing on different topics */
-                unsigned int port = rand_range(basePort, maxPort);
-
-                char *url = NULL;
-                asprintf(&url, "tcp://%s:%u", bindIP, port);
-
-                char *bindUrl = NULL;
-                asprintf(&bindUrl, "tcp://0.0.0.0:%u", port);
-
-
-                int rv = zsock_bind(zmqSocket, "%s", bindUrl);
-                if (rv == -1) {
-                    L_WARN("Error for zmq_bind using dynamic bind url '%s'. %s", bindUrl, strerror(errno));
-                    free(url);
-                } else {
-                    sender->url = url;
-                }
-                retry++;
-                free(bindUrl);
-            }
-        }
-
-        if (sender->url == NULL)  {
-            zsock_destroy(&zmqSocket);
-        } else {
-            sender->zmq.socket = zmqSocket;
-        }
-    }
-
-    if (sender->url != NULL) {
-        sender->scope = scope == NULL ? NULL : strndup(scope, 1024 * 1024);
-        sender->topic = strndup(topic, 1024 * 1024);
-
-        celixThreadMutex_create(&sender->boundedServices.mutex, NULL);
-        sender->boundedServices.map = hashMap_create(NULL, NULL, NULL, NULL);
-    }
-
-    //register publisher services using a service factory
-    if (sender->url != NULL) {
-        sender->publisher.factory.handle = sender;
-        sender->publisher.factory.getService = psa_zmq_getPublisherService;
-        sender->publisher.factory.ungetService = psa_zmq_ungetPublisherService;
-
-        celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, PUBSUB_PUBLISHER_TOPIC, sender->topic);
-        if (sender->scope != NULL) {
-            celix_properties_set(props, PUBSUB_PUBLISHER_SCOPE, sender->scope);
-        }
-
-        celix_service_registration_options_t opts = CELIX_EMPTY_SERVICE_REGISTRATION_OPTIONS;
-        opts.factory = &sender->publisher.factory;
-        opts.serviceName = PUBSUB_PUBLISHER_SERVICE_NAME;
-        opts.serviceVersion = PUBSUB_PUBLISHER_SERVICE_VERSION;
-        opts.properties = props;
-
-        sender->publisher.svcId = celix_bundleContext_registerServiceWithOptions(ctx, &opts);
-    }
-
-    if (sender->url == NULL) {
-        free(sender);
-        sender = NULL;
-    }
-
-    return sender;
-}
-
-static void pubsub_zmqTopicSender_destroyEntry(psa_zmq_send_msg_entry_t *msgEntry) {
-    celixThreadMutex_destroy(&msgEntry->metrics.mutex);
-    if(msgEntry->headerBuffer != NULL) {
-        free(msgEntry->headerBuffer);
-    }
-    if(msgEntry->metadataBuffer != NULL) {
-        free(msgEntry->metadataBuffer);
-    }
-    if(msgEntry->footerBuffer != NULL) {
-        free(msgEntry->footerBuffer);
-    }
-    free(msgEntry);
-}
-
-void pubsub_zmqTopicSender_destroy(pubsub_zmq_topic_sender_t *sender) {
-    if (sender != NULL) {
-        celix_bundleContext_unregisterService(sender->ctx, sender->publisher.svcId);
-
-        zsock_destroy(&sender->zmq.socket);
-
-        celixThreadMutex_lock(&sender->boundedServices.mutex);
-        hash_map_iterator_t iter = hashMapIterator_construct(sender->boundedServices.map);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_zmq_bounded_service_entry_t *entry = hashMapIterator_nextValue(&iter);
-            if (entry != NULL) {
-                sender->serializer->destroySerializerMap(sender->serializer->handle, entry->msgTypes);
-
-                hash_map_iterator_t iter2 = hashMapIterator_construct(entry->msgEntries);
-                while (hashMapIterator_hasNext(&iter2)) {
-                    psa_zmq_send_msg_entry_t *msgEntry = hashMapIterator_nextValue(&iter2);
-                    pubsub_zmqTopicSender_destroyEntry(msgEntry);
-                }
-                hashMap_destroy(entry->msgEntries, false, false);
-
-                free(entry);
-            }
-        }
-        hashMap_destroy(sender->boundedServices.map, false, false);
-        celixThreadMutex_unlock(&sender->boundedServices.mutex);
-
-        celixThreadMutex_destroy(&sender->boundedServices.mutex);
-
-        if (sender->scope != NULL) {
-            free(sender->scope);
-        }
-        free(sender->topic);
-        free(sender->url);
-        free(sender);
-    }
-}
-
-long pubsub_zmqTopicSender_serializerSvcId(pubsub_zmq_topic_sender_t *sender) {
-    return sender->serializerSvcId;
-}
-
-long pubsub_zmqTopicSender_protocolSvcId(pubsub_zmq_topic_sender_t *sender) {
-    return sender->protocolSvcId;
-}
-
-const char* pubsub_zmqTopicSender_scope(pubsub_zmq_topic_sender_t *sender) {
-    return sender->scope;
-}
-
-const char* pubsub_zmqTopicSender_topic(pubsub_zmq_topic_sender_t *sender) {
-    return sender->topic;
-}
-
-const char* pubsub_zmqTopicSender_url(pubsub_zmq_topic_sender_t *sender) {
-    return sender->url;
-}
-
-bool pubsub_zmqTopicSender_isStatic(pubsub_zmq_topic_sender_t *sender) {
-    return sender->isStatic;
-}
-
-void pubsub_zmqTopicSender_connectTo(pubsub_zmq_topic_sender_t *sender  __attribute__((unused)), const celix_properties_t *endpoint __attribute__((unused))) {
-    /*nop*/
-}
-
-void pubsub_zmqTopicSender_disconnectFrom(pubsub_zmq_topic_sender_t *sender __attribute__((unused)), const celix_properties_t *endpoint __attribute__((unused))) {
-    /*nop*/
-}
-
-static int psa_zmq_localMsgTypeIdForMsgType(void* handle, const char* msgType, unsigned int* msgTypeId) {
-    psa_zmq_bounded_service_entry_t *entry = (psa_zmq_bounded_service_entry_t *) handle;
-    *msgTypeId = (unsigned int)(uintptr_t) hashMap_get(entry->msgTypeIds, msgType);
-    return 0;
-}
-
-static void* psa_zmq_getPublisherService(void *handle, const celix_bundle_t *requestingBundle, const celix_properties_t *svcProperties __attribute__((unused))) {
-    pubsub_zmq_topic_sender_t *sender = handle;
-    long bndId = celix_bundle_getId(requestingBundle);
-
-    celixThreadMutex_lock(&sender->boundedServices.mutex);
-    psa_zmq_bounded_service_entry_t *entry = hashMap_get(sender->boundedServices.map, (void*)bndId);
-    if (entry != NULL) {
-        entry->getCount += 1;
-    } else {
-        entry = calloc(1, sizeof(*entry));
-        entry->getCount = 1;
-        entry->parent = sender;
-        entry->bndId = bndId;
-        entry->msgEntries = hashMap_create(NULL, NULL, NULL, NULL);
-        entry->msgTypeIds = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
-
-        int rc = sender->serializer->createSerializerMap(sender->serializer->handle, (celix_bundle_t*)requestingBundle, &entry->msgTypes);
-        if (rc == 0) {
-            hash_map_iterator_t iter = hashMapIterator_construct(entry->msgTypes);
-            while (hashMapIterator_hasNext(&iter)) {
-                hash_map_entry_t *hashMapEntry = hashMapIterator_nextEntry(&iter);
-                void *key = hashMapEntry_getKey(hashMapEntry);
-                psa_zmq_send_msg_entry_t *sendEntry = calloc(1, sizeof(*sendEntry));
-                sendEntry->msgSer = hashMapEntry_getValue(hashMapEntry);
-                sendEntry->protSer = sender->protocol;
-                sendEntry->type = (int32_t)sendEntry->msgSer->msgId;
-                int major;
-                int minor;
-                version_getMajor(sendEntry->msgSer->msgVersion, &major);
-                version_getMinor(sendEntry->msgSer->msgVersion, &minor);
-                sendEntry->major = (uint8_t)major;
-                sendEntry->minor = (uint8_t)minor;
-                uuid_copy(sendEntry->originUUID, sender->fwUUID);
-                celixThreadMutex_create(&sendEntry->metrics.mutex, NULL);
-                hashMap_put(entry->msgEntries, key, sendEntry);
-                hashMap_put(entry->msgTypeIds, strndup(sendEntry->msgSer->msgName, 1024), (void *)(uintptr_t) sendEntry->msgSer->msgId);
-            }
-            entry->service.handle = entry;
-            entry->service.localMsgTypeIdForMsgType = psa_zmq_localMsgTypeIdForMsgType;
-            entry->service.send = psa_zmq_topicPublicationSend;
-            hashMap_put(sender->boundedServices.map, (void*)bndId, entry);
-        } else {
-            L_ERROR("Error creating serializer map for ZMQ TopicSender %s/%s", sender->scope == NULL ? "(null)" : sender->scope, sender->topic);
-        }
-    }
-    celixThreadMutex_unlock(&sender->boundedServices.mutex);
-
-    return &entry->service;
-}
-
-static void psa_zmq_ungetPublisherService(void *handle, const celix_bundle_t *requestingBundle, const celix_properties_t *svcProperties __attribute__((unused))) {
-    pubsub_zmq_topic_sender_t *sender = handle;
-    long bndId = celix_bundle_getId(requestingBundle);
-
-    celixThreadMutex_lock(&sender->boundedServices.mutex);
-    psa_zmq_bounded_service_entry_t *entry = hashMap_get(sender->boundedServices.map, (void*)bndId);
-    if (entry != NULL) {
-        entry->getCount -= 1;
-    }
-    if (entry != NULL && entry->getCount == 0) {
-        //free entry
-        hashMap_remove(sender->boundedServices.map, (void*)bndId);
-        int rc = sender->serializer->destroySerializerMap(sender->serializer->handle, entry->msgTypes);
-        if (rc != 0) {
-            L_ERROR("Error destroying publisher service, serializer not available / cannot get msg serializer map\n");
-        }
-
-        hash_map_iterator_t iter = hashMapIterator_construct(entry->msgEntries);
-        while (hashMapIterator_hasNext(&iter)) {
-            psa_zmq_send_msg_entry_t *msgEntry = hashMapIterator_nextValue(&iter);
-            pubsub_zmqTopicSender_destroyEntry(msgEntry);
-        }
-        hashMap_destroy(entry->msgEntries, false, false);
-
-        hashMap_destroy(entry->msgTypeIds, true, false);
-        free(entry);
-    }
-    celixThreadMutex_unlock(&sender->boundedServices.mutex);
-}
-
-pubsub_admin_sender_metrics_t* pubsub_zmqTopicSender_metrics(pubsub_zmq_topic_sender_t *sender) {
-    pubsub_admin_sender_metrics_t *result = calloc(1, sizeof(*result));
-    snprintf(result->scope, PUBSUB_AMDIN_METRICS_NAME_MAX, "%s", sender->scope == NULL ? PUBSUB_DEFAULT_ENDPOINT_SCOPE : sender->scope);
-    snprintf(result->topic, PUBSUB_AMDIN_METRICS_NAME_MAX, "%s", sender->topic);
-    celixThreadMutex_lock(&sender->boundedServices.mutex);
-    size_t count = 0;
-    hash_map_iterator_t iter = hashMapIterator_construct(sender->boundedServices.map);
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_zmq_bounded_service_entry_t *entry = hashMapIterator_nextValue(&iter);
-        hash_map_iterator_t iter2 = hashMapIterator_construct(entry->msgEntries);
-        while (hashMapIterator_hasNext(&iter2)) {
-            hashMapIterator_nextValue(&iter2);
-            count += 1;
-        }
-    }
-
-    result->msgMetrics = calloc(count, sizeof(*result));
-
-    iter = hashMapIterator_construct(sender->boundedServices.map);
-    int i = 0;
-    while (hashMapIterator_hasNext(&iter)) {
-        psa_zmq_bounded_service_entry_t *entry = hashMapIterator_nextValue(&iter);
-        hash_map_iterator_t iter2 = hashMapIterator_construct(entry->msgEntries);
-        while (hashMapIterator_hasNext(&iter2)) {
-            psa_zmq_send_msg_entry_t *mEntry = hashMapIterator_nextValue(&iter2);
-            celixThreadMutex_lock(&mEntry->metrics.mutex);
-            result->msgMetrics[i].nrOfMessagesSend = mEntry->metrics.nrOfMessagesSend;
-            result->msgMetrics[i].nrOfMessagesSendFailed = mEntry->metrics.nrOfMessagesSendFailed;
-            result->msgMetrics[i].nrOfSerializationErrors = mEntry->metrics.nrOfSerializationErrors;
-            result->msgMetrics[i].averageSerializationTimeInSeconds = mEntry->metrics.averageSerializationTimeInSeconds;
-            result->msgMetrics[i].averageTimeBetweenMessagesInSeconds = mEntry->metrics.averageTimeBetweenMessagesInSeconds;
-            result->msgMetrics[i].lastMessageSend = mEntry->metrics.lastMessageSend;
-            result->msgMetrics[i].bndId = entry->bndId;
-            result->msgMetrics[i].typeId = mEntry->type;
-            snprintf(result->msgMetrics[i].typeFqn, PUBSUB_AMDIN_METRICS_NAME_MAX, "%s", mEntry->msgSer->msgName);
-            i += 1;
-            celixThreadMutex_unlock(&mEntry->metrics.mutex);
-        }
-    }
-
-    celixThreadMutex_unlock(&sender->boundedServices.mutex);
-    result->nrOfmsgMetrics = (int)count;
-    return result;
-}
-
-static void psa_zmq_freeMsg(void *msg, void *hint) {
-    psa_zmq_zerocopy_free_entry *entry = hint;
-    entry->msgSer->freeSerializeMsg(entry->msgSer->handle, entry->serializedOutput, entry->serializedOutputLen);
-    free(entry);
-}
-
-static void psa_zmq_unlockData(void *unused __attribute__((unused)), void *hint) {
-    psa_zmq_send_msg_entry_t *entry = hint;
-    __atomic_store_n(&entry->dataLocked, false, __ATOMIC_RELEASE);
-}
-
-static int psa_zmq_topicPublicationSend(void* handle, unsigned int msgTypeId, const void *inMsg, celix_properties_t *metadata) {
-    int status = CELIX_SUCCESS;
-    psa_zmq_bounded_service_entry_t *bound = handle;
-    pubsub_zmq_topic_sender_t *sender = bound->parent;
-    bool monitor = sender->metricsEnabled;
-
-    psa_zmq_send_msg_entry_t *entry = hashMap_get(bound->msgEntries, (void*)(uintptr_t)(msgTypeId));
-
-    //metrics updates
-    struct timespec sendTime = { 0, 0 };
-    struct timespec serializationStart;
-    struct timespec serializationEnd;
-    //int unknownMessageCountUpdate = 0;
-    int sendErrorUpdate = 0;
-    int serializationErrorUpdate = 0;
-    int sendCountUpdate = 0;
-
-    if (entry != NULL) {
-        delay_first_send_for_late_joiners(sender);
-
-
-
-        if (monitor) {
-            clock_gettime(CLOCK_REALTIME, &serializationStart);
-        }
-        size_t serializedOutputLen = 0;
-        struct iovec *serializedOutput = NULL;
-        status = entry->msgSer->serialize(entry->msgSer->handle, inMsg, &serializedOutput, &serializedOutputLen);
-
-        if (monitor) {
-            clock_gettime(CLOCK_REALTIME, &serializationEnd);
-        }
-
-        if (status == CELIX_SUCCESS /*ser ok*/) {
-            // Some ZMQ functions are not thread-safe, but this atomic compare exchange ensures one access at a time.
-            bool expected = false;
-            while(!__atomic_compare_exchange_n(&entry->dataLocked, &expected, true, false, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) {
-                expected = false;
-                usleep(500);
-            }
-
-            pubsub_protocol_message_t message;
-            message.payload.payload = serializedOutput->iov_base;
-            message.payload.length = serializedOutput->iov_len;
-
-            void *payloadData = NULL;
-            size_t payloadLength = 0;
-            entry->protSer->encodePayload(entry->protSer->handle, &message, &payloadData, &payloadLength);
-
-            if (metadata != NULL) {
-                message.metadata.metadata = metadata;
-                entry->protSer->encodeMetadata(entry->protSer->handle, &message, &entry->metadataBuffer, &entry->metadataBufferSize);
-            } else {
-                message.metadata.metadata = NULL;
-            }
-
-            entry->protSer->encodeFooter(entry->protSer->handle, &message, &entry->footerBuffer, &entry->footerBufferSize);
-
-            message.header.msgId = msgTypeId;
-            message.header.seqNr = entry->seqNr;
-            message.header.msgMajorVersion = 0;
-            message.header.msgMinorVersion = 0;
-            message.header.payloadSize = payloadLength;
-            message.header.metadataSize = entry->metadataBufferSize;
-            message.header.payloadPartSize = payloadLength;
-            message.header.payloadOffset = 0;
-            message.header.isLastSegment = 1;
-            message.header.convertEndianess = 0;
-
-            // increase seqNr
-            entry->seqNr++;
-
-            entry->protSer->encodeHeader(entry->protSer->handle, &message, &entry->headerBuffer, &entry->headerBufferSize);
-
-            errno = 0;
-            bool sendOk;
-
-            if (bound->parent->zeroCopyEnabled) {
-
-                zmq_msg_t msg1; // Header
-                zmq_msg_t msg2; // Payload
-                zmq_msg_t msg3; // Metadata
-                zmq_msg_t msg4; // Footer
-                void *socket = zsock_resolve(sender->zmq.socket);
-                psa_zmq_zerocopy_free_entry *freeMsgEntry = malloc(sizeof(psa_zmq_zerocopy_free_entry));
-                freeMsgEntry->msgSer = entry->msgSer;
-                freeMsgEntry->serializedOutput = serializedOutput;
-                freeMsgEntry->serializedOutputLen = serializedOutputLen;
-
-                zmq_msg_init_data(&msg1, entry->headerBuffer, entry->headerBufferSize, psa_zmq_unlockData, entry);
-                //send header
-                int rc = zmq_msg_send(&msg1, socket, ZMQ_SNDMORE);
-                if (rc == -1) {
-                    L_WARN("Error sending header msg. %s", strerror(errno));
-                    zmq_msg_close(&msg1);
-                }
-
-                //send Payload
-                if (rc > 0) {
-                    int flag = ((entry->metadataBufferSize > 0)  || (entry->footerBufferSize > 0)) ? ZMQ_SNDMORE : 0;
-                    zmq_msg_init_data(&msg2, payloadData, payloadLength, psa_zmq_freeMsg, freeMsgEntry);
-                    rc = zmq_msg_send(&msg2, socket, flag);
-                    if (rc == -1) {
-                        L_WARN("Error sending payload msg. %s", strerror(errno));
-                        zmq_msg_close(&msg2);
-                    }
-                }
-
-                //send MetaData
-                if (rc > 0 && entry->metadataBufferSize > 0) {
-                    int flag = (entry->footerBufferSize > 0 ) ? ZMQ_SNDMORE : 0;
-                    zmq_msg_init_data(&msg3, entry->metadataBuffer, entry->metadataBufferSize, NULL, NULL);
-                    rc = zmq_msg_send(&msg3, socket, flag);
-                    if (rc == -1) {
-                        L_WARN("Error sending metadata msg. %s", strerror(errno));
-                        zmq_msg_close(&msg3);
-                    }
-                }
-
-                //send Footer
-                if (rc > 0 && entry->footerBufferSize > 0) {
-                    zmq_msg_init_data(&msg4, entry->footerBuffer, entry->footerBufferSize, NULL, NULL);
-                    rc = zmq_msg_send(&msg4, socket, 0);
-                    if (rc == -1) {
-                        L_WARN("Error sending footer msg. %s", strerror(errno));
-                        zmq_msg_close(&msg4);
-                    }
-                }
-
-                sendOk = rc > 0;
-            } else {
-                //no zero copy
-                zmsg_t *msg = zmsg_new();
-                zmsg_addmem(msg, entry->headerBuffer, entry->headerBufferSize);
-                zmsg_addmem(msg, payloadData, payloadLength);
-                if (entry->metadataBufferSize > 0) {
-                    zmsg_addmem(msg, entry->metadataBuffer, entry->metadataBufferSize);
-                }
-                if (entry->footerBufferSize > 0) {
-                    zmsg_addmem(msg, entry->footerBuffer, entry->footerBufferSize);
-                }
-                int rc = zmsg_send(&msg, sender->zmq.socket);
-                sendOk = rc == 0;
-
-                if (!sendOk) {
-                    zmsg_destroy(&msg); //if send was not ok, no owner change -> destroy msg
-                }
-
-                // Note: serialized Payload is deleted by serializer
-                if (payloadData && (payloadData != message.payload.payload)) {
-                    free(payloadData);
-                }
-
-                __atomic_store_n(&entry->dataLocked, false, __ATOMIC_RELEASE);
-            }
-
-            if (message.metadata.metadata) {
-                celix_properties_destroy(message.metadata.metadata);
-            }
-            if (!bound->parent->zeroCopyEnabled && serializedOutput) {
-                entry->msgSer->freeSerializeMsg(entry->msgSer->handle, serializedOutput, serializedOutputLen);
-            }
-
-            if (sendOk) {
-                sendCountUpdate = 1;
-            } else {
-                sendErrorUpdate = 1;
-                L_WARN("[PSA_ZMQ_TS] Error sending zmg. %s", strerror(errno));
-            }
-        } else {
-            serializationErrorUpdate = 1;
-            L_WARN("[PSA_ZMQ_TS] Error serialize message of type %s for scope/topic %s/%s", entry->msgSer->msgName, sender->scope == NULL ? "(null)" : sender->scope, sender->topic);
-        }
-    } else {
-        //unknownMessageCountUpdate = 1;
-        status = CELIX_SERVICE_EXCEPTION;
-        L_WARN("[PSA_ZMQ_TS] Error cannot serialize message with msg type id %i for scope/topic %s/%s", msgTypeId, sender->scope == NULL ? "(null)" : sender->scope, sender->topic);
-    }
-
-
-    if (monitor && entry != NULL) {
-        celixThreadMutex_lock(&entry->metrics.mutex);
-
-        long n = entry->metrics.nrOfMessagesSend + entry->metrics.nrOfMessagesSendFailed;
-        double diff = celix_difftime(&serializationStart, &serializationEnd);
... 444 lines suppressed ...