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 ...