You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by rl...@apache.org on 2018/02/02 13:38:08 UTC

[1/4] celix git commit: Changing pubsub endpoint to store more information in etcd

Repository: celix
Updated Branches:
  refs/heads/develop a8b8410f1 -> 0a5ef69a6


Changing pubsub endpoint to store more information in etcd


Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/9094f554
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/9094f554
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/9094f554

Branch: refs/heads/develop
Commit: 9094f554217e963797910306359c89b145518724
Parents: d7307ff
Author: Roy Lenferink <rl...@apache.org>
Authored: Wed Jan 31 17:26:11 2018 +0100
Committer: Roy Lenferink <rl...@apache.org>
Committed: Fri Feb 2 11:48:19 2018 +0100

----------------------------------------------------------------------
 .../private/src/pubsub_admin_impl.c             | 103 ++++++++++++-------
 .../private/src/topic_publication.c             |  15 +--
 .../private/src/pubsub_admin_impl.c             |  99 +++++++++++-------
 .../private/src/topic_publication.c             |  13 +--
 .../public/include/pubsub_endpoint.h            |  19 ++--
 .../pubsub_common/public/src/pubsub_endpoint.c  |  88 ++++++++++------
 .../pubsub_discovery/private/src/etcd_watcher.c |  56 +++++++++-
 .../pubsub_discovery/private/src/etcd_writer.c  |  44 ++++++--
 .../private/src/pubsub_discovery_impl.c         |  19 ++--
 .../private/src/pubsub_topology_manager.c       |  40 ++++---
 utils/private/src/properties.c                  |   5 +
 utils/public/include/properties.h               |   2 +
 12 files changed, 343 insertions(+), 160 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_admin_udp_mc/private/src/pubsub_admin_impl.c
----------------------------------------------------------------------
diff --git a/pubsub/pubsub_admin_udp_mc/private/src/pubsub_admin_impl.c b/pubsub/pubsub_admin_udp_mc/private/src/pubsub_admin_impl.c
index 1fbdb08..8124950 100644
--- a/pubsub/pubsub_admin_udp_mc/private/src/pubsub_admin_impl.c
+++ b/pubsub/pubsub_admin_udp_mc/private/src/pubsub_admin_impl.c
@@ -311,7 +311,9 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu
 			status = pubsub_topicSubscriptionCreate(admin->bundle_context, admin->ifIpAddress, PUBSUB_SUBSCRIBER_SCOPE_DEFAULT, PUBSUB_ANY_SUB_TOPIC, best_serializer, &any_sub);
 		}
 		else{
-			printf("PSA_UDP_MC: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",subEP->topic);
+			printf("PSA_UDP_MC: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",
+				   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
 			celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 			arrayList_add(admin->noSerializerSubscriptions,subEP);
 			celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
@@ -330,8 +332,8 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu
 				if(topic_publishers!=NULL){
 					for(i=0;i<arrayList_size(topic_publishers);i++){
 						pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(topic_publishers,i);
-						if(pubEP->endpoint !=NULL){
-							status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint);
+						if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
+							status += pubsub_topicSubscriptionConnectPublisher(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 						}
 					}
 					arrayList_destroy(topic_publishers);
@@ -348,8 +350,8 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu
 				if(ext_pub_list!=NULL){
 					for(i=0;i<arrayList_size(ext_pub_list);i++){
 						pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
-						if(pubEP->endpoint !=NULL){
-							status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint);
+						if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
+							status += pubsub_topicSubscriptionConnectPublisher(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 						}
 					}
 				}
@@ -379,9 +381,13 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu
 celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
 	celix_status_t status = CELIX_SUCCESS;
 
-	printf("PSA_UDP_MC: Received subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",subEP->frameworkUUID,subEP->serviceID,subEP->scope,subEP->topic);
+	printf("PSA_UDP_MC: Received subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",
+		   properties_get(subEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+		   subEP->serviceID,
+		   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+		   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
-	if(strcmp(subEP->topic,PUBSUB_ANY_SUB_TOPIC)==0){
+	if(strcmp(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),PUBSUB_ANY_SUB_TOPIC)==0){
 		return pubsubAdmin_addAnySubscription(admin,subEP);
 	}
 
@@ -391,7 +397,7 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
 	celixThreadMutex_lock(&admin->localPublicationsLock);
 	celixThreadMutex_lock(&admin->externalPublicationsLock);
 
-	char* scope_topic = createScopeTopicKey(subEP->scope,subEP->topic);
+	char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
 	service_factory_pt factory = (service_factory_pt)hashMap_get(admin->localPublications,scope_topic);
 	array_list_pt ext_pub_list = (array_list_pt)hashMap_get(admin->externalPublications,scope_topic);
@@ -406,10 +412,12 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
 		if(subscription == NULL) {
 			pubsub_serializer_service_t *best_serializer = NULL;
 			if( (status=pubsubAdmin_getBestSerializer(admin, subEP, &best_serializer)) == CELIX_SUCCESS){
-				status += pubsub_topicSubscriptionCreate(admin->bundle_context,admin->ifIpAddress, subEP->scope, subEP->topic, best_serializer, &subscription);
+				status += pubsub_topicSubscriptionCreate(admin->bundle_context,admin->ifIpAddress, (char*) properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC), best_serializer, &subscription);
 			}
 			else{
-				printf("PSA_UDP_MC: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",subEP->topic);
+				printf("PSA_UDP_MC: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",
+					   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
 				celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 				arrayList_add(admin->noSerializerSubscriptions,subEP);
 				celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
@@ -425,8 +433,8 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
 					if(topic_publishers!=NULL){
 						for(i=0;i<arrayList_size(topic_publishers);i++){
 							pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(topic_publishers,i);
-							if(pubEP->endpoint !=NULL){
-								status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint);
+							if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
+								status += pubsub_topicSubscriptionConnectPublisher(subscription, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 							}
 						}
 						arrayList_destroy(topic_publishers);
@@ -438,8 +446,8 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
 				if(ext_pub_list!=NULL){
 					for(i=0;i<arrayList_size(ext_pub_list);i++){
 						pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
-						if(pubEP->endpoint !=NULL){
-							status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint);
+						if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
+							status += pubsub_topicSubscriptionConnectPublisher(subscription, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 						}
 					}
 				}
@@ -476,9 +484,13 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
 celix_status_t pubsubAdmin_removeSubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
 	celix_status_t status = CELIX_SUCCESS;
 
-	printf("PSA_UDP_MC: Removing subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",subEP->frameworkUUID,subEP->serviceID,subEP->scope, subEP->topic);
+	printf("PSA_UDP_MC: Removing subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",
+		   properties_get(subEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+		   subEP->serviceID,
+		   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+		   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
-	char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic);
+	char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
 	celixThreadMutex_lock(&admin->subscriptionsLock);
 	topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic);
@@ -510,7 +522,11 @@ celix_status_t pubsubAdmin_removeSubscription(pubsub_admin_pt admin,pubsub_endpo
 celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin,pubsub_endpoint_pt pubEP){
 	celix_status_t status = CELIX_SUCCESS;
 
-	printf("PSA_UDP_MC: Received publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",pubEP->frameworkUUID,pubEP->serviceID,pubEP->scope, pubEP->topic);
+	printf("PSA_UDP_MC: Received publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",
+		   properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+		   pubEP->serviceID,
+		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
 	const char* fwUUID = NULL;
 
@@ -519,9 +535,9 @@ celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin,pubsub_endpoint_
 		printf("PSA_UDP_MC: Cannot retrieve fwUUID.\n");
 		return CELIX_INVALID_BUNDLE_CONTEXT;
 	}
-	char* scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic);
+	char* scope_topic = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
-	if ((strcmp(pubEP->frameworkUUID, fwUUID) == 0) && (pubEP->endpoint == NULL)) {
+	if ((strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID), fwUUID) == 0) && (properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) == NULL)) {
 
 		celixThreadMutex_lock(&admin->localPublicationsLock);
 
@@ -534,7 +550,9 @@ celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin,pubsub_endpoint_
 				status = pubsub_topicPublicationCreate(admin->sendSocket, pubEP, best_serializer, admin->mcIpAddress, &pub);
 			}
 			else{
-				printf("PSA_UDP_MC: Cannot find a serializer for publishing topic %s. Adding it to pending list.\n", pubEP->topic);
+				printf("PSA_UDP_MC: Cannot find a serializer for publishing topic %s. Adding it to pending list.\n",
+					   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+
 				celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 				arrayList_add(admin->noSerializerPublications,pubEP);
 				celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
@@ -547,7 +565,10 @@ celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin,pubsub_endpoint_
 					connectTopicPubSubToSerializer(admin, best_serializer, pub, true);
 				}
 			} else {
-				printf("PSA_UDP_MC: Cannot create a topicPublication for scope=%s, topic=%s (bundle %ld).\n", pubEP->scope, pubEP->topic, pubEP->serviceID);
+				printf("PSA_UDP_MC: Cannot create a topicPublication for scope=%s, topic=%s (bundle %ld).\n",
+					   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+					   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+					   pubEP->serviceID);
 			}
 		} else {
 			//just add the new EP to the list
@@ -595,14 +616,14 @@ celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin,pubsub_endpoint_
 	celixThreadMutex_lock(&admin->subscriptionsLock);
 
 	topic_subscription_pt sub = (topic_subscription_pt) hashMap_get(admin->subscriptions, scope_topic);
-	if (sub != NULL && pubEP->endpoint != NULL) {
-		pubsub_topicSubscriptionAddConnectPublisherToPendingList(sub, pubEP->endpoint);
+	if (sub != NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) != NULL) {
+		pubsub_topicSubscriptionAddConnectPublisherToPendingList(sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 	}
 
 	/* And check also for ANY subscription */
 	topic_subscription_pt any_sub = (topic_subscription_pt) hashMap_get(admin->subscriptions, PUBSUB_ANY_SUB_TOPIC);
-	if (any_sub != NULL && pubEP->endpoint != NULL) {
-		pubsub_topicSubscriptionAddConnectPublisherToPendingList(any_sub, pubEP->endpoint);
+	if (any_sub != NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) != NULL) {
+		pubsub_topicSubscriptionAddConnectPublisherToPendingList(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 	}
 
 	free(scope_topic);
@@ -617,7 +638,11 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi
 	celix_status_t status = CELIX_SUCCESS;
 	int count = 0;
 
-	printf("PSA_UDP_MC: Removing publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",pubEP->frameworkUUID,pubEP->serviceID,pubEP->scope, pubEP->topic);
+	printf("PSA_UDP_MC: Removing publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",
+		   properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+		   pubEP->serviceID,
+		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
 	const char* fwUUID = NULL;
 
@@ -626,9 +651,9 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi
 		printf("PSA_UDP_MC: Cannot retrieve fwUUID.\n");
 		return CELIX_INVALID_BUNDLE_CONTEXT;
 	}
-	char *scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic);
+	char *scope_topic = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
-	if(strcmp(pubEP->frameworkUUID,fwUUID)==0){
+	if(strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),fwUUID)==0){
 
 		celixThreadMutex_lock(&admin->localPublicationsLock);
 		service_factory_pt factory = (service_factory_pt)hashMap_get(admin->localPublications,scope_topic);
@@ -665,7 +690,7 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi
 			// Check if there are more publishers on the same endpoint (happens when 1 celix-instance with multiple bundles publish in same topic)
 			for(i=0; i<arrayList_size(ext_pub_list);i++) {
 				pubsub_endpoint_pt p  = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
-				if (strcmp(pubEP->endpoint,p->endpoint) == 0) {
+				if (strcmp(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL),properties_get(p->endpoint_props, PUBSUB_ENDPOINT_URL)) == 0) {
 					count++;
 				}
 			}
@@ -687,14 +712,14 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi
 	celixThreadMutex_lock(&admin->subscriptionsLock);
 
 	topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic);
-	if(sub!=NULL && pubEP->endpoint!=NULL && count == 0){
-		pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub,pubEP->endpoint);
+	if(sub!=NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL && count == 0){
+		pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 	}
 
 	/* And check also for ANY subscription */
 	topic_subscription_pt any_sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,PUBSUB_ANY_SUB_TOPIC);
-	if(any_sub!=NULL && pubEP->endpoint!=NULL && count == 0){
-		pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(any_sub,pubEP->endpoint);
+	if(any_sub!=NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL && count == 0){
+		pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 	}
 
 	free(scope_topic);
@@ -793,7 +818,7 @@ static celix_status_t pubsubAdmin_getIpAddress(const char* interface, char** ip)
 static celix_status_t pubsubAdmin_addSubscriptionToPendingList(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
 	celix_status_t status = CELIX_SUCCESS;
 
-	char* scope_topic =createScopeTopicKey(subEP->scope, subEP->topic);
+	char* scope_topic =createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 	array_list_pt pendingListPerTopic = hashMap_get(admin->pendingSubscriptions,scope_topic);
 	if(pendingListPerTopic==NULL){
 		arrayList_create(&pendingListPerTopic);
@@ -888,9 +913,8 @@ celix_status_t pubsubAdmin_serializerRemoved(void * handle, service_reference_pt
 				/* Remove the publication */
 				pubsubAdmin_removePublication(admin, pubEP);
 				/* Reset the endpoint field, so that will be recreated from scratch when a new serializer will be found */
-				if(pubEP->endpoint!=NULL){
-					free(pubEP->endpoint);
-					pubEP->endpoint = NULL;
+				if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL){
+					properties_unset(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL);
 				}
 				/* Add the orphan endpoint to the noSerializer pending list */
 				celixThreadMutex_lock(&admin->noSerializerPendingsLock);
@@ -940,9 +964,8 @@ celix_status_t pubsubAdmin_serializerRemoved(void * handle, service_reference_pt
 				/* Remove the subscription */
 				pubsubAdmin_removeSubscription(admin, subEP);
 				/* Reset the endpoint field, so that will be recreated from scratch when a new serializer will be found */
-				if(subEP->endpoint!=NULL){
-					free(subEP->endpoint);
-					subEP->endpoint = NULL;
+				if(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL){
+					properties_unset(subEP->endpoint_props, PUBSUB_ENDPOINT_URL);
 				}
 				/* Add the orphan endpoint to the noSerializer pending list */
 				celixThreadMutex_lock(&admin->noSerializerPendingsLock);

http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_admin_udp_mc/private/src/topic_publication.c
----------------------------------------------------------------------
diff --git a/pubsub/pubsub_admin_udp_mc/private/src/topic_publication.c b/pubsub/pubsub_admin_udp_mc/private/src/topic_publication.c
index e43ec29..52abeda 100644
--- a/pubsub/pubsub_admin_udp_mc/private/src/topic_publication.c
+++ b/pubsub/pubsub_admin_udp_mc/private/src/topic_publication.c
@@ -174,14 +174,17 @@ celix_status_t pubsub_topicPublicationStart(bundle_context_pt bundle_context,top
 		factory->ungetService = pubsub_topicPublicationUngetService;
 
 		properties_pt props = properties_create();
-		properties_set(props,PUBSUB_PUBLISHER_SCOPE,pubEP->scope);
-		properties_set(props,PUBSUB_PUBLISHER_TOPIC,pubEP->topic);
+		properties_set(props,PUBSUB_PUBLISHER_SCOPE,properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE));
+		properties_set(props,PUBSUB_PUBLISHER_TOPIC,properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
 		status = bundleContext_registerServiceFactory(bundle_context,PUBSUB_PUBLISHER_SERVICE_NAME,factory,props,&(pub->svcFactoryReg));
 
 		if(status != CELIX_SUCCESS){
 			properties_destroy(props);
-			printf("PSA_UDP_MC_PSA_UDP_MC_TP: Cannot register ServiceFactory for topic %s, topic %s (bundle %ld).\n",pubEP->scope, pubEP->topic,pubEP->serviceID);
+			printf("PSA_UDP_MC_PSA_UDP_MC_TP: Cannot register ServiceFactory for topic %s, topic %s (bundle %ld).\n",
+				   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+				   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+				   pubEP->serviceID);
 		}
 		else{
 			*svcFactory = factory;
@@ -202,7 +205,7 @@ celix_status_t pubsub_topicPublicationStop(topic_publication_pt pub){
 celix_status_t pubsub_topicPublicationAddPublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep){
 
 	celixThreadMutex_lock(&(pub->tp_lock));
-	ep->endpoint = strdup(pub->endpoint);
+	pubsubEndpoint_setField(ep, PUBSUB_ENDPOINT_URL, pub->endpoint);
 	arrayList_add(pub->pub_ep_list,ep);
 	celixThreadMutex_unlock(&(pub->tp_lock));
 
@@ -393,8 +396,8 @@ static publish_bundle_bound_service_pt pubsub_createPublishBundleBoundService(to
 		}
 
 		pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(bound->parent->pub_ep_list,0);
-		bound->scope=strdup(pubEP->scope);
-		bound->topic=strdup(pubEP->topic);
+		bound->scope=strdup(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE));
+		bound->topic=strdup(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 		bound->largeUdpHandle = largeUdp_create(1);
 
 		bound->service.handle = bound;

http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_admin_zmq/private/src/pubsub_admin_impl.c
----------------------------------------------------------------------
diff --git a/pubsub/pubsub_admin_zmq/private/src/pubsub_admin_impl.c b/pubsub/pubsub_admin_zmq/private/src/pubsub_admin_impl.c
index 29ead0c..9a486dd 100644
--- a/pubsub/pubsub_admin_zmq/private/src/pubsub_admin_impl.c
+++ b/pubsub/pubsub_admin_zmq/private/src/pubsub_admin_impl.c
@@ -312,7 +312,8 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu
 			status = pubsub_topicSubscriptionCreate(admin->bundle_context, PUBSUB_SUBSCRIBER_SCOPE_DEFAULT, PUBSUB_ANY_SUB_TOPIC, best_serializer, &any_sub);
 		}
 		else{
-			printf("PSA_ZMQ: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",subEP->topic);
+			printf("PSA_ZMQ: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",
+				   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 			celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 			arrayList_add(admin->noSerializerSubscriptions,subEP);
 			celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
@@ -331,8 +332,8 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu
 				if(topic_publishers!=NULL){
 					for(i=0;i<arrayList_size(topic_publishers);i++){
 						pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(topic_publishers,i);
-						if(pubEP->endpoint !=NULL){
-							status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint);
+						if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
+							status += pubsub_topicSubscriptionConnectPublisher(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 						}
 					}
 					arrayList_destroy(topic_publishers);
@@ -349,8 +350,8 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu
 				if(ext_pub_list!=NULL){
 					for(i=0;i<arrayList_size(ext_pub_list);i++){
 						pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
-						if(pubEP->endpoint !=NULL){
-							status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint);
+						if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
+							status += pubsub_topicSubscriptionConnectPublisher(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 						}
 					}
 				}
@@ -380,9 +381,13 @@ static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsu
 celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
 	celix_status_t status = CELIX_SUCCESS;
 
-	printf("PSA_ZMQ: Received subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",subEP->frameworkUUID,subEP->serviceID,subEP->scope, subEP->topic);
+	printf("PSA_ZMQ: Received subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",
+		   properties_get(subEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+		   subEP->serviceID,
+		   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+		   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
-	if(strcmp(subEP->topic,PUBSUB_ANY_SUB_TOPIC)==0){
+	if(strcmp(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),PUBSUB_ANY_SUB_TOPIC)==0){
 		return pubsubAdmin_addAnySubscription(admin,subEP);
 	}
 
@@ -392,7 +397,7 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
 	celixThreadMutex_lock(&admin->localPublicationsLock);
 	celixThreadMutex_lock(&admin->externalPublicationsLock);
 
-	char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic);
+	char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
 	service_factory_pt factory = (service_factory_pt)hashMap_get(admin->localPublications,scope_topic);
 	array_list_pt ext_pub_list = (array_list_pt)hashMap_get(admin->externalPublications,scope_topic);
@@ -407,10 +412,11 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
 		if(subscription == NULL) {
 			pubsub_serializer_service_t *best_serializer = NULL;
 			if( (status=pubsubAdmin_getBestSerializer(admin, subEP, &best_serializer)) == CELIX_SUCCESS){
-				status += pubsub_topicSubscriptionCreate(admin->bundle_context,subEP->scope, subEP->topic, best_serializer, &subscription);
+				status += pubsub_topicSubscriptionCreate(admin->bundle_context, (char*) properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC), best_serializer, &subscription);
 			}
 			else{
-				printf("PSA_ZMQ: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",subEP->topic);
+				printf("PSA_ZMQ: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",
+					   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 				celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 				arrayList_add(admin->noSerializerSubscriptions,subEP);
 				celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
@@ -426,8 +432,8 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
 					if(topic_publishers!=NULL){
 						for(i=0;i<arrayList_size(topic_publishers);i++){
 							pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(topic_publishers,i);
-							if(pubEP->endpoint !=NULL){
-								status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint);
+							if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
+								status += pubsub_topicSubscriptionConnectPublisher(subscription,(char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 							}
 						}
 						arrayList_destroy(topic_publishers);
@@ -439,8 +445,8 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
 				if(ext_pub_list!=NULL){
 					for(i=0;i<arrayList_size(ext_pub_list);i++){
 						pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
-						if(pubEP->endpoint !=NULL){
-							status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint);
+						if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
+							status += pubsub_topicSubscriptionConnectPublisher(subscription,(char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 						}
 					}
 				}
@@ -477,9 +483,12 @@ celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint
 celix_status_t pubsubAdmin_removeSubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
 	celix_status_t status = CELIX_SUCCESS;
 
-	printf("PSA_ZMQ: Removing subscription [FWUUID=%s bundleID=%ld topic=%s]\n",subEP->frameworkUUID,subEP->serviceID,subEP->topic);
+	printf("PSA_ZMQ: Removing subscription [FWUUID=%s bundleID=%ld topic=%s]\n",
+		   properties_get(subEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+		   subEP->serviceID,
+		   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
-	char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic);
+	char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
 	celixThreadMutex_lock(&admin->subscriptionsLock);
 	topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic);
@@ -511,7 +520,11 @@ celix_status_t pubsubAdmin_removeSubscription(pubsub_admin_pt admin,pubsub_endpo
 celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin, pubsub_endpoint_pt pubEP) {
 	celix_status_t status = CELIX_SUCCESS;
 
-	printf("PSA_ZMQ: Received publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n", pubEP->frameworkUUID, pubEP->serviceID, pubEP->scope, pubEP->topic);
+	printf("PSA_ZMQ: Received publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",
+		   properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+		   pubEP->serviceID,
+		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
 	const char* fwUUID = NULL;
 
@@ -521,9 +534,10 @@ celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin, pubsub_endpoint
 		return CELIX_INVALID_BUNDLE_CONTEXT;
 	}
 
-	char *scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic);
+	char *scope_topic = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
-	if ((strcmp(pubEP->frameworkUUID, fwUUID) == 0) && (pubEP->endpoint == NULL)) {
+	if ((strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID), fwUUID) == 0) &&
+			(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) == NULL)) {
 
 		celixThreadMutex_lock(&admin->localPublicationsLock);
 
@@ -536,7 +550,8 @@ celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin, pubsub_endpoint
 				status = pubsub_topicPublicationCreate(admin->bundle_context, pubEP, best_serializer, admin->ipAddress, admin->basePort, admin->maxPort, &pub);
 			}
 			else{
-				printf("PSA_ZMQ: Cannot find a serializer for publishing topic %s. Adding it to pending list.\n", pubEP->topic);
+				printf("PSA_ZMQ: Cannot find a serializer for publishing topic %s. Adding it to pending list.\n",
+					   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 				celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 				arrayList_add(admin->noSerializerPublications,pubEP);
 				celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
@@ -549,7 +564,10 @@ celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin, pubsub_endpoint
 					connectTopicPubSubToSerializer(admin, best_serializer, pub, true);
 				}
 			} else {
-				printf("PSA_ZMQ: Cannot create a topicPublication for scope=%s, topic=%s (bundle %ld).\n", pubEP->scope, pubEP->topic, pubEP->serviceID);
+				printf("PSA_ZMQ: Cannot create a topicPublication for scope=%s, topic=%s (bundle %ld).\n",
+					   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+					   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+					   pubEP->serviceID);
 			}
 		} else {
 			//just add the new EP to the list
@@ -597,14 +615,14 @@ celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin, pubsub_endpoint
 	celixThreadMutex_lock(&admin->subscriptionsLock);
 
 	topic_subscription_pt sub = (topic_subscription_pt) hashMap_get(admin->subscriptions, scope_topic);
-	if (sub != NULL && pubEP->endpoint != NULL) {
-		pubsub_topicSubscriptionAddConnectPublisherToPendingList(sub, pubEP->endpoint);
+	if (sub != NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) != NULL) {
+		pubsub_topicSubscriptionAddConnectPublisherToPendingList(sub, (char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 	}
 
 	/* And check also for ANY subscription */
 	topic_subscription_pt any_sub = (topic_subscription_pt) hashMap_get(admin->subscriptions, PUBSUB_ANY_SUB_TOPIC);
-	if (any_sub != NULL && pubEP->endpoint != NULL) {
-		pubsub_topicSubscriptionAddConnectPublisherToPendingList(any_sub, pubEP->endpoint);
+	if (any_sub != NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) != NULL) {
+		pubsub_topicSubscriptionAddConnectPublisherToPendingList(any_sub, (char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 	}
 
 	free(scope_topic);
@@ -619,7 +637,10 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi
 	celix_status_t status = CELIX_SUCCESS;
 	int count = 0;
 
-	printf("PSA_ZMQ: Removing publication [FWUUID=%s bundleID=%ld topic=%s]\n",pubEP->frameworkUUID,pubEP->serviceID,pubEP->topic);
+	printf("PSA_ZMQ: Removing publication [FWUUID=%s bundleID=%ld topic=%s]\n",
+		   properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+		   pubEP->serviceID,
+		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
 	const char* fwUUID = NULL;
 
@@ -628,9 +649,9 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi
 		printf("PSA_ZMQ: Cannot retrieve fwUUID.\n");
 		return CELIX_INVALID_BUNDLE_CONTEXT;
 	}
-	char *scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic);
+	char *scope_topic = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
-	if(strcmp(pubEP->frameworkUUID,fwUUID)==0){
+	if(strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),fwUUID)==0){
 
 		celixThreadMutex_lock(&admin->localPublicationsLock);
 		service_factory_pt factory = (service_factory_pt)hashMap_get(admin->localPublications,scope_topic);
@@ -666,7 +687,7 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi
 			// Check if there are more publishers on the same endpoint (happens when 1 celix-instance with multiple bundles publish in same topic)
 			for(i=0; i<arrayList_size(ext_pub_list);i++) {
 				pubsub_endpoint_pt p  = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
-				if (strcmp(pubEP->endpoint,p->endpoint) == 0) {
+				if (strcmp(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL),properties_get(p->endpoint_props, PUBSUB_ENDPOINT_URL)) == 0) {
 					count++;
 				}
 			}
@@ -688,14 +709,14 @@ celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoi
 	celixThreadMutex_lock(&admin->subscriptionsLock);
 
 	topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic);
-	if(sub!=NULL && pubEP->endpoint!=NULL && count == 0){
-		pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub,pubEP->endpoint);
+	if(sub!=NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL && count == 0){
+		pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub,(char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 	}
 
 	/* And check also for ANY subscription */
 	topic_subscription_pt any_sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,PUBSUB_ANY_SUB_TOPIC);
-	if(any_sub!=NULL && pubEP->endpoint!=NULL && count == 0){
-		pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(any_sub,pubEP->endpoint);
+	if(any_sub!=NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL && count == 0){
+		pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(any_sub,(char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 	}
 
 	free(scope_topic);
@@ -793,7 +814,7 @@ static celix_status_t pubsubAdmin_getIpAdress(const char* interface, char** ip)
 
 static celix_status_t pubsubAdmin_addSubscriptionToPendingList(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
 	celix_status_t status = CELIX_SUCCESS;
-	char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic);
+	char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 	array_list_pt pendingListPerTopic = hashMap_get(admin->pendingSubscriptions,scope_topic);
 	if(pendingListPerTopic==NULL){
 		arrayList_create(&pendingListPerTopic);
@@ -887,9 +908,8 @@ celix_status_t pubsubAdmin_serializerRemoved(void * handle, service_reference_pt
 				/* Remove the publication */
 				pubsubAdmin_removePublication(admin, pubEP);
 				/* Reset the endpoint field, so that will be recreated from scratch when a new serializer will be found */
-				if(pubEP->endpoint!=NULL){
-					free(pubEP->endpoint);
-					pubEP->endpoint = NULL;
+				if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL){
+					properties_unset(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL);
 				}
 				/* Add the orphan endpoint to the noSerializer pending list */
 				celixThreadMutex_lock(&admin->noSerializerPendingsLock);
@@ -939,9 +959,8 @@ celix_status_t pubsubAdmin_serializerRemoved(void * handle, service_reference_pt
 				/* Remove the subscription */
 				pubsubAdmin_removeSubscription(admin, subEP);
 				/* Reset the endpoint field, so that will be recreated from scratch when a new serializer will be found */
-				if(subEP->endpoint!=NULL){
-					free(subEP->endpoint);
-					subEP->endpoint = NULL;
+				if(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL){
+					properties_unset(subEP->endpoint_props, PUBSUB_ENDPOINT_URL);
 				}
 				/* Add the orphan endpoint to the noSerializer pending list */
 				celixThreadMutex_lock(&admin->noSerializerPendingsLock);

http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_admin_zmq/private/src/topic_publication.c
----------------------------------------------------------------------
diff --git a/pubsub/pubsub_admin_zmq/private/src/topic_publication.c b/pubsub/pubsub_admin_zmq/private/src/topic_publication.c
index 34c25b3..105d540 100644
--- a/pubsub/pubsub_admin_zmq/private/src/topic_publication.c
+++ b/pubsub/pubsub_admin_zmq/private/src/topic_publication.c
@@ -198,7 +198,7 @@ celix_status_t pubsub_topicPublicationCreate(bundle_context_pt bundle_context, p
         memset(bindAddress, 0, EP_ADDRESS_LEN);
 
 		snprintf(ep,EP_ADDRESS_LEN,"tcp://%s:%u",bindIP,port);
-        snprintf(bindAddress, EP_ADDRESS_LEN, "tcp://0.0.0.0:%u", port); //NOTE using a different bind addres than endpoint address
+        snprintf(bindAddress, EP_ADDRESS_LEN, "tcp://0.0.0.0:%u", port); //NOTE using a different bind address than endpoint address
 		rv = zsock_bind (socket, "%s", bindAddress);
         if (rv == -1) {
             perror("Error for zmq_bind");
@@ -289,15 +289,16 @@ celix_status_t pubsub_topicPublicationStart(bundle_context_pt bundle_context,top
 		factory->ungetService = pubsub_topicPublicationUngetService;
 
 		properties_pt props = properties_create();
-		properties_set(props,PUBSUB_PUBLISHER_TOPIC,pubEP->topic);
-		properties_set(props,PUBSUB_PUBLISHER_SCOPE,pubEP->scope);
+		properties_set(props,PUBSUB_PUBLISHER_TOPIC,properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
+		properties_set(props,PUBSUB_PUBLISHER_SCOPE,properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE));
 		properties_set(props,"service.version", PUBSUB_PUBLISHER_SERVICE_VERSION);
 
 		status = bundleContext_registerServiceFactory(bundle_context,PUBSUB_PUBLISHER_SERVICE_NAME,factory,props,&(pub->svcFactoryReg));
 
 		if(status != CELIX_SUCCESS){
 			properties_destroy(props);
-			printf("PSA_ZMQ_PSA_ZMQ_TP: Cannot register ServiceFactory for topic %s (bundle %ld).\n",pubEP->topic,pubEP->serviceID);
+			printf("PSA_ZMQ_PSA_ZMQ_TP: Cannot register ServiceFactory for topic %s (bundle %ld).\n",
+				   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),pubEP->serviceID);
 		}
 		else{
 			*svcFactory = factory;
@@ -318,7 +319,7 @@ celix_status_t pubsub_topicPublicationStop(topic_publication_pt pub){
 celix_status_t pubsub_topicPublicationAddPublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep){
 
 	celixThreadMutex_lock(&(pub->tp_lock));
-	ep->endpoint = strdup(pub->endpoint);
+    pubsubEndpoint_setField(ep, PUBSUB_ENDPOINT_URL, pub->endpoint);
 	arrayList_add(pub->pub_ep_list,ep);
 	celixThreadMutex_unlock(&(pub->tp_lock));
 
@@ -587,7 +588,7 @@ static publish_bundle_bound_service_pt pubsub_createPublishBundleBoundService(to
 		arrayList_create(&bound->mp_parts);
 
 		pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(bound->parent->pub_ep_list,0);
-		bound->topic=strdup(pubEP->topic);
+		bound->topic=strdup(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
 		bound->service.handle = bound;
 		bound->service.localMsgTypeIdForMsgType = pubsub_localMsgTypeIdForUUID;

http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_common/public/include/pubsub_endpoint.h
----------------------------------------------------------------------
diff --git a/pubsub/pubsub_common/public/include/pubsub_endpoint.h b/pubsub/pubsub_common/public/include/pubsub_endpoint.h
index 8a979eb..0a0b727 100644
--- a/pubsub/pubsub_common/public/include/pubsub_endpoint.h
+++ b/pubsub/pubsub_common/public/include/pubsub_endpoint.h
@@ -34,13 +34,19 @@
 #include "publisher.h"
 #include "subscriber.h"
 
+#define PUBSUB_ENDPOINT_ID              "pubsub.endpoint.id"
+#define PUBSUB_ENDPOINT_SERVICE_ID      "service.id"
+#define PUBSUB_ENDPOINT_SERIALIZER      "serializer"
+#define PUBSUB_ENDPOINT_ADMIN_TYPE      "pubsub.admin.type"
+#define PUBSUB_ENDPOINT_URL             "pubsub.endpoint"
+#define PUBSUB_ENDPOINT_TOPIC           "pubsub.topic"
+#define PUBSUB_ENDPOINT_SCOPE           "pubsub.scope"
+#define PUBSUB_ENDPOINT_TYPE            "pubsub.type"
+
 struct pubsub_endpoint {
-    char *frameworkUUID;
-    char *scope;
-    char *topic;
-    long serviceID;
-    char* endpoint;
-    bool is_secure;
+    long serviceID;         //optional
+    bool is_secure;         //optional
+    properties_pt endpoint_props;
     properties_pt topic_props;
 };
 
@@ -52,6 +58,7 @@ celix_status_t pubsubEndpoint_createFromListenerHookInfo(listener_hook_info_pt i
 celix_status_t pubsubEndpoint_clone(pubsub_endpoint_pt in, pubsub_endpoint_pt *out);
 celix_status_t pubsubEndpoint_destroy(pubsub_endpoint_pt psEp);
 bool pubsubEndpoint_equals(pubsub_endpoint_pt psEp1,pubsub_endpoint_pt psEp2);
+celix_status_t pubsubEndpoint_setField(pubsub_endpoint_pt ep, const char* key, const char* value);
 
 char *createScopeTopicKey(const char* scope, const char* topic);
 

http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_common/public/src/pubsub_endpoint.c
----------------------------------------------------------------------
diff --git a/pubsub/pubsub_common/public/src/pubsub_endpoint.c b/pubsub/pubsub_common/public/src/pubsub_endpoint.c
index c3fd293..d3b746e 100644
--- a/pubsub/pubsub_common/public/src/pubsub_endpoint.c
+++ b/pubsub/pubsub_common/public/src/pubsub_endpoint.c
@@ -26,6 +26,7 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <uuid/uuid.h>
 
 #include "celix_errno.h"
 #include "celix_log.h"
@@ -42,22 +43,33 @@ static properties_pt pubsubEndpoint_getTopicProperties(bundle_pt bundle, const c
 
 static void pubsubEndpoint_setFields(pubsub_endpoint_pt psEp, const char* fwUUID, const char* scope, const char* topic, long serviceId,const char* endpoint,properties_pt topic_props, bool cloneProps){
 
+	if (psEp->endpoint_props == NULL) {
+		psEp->endpoint_props = properties_create();
+	}
+
+	char endpointUuid[37];
+
+	uuid_t endpointUid;
+	uuid_generate(endpointUid);
+	uuid_unparse(endpointUid, endpointUuid);
+	properties_set(psEp->endpoint_props, PUBSUB_ENDPOINT_ID, endpointUuid);
+
 	if (fwUUID != NULL) {
-		psEp->frameworkUUID = strdup(fwUUID);
+		properties_set(psEp->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID, fwUUID);
 	}
 
 	if (scope != NULL) {
-		psEp->scope = strdup(scope);
+		properties_set(psEp->endpoint_props, PUBSUB_ENDPOINT_SCOPE, scope);
 	}
 
 	if (topic != NULL) {
-		psEp->topic = strdup(topic);
+		properties_set(psEp->endpoint_props, PUBSUB_ENDPOINT_TOPIC, topic);
 	}
 
 	psEp->serviceID = serviceId;
 
 	if(endpoint != NULL) {
-		psEp->endpoint = strdup(endpoint);
+		properties_set(psEp->endpoint_props, PUBSUB_ENDPOINT_URL, endpoint);
 	}
 
 	if(topic_props != NULL){
@@ -102,6 +114,21 @@ static properties_pt pubsubEndpoint_getTopicProperties(bundle_pt bundle, const c
 	return topic_props;
 }
 
+celix_status_t pubsubEndpoint_setField(pubsub_endpoint_pt ep, const char* key, const char* value) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (ep->endpoint_props == NULL) {
+		printf("PUBSUB_EP: No endpoint_props for endpoint available!\n");
+		return CELIX_ILLEGAL_STATE;
+	}
+
+	if (key != NULL && value != NULL) {
+		properties_set(ep->endpoint_props, key, value);
+	}
+
+	return status;
+}
+
 celix_status_t pubsubEndpoint_create(const char* fwUUID, const char* scope, const char* topic, long serviceId,const char* endpoint,properties_pt topic_props,pubsub_endpoint_pt* psEp){
 	celix_status_t status = CELIX_SUCCESS;
 
@@ -116,9 +143,22 @@ celix_status_t pubsubEndpoint_create(const char* fwUUID, const char* scope, cons
 celix_status_t pubsubEndpoint_clone(pubsub_endpoint_pt in, pubsub_endpoint_pt *out){
 	celix_status_t status = CELIX_SUCCESS;
 
-	*out = calloc(1,sizeof(**out));
+    pubsub_endpoint_pt ep = calloc(1,sizeof(*ep));
 
-	pubsubEndpoint_setFields(*out, in->frameworkUUID, in->scope, in->topic, in->serviceID, in->endpoint, in->topic_props, true);
+	status = properties_copy(in->endpoint_props, &(ep->endpoint_props));
+
+    if (in->topic_props != NULL) {
+        status += properties_copy(in->topic_props, &(ep->topic_props));
+    }
+
+	ep->serviceID = in->serviceID;
+	ep->is_secure = in->is_secure;
+
+    if (status == CELIX_SUCCESS) {
+        *out = ep;
+    } else {
+        pubsubEndpoint_destroy(ep);
+    }
 
 	return status;
 
@@ -150,7 +190,11 @@ celix_status_t pubsubEndpoint_createFromServiceReference(service_reference_pt re
 
 	pubsubEndpoint_setFields(ep, fwUUID, scope!=NULL?scope:PUBSUB_SUBSCRIBER_SCOPE_DEFAULT, topic, strtol(serviceId,NULL,10), NULL, topic_props, false);
 
-	if (!ep->frameworkUUID || !ep->serviceID || !ep->scope || !ep->topic) {
+	if (!properties_get(ep->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID) ||
+			!ep->serviceID ||
+			!properties_get(ep->endpoint_props, PUBSUB_ENDPOINT_SCOPE) ||
+			!properties_get(ep->endpoint_props, PUBSUB_ENDPOINT_TOPIC)) {
+
 		fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "PUBSUB_ENDPOINT: incomplete description!.");
 		status = CELIX_BUNDLE_EXCEPTION;
 		pubsubEndpoint_destroy(ep);
@@ -206,30 +250,14 @@ celix_status_t pubsubEndpoint_createFromListenerHookInfo(listener_hook_info_pt i
 
 celix_status_t pubsubEndpoint_destroy(pubsub_endpoint_pt psEp){
 
-	if(psEp->frameworkUUID!=NULL){
-		free(psEp->frameworkUUID);
-		psEp->frameworkUUID = NULL;
-	}
-
-	if(psEp->scope!=NULL){
-		free(psEp->scope);
-		psEp->scope = NULL;
-	}
-
-	if(psEp->topic!=NULL){
-		free(psEp->topic);
-		psEp->topic = NULL;
-	}
-
-	if(psEp->endpoint!=NULL){
-		free(psEp->endpoint);
-		psEp->endpoint = NULL;
-	}
-
 	if(psEp->topic_props != NULL){
 		properties_destroy(psEp->topic_props);
 	}
 
+	if (psEp->endpoint_props != NULL) {
+		properties_destroy(psEp->endpoint_props);
+    }
+
 	free(psEp);
 
 	return CELIX_SUCCESS;
@@ -238,9 +266,9 @@ celix_status_t pubsubEndpoint_destroy(pubsub_endpoint_pt psEp){
 
 bool pubsubEndpoint_equals(pubsub_endpoint_pt psEp1,pubsub_endpoint_pt psEp2){
 
-	return ((strcmp(psEp1->frameworkUUID,psEp2->frameworkUUID)==0) &&
-			(strcmp(psEp1->scope,psEp2->scope)==0) &&
-			(strcmp(psEp1->topic,psEp2->topic)==0) &&
+	return ((strcmp(properties_get(psEp1->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),properties_get(psEp2->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID))==0) &&
+			(strcmp(properties_get(psEp1->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(psEp2->endpoint_props, PUBSUB_ENDPOINT_SCOPE))==0) &&
+			(strcmp(properties_get(psEp1->endpoint_props, PUBSUB_ENDPOINT_TOPIC),properties_get(psEp2->endpoint_props, PUBSUB_ENDPOINT_TOPIC))==0) &&
 			(psEp1->serviceID == psEp2->serviceID) /*&&
 			((psEp1->endpoint==NULL && psEp2->endpoint==NULL)||(strcmp(psEp1->endpoint,psEp2->endpoint)==0))*/
 	);

http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_discovery/private/src/etcd_watcher.c
----------------------------------------------------------------------
diff --git a/pubsub/pubsub_discovery/private/src/etcd_watcher.c b/pubsub/pubsub_discovery/private/src/etcd_watcher.c
index 3c3a5a8..726269a 100644
--- a/pubsub/pubsub_discovery/private/src/etcd_watcher.c
+++ b/pubsub/pubsub_discovery/private/src/etcd_watcher.c
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#include <jansson.h>
 
 #include "celix_log.h"
 #include "constants.h"
@@ -143,7 +144,60 @@ celix_status_t etcdWatcher_getPublisherEndpointFromKey(pubsub_discovery_pt pubsu
 			status = CELIX_ILLEGAL_STATE;
 		}
 		else{
-			status = pubsubEndpoint_create(fwUUID,scope,topic,strtol(serviceId,NULL,10),etcdValue,NULL,pubEP);
+
+			// etcdValue contains the json formatted string
+			json_error_t error;
+			json_t* jsonRoot = json_loads(etcdValue, JSON_DECODE_ANY, &error);
+
+			const char* endpoint_serializer = NULL;
+			const char* endpoint_admin_type = NULL;
+			const char* endpoint_url = NULL;
+			const char* endpoint_type = NULL;
+
+			if (json_is_object(jsonRoot)){
+
+				void *iter = json_object_iter(jsonRoot);
+
+				const char *key;
+				json_t *value;
+
+				while (iter) {
+					key = json_object_iter_key(iter);
+					value = json_object_iter_value(iter);
+
+					if (strcmp(key, PUBSUB_ENDPOINT_SERIALIZER) == 0) {
+						endpoint_serializer = json_string_value(value);
+					} else if (strcmp(key, PUBSUB_ENDPOINT_ADMIN_TYPE) == 0) {
+						endpoint_admin_type = json_string_value(value);
+					} else if (strcmp(key, PUBSUB_ENDPOINT_URL) == 0) {
+						endpoint_url = json_string_value(value);
+					} else if (strcmp(key, PUBSUB_ENDPOINT_TYPE) == 0) {
+						endpoint_type = json_string_value(value);
+					}
+
+					iter = json_object_iter_next(jsonRoot, iter);
+				}
+
+				if (endpoint_url == NULL) {
+					printf("EW: No endpoint found in json object!\n");
+					endpoint_url = etcdValue;
+				}
+
+			} else {
+				endpoint_url = etcdValue;
+			}
+
+			status = pubsubEndpoint_create(fwUUID,scope,topic,strtol(serviceId,NULL,10),endpoint_url,NULL,pubEP);
+
+            if (status == CELIX_SUCCESS) {
+                status += pubsubEndpoint_setField(*pubEP, PUBSUB_ENDPOINT_SERIALIZER, endpoint_serializer);
+                status += pubsubEndpoint_setField(*pubEP, PUBSUB_ENDPOINT_ADMIN_TYPE, endpoint_admin_type);
+                status += pubsubEndpoint_setField(*pubEP, PUBSUB_ENDPOINT_TYPE, endpoint_type);
+            }
+
+			if (jsonRoot != NULL) {
+				json_decref(jsonRoot);
+			}
 		}
 	}
 	return status;

http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_discovery/private/src/etcd_writer.c
----------------------------------------------------------------------
diff --git a/pubsub/pubsub_discovery/private/src/etcd_writer.c b/pubsub/pubsub_discovery/private/src/etcd_writer.c
index 1c423f3..e820e50 100644
--- a/pubsub/pubsub_discovery/private/src/etcd_writer.c
+++ b/pubsub/pubsub_discovery/private/src/etcd_writer.c
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#include <jansson.h>
 
 #include "celix_log.h"
 #include "constants.h"
@@ -82,7 +83,12 @@ void etcdWriter_destroy(etcd_writer_pt writer) {
 	for(int i = 0; i < arrayList_size(writer->localPubs); i++) {
 		pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(writer->localPubs,i);
 		memset(dir,0,MAX_ROOTNODE_LENGTH);
-		snprintf(dir,MAX_ROOTNODE_LENGTH,"%s/%s/%s/%s",rootPath,pubEP->scope,pubEP->topic,pubEP->frameworkUUID);
+		snprintf(dir,MAX_ROOTNODE_LENGTH,"%s/%s/%s/%s",
+				 rootPath,
+				 properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+				 properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+				 properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID));
+
 		etcd_del(dir);
 		pubsubEndpoint_destroy(pubEP);
 	}
@@ -100,7 +106,7 @@ celix_status_t etcdWriter_addPublisherEndpoint(etcd_writer_pt writer, pubsub_end
 	if(storeEP){
 		const char *fwUUID = NULL;
 		bundleContext_getProperty(writer->pubsub_discovery->context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &fwUUID);
-		if(fwUUID && strcmp(pubEP->frameworkUUID, fwUUID) == 0) {
+		if(fwUUID && strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID), fwUUID) == 0) {
 			celixThreadMutex_lock(&writer->localPubsLock);
 			pubsub_endpoint_pt p = NULL;
 			pubsubEndpoint_clone(pubEP, &p);
@@ -128,12 +134,33 @@ celix_status_t etcdWriter_addPublisherEndpoint(etcd_writer_pt writer, pubsub_end
 
 	const char *rootPath = etcdWriter_getRootPath(writer->pubsub_discovery->context);
 
-	asprintf(&key,"%s/%s/%s/%s/%ld",rootPath,pubEP->scope,pubEP->topic,pubEP->frameworkUUID,pubEP->serviceID);
-
-	if(!etcd_set(key,pubEP->endpoint,ttl,false)){
+	asprintf(&key,"%s/%s/%s/%s/%ld",
+			 rootPath,
+			 properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+			 properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+			 properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+			 pubEP->serviceID);
+
+    char serviceID [sizeof(pubEP->serviceID)];
+    snprintf(serviceID, sizeof(pubEP->serviceID), "%ld", pubEP->serviceID);
+	json_t* jsonEndpoint = json_pack("{s:s,s:s,s:s,s:s,s:s,s:s,s:s}",
+									 PUBSUB_ENDPOINT_SERVICE_ID, serviceID,
+									 PUBSUB_ENDPOINT_SERIALIZER, "serializer.json", //TODO: Serializer not (yet) stored in endpoint
+									 PUBSUB_ENDPOINT_ADMIN_TYPE, "zmq", //TODO: PSA type not (yet) stored in endpoint
+									 PUBSUB_ENDPOINT_URL, properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL),
+									 PUBSUB_ENDPOINT_TYPE, "publisher", //TODO: Check if necessary
+									 PUBSUB_ENDPOINT_TOPIC, properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+									 PUBSUB_ENDPOINT_SCOPE, properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE)
+	);
+	char* jsonEndpointStr = json_dumps(jsonEndpoint, JSON_COMPACT);
+
+	if (!etcd_set(key,jsonEndpointStr,ttl,false)) {
 		status = CELIX_ILLEGAL_ARGUMENT;
 	}
 	FREE_MEM(key);
+	FREE_MEM(jsonEndpointStr);
+	json_decref(jsonEndpoint);
+
 	return status;
 }
 
@@ -143,7 +170,12 @@ celix_status_t etcdWriter_deletePublisherEndpoint(etcd_writer_pt writer, pubsub_
 
 	const char *rootPath = etcdWriter_getRootPath(writer->pubsub_discovery->context);
 
-	asprintf(&key, "%s/%s/%s/%s/%ld", rootPath, pubEP->scope, pubEP->topic, pubEP->frameworkUUID, pubEP->serviceID);
+	asprintf(&key, "%s/%s/%s/%s/%ld",
+			 rootPath,
+			 properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
+			 properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+			 properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+			 pubEP->serviceID);
 
 	celixThreadMutex_lock(&writer->localPubsLock);
 	for (unsigned int i = 0; i < arrayList_size(writer->localPubs); i++) {

http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_discovery/private/src/pubsub_discovery_impl.c
----------------------------------------------------------------------
diff --git a/pubsub/pubsub_discovery/private/src/pubsub_discovery_impl.c b/pubsub/pubsub_discovery/private/src/pubsub_discovery_impl.c
index 94a8e11..e3e9704 100644
--- a/pubsub/pubsub_discovery/private/src/pubsub_discovery_impl.c
+++ b/pubsub/pubsub_discovery/private/src/pubsub_discovery_impl.c
@@ -143,7 +143,7 @@ celix_status_t pubsub_discovery_stop(pubsub_discovery_pt ps_discovery) {
         int i;
         for (i = 0; i < arrayList_size(pubEP_list); i++) {
             pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt) arrayList_get(pubEP_list, i);
-            if (strcmp(pubEP->frameworkUUID, fwUUID) == 0) {
+            if (strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID), fwUUID) == 0) {
                 etcdWriter_deletePublisherEndpoint(ps_discovery->writer, pubEP);
             } else {
                 pubsub_discovery_informPublishersListeners(ps_discovery, pubEP, false);
@@ -177,7 +177,7 @@ celix_status_t pubsub_discovery_addNode(pubsub_discovery_pt pubsub_discovery, pu
 	bool inform=false;
 	celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
 
-	char *pubs_key = createScopeTopicKey(pubEP->scope, pubEP->topic);
+	char *pubs_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 	array_list_pt pubEP_list = (array_list_pt)hashMap_get(pubsub_discovery->discoveredPubs,pubs_key);
 	if(pubEP_list==NULL){
 		arrayList_create(&pubEP_list);
@@ -216,11 +216,12 @@ celix_status_t pubsub_discovery_removeNode(pubsub_discovery_pt pubsub_discovery,
     bool found = false;
 
     celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
-    char *pubs_key = createScopeTopicKey(pubEP->scope, pubEP->topic);
+    char *pubs_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
     array_list_pt pubEP_list = (array_list_pt) hashMap_get(pubsub_discovery->discoveredPubs, pubs_key);
     free(pubs_key);
     if (pubEP_list == NULL) {
-        printf("PSD: Cannot find any registered publisher for topic %s. Something is not consistent.\n", pubEP->topic);
+        printf("PSD: Cannot find any registered publisher for topic %s. Something is not consistent.\n",
+			   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
         status = CELIX_ILLEGAL_STATE;
     } else {
         int i;
@@ -278,12 +279,14 @@ celix_status_t pubsub_discovery_informPublishersListeners(pubsub_discovery_pt pu
 /* Service's functions implementation */
 celix_status_t pubsub_discovery_announcePublisher(void *handle, pubsub_endpoint_pt pubEP) {
 	celix_status_t status = CELIX_SUCCESS;
-	printf("pubsub_discovery_announcePublisher : %s / %s\n", pubEP->topic, pubEP->endpoint);
+	printf("pubsub_discovery_announcePublisher : %s / %s\n",
+		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 	pubsub_discovery_pt pubsub_discovery = (pubsub_discovery_pt) handle;
 
 	celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
 
-	char *pub_key = createScopeTopicKey(pubEP->scope,pubEP->topic);
+	char *pub_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 	array_list_pt pubEP_list = (array_list_pt)hashMap_get(pubsub_discovery->discoveredPubs,pub_key);
 
 	if(pubEP_list==NULL){
@@ -310,11 +313,11 @@ celix_status_t pubsub_discovery_removePublisher(void *handle, pubsub_endpoint_pt
 
 	celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
 
-	char *pub_key = createScopeTopicKey(pubEP->scope,pubEP->topic);
+	char *pub_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 	array_list_pt pubEP_list = (array_list_pt)hashMap_get(pubsub_discovery->discoveredPubs,pub_key);
 	free(pub_key);
 	if(pubEP_list==NULL){
-		printf("PSD: Cannot find any registered publisher for topic %s. Something is not consistent.\n",pubEP->topic);
+		printf("PSD: Cannot find any registered publisher for topic %s. Something is not consistent.\n",properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 		status = CELIX_ILLEGAL_STATE;
 	}
 	else{

http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/pubsub/pubsub_topology_manager/private/src/pubsub_topology_manager.c
----------------------------------------------------------------------
diff --git a/pubsub/pubsub_topology_manager/private/src/pubsub_topology_manager.c b/pubsub/pubsub_topology_manager/private/src/pubsub_topology_manager.c
index 987d864..4ee9951 100644
--- a/pubsub/pubsub_topology_manager/private/src/pubsub_topology_manager.c
+++ b/pubsub/pubsub_topology_manager/private/src/pubsub_topology_manager.c
@@ -216,7 +216,7 @@ celix_status_t pubsub_topologyManager_psaRemoved(void * handle, service_referenc
 				int i;
 				for(i=0;i<arrayList_size(pubEP_list);i++){
 					pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pubEP_list,i);
-					if(strcmp(pubEP->frameworkUUID,fwUUID)==0){
+					if(strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),fwUUID)==0){
 						disc->removePublisher(disc->handle,pubEP);
 					}
 				}
@@ -263,7 +263,7 @@ celix_status_t pubsub_topologyManager_subscriberAdded(void * handle, service_ref
 	pubsub_endpoint_pt sub = NULL;
 	if(pubsubEndpoint_createFromServiceReference(reference,&sub,false) == CELIX_SUCCESS){
 		celixThreadMutex_lock(&manager->subscriptionsLock);
-		char *sub_key = createScopeTopicKey(sub->scope, sub->topic);
+		char *sub_key = createScopeTopicKey(properties_get(sub->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(sub->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
 		array_list_pt sub_list_by_topic = hashMap_get(manager->subscriptions,sub_key);
 		if(sub_list_by_topic==NULL){
@@ -300,7 +300,7 @@ celix_status_t pubsub_topologyManager_subscriberAdded(void * handle, service_ref
 			service_reference_pt disc_sr = (service_reference_pt)hashMapIterator_nextKey(iter);
 			publisher_endpoint_announce_pt disc = NULL;
 			bundleContext_getService(manager->context, disc_sr, (void**) &disc);
-			disc->interestedInTopic(disc->handle, sub->scope, sub->topic);
+			disc->interestedInTopic(disc->handle, properties_get(sub->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(sub->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 			bundleContext_ungetService(manager->context, disc_sr, NULL);
 		}
 		hashMapIterator_destroy(iter);
@@ -339,7 +339,7 @@ celix_status_t pubsub_topologyManager_subscriberRemoved(void * handle, service_r
 			service_reference_pt disc_sr = (service_reference_pt)hashMapIterator_nextKey(iter);
 			publisher_endpoint_announce_pt disc = NULL;
 			bundleContext_getService(manager->context, disc_sr, (void**) &disc);
-			disc->uninterestedInTopic(disc->handle, subcmp->scope, subcmp->topic);
+			disc->uninterestedInTopic(disc->handle, properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 			bundleContext_ungetService(manager->context, disc_sr, NULL);
 		}
 		hashMapIterator_destroy(iter);
@@ -348,7 +348,7 @@ celix_status_t pubsub_topologyManager_subscriberRemoved(void * handle, service_r
 		celixThreadMutex_lock(&manager->subscriptionsLock);
 		celixThreadMutex_lock(&manager->psaListLock);
 
-		char *sub_key = createScopeTopicKey(subcmp->scope,subcmp->topic);
+		char *sub_key = createScopeTopicKey(properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 		array_list_pt sub_list_by_topic = hashMap_get(manager->subscriptions,sub_key);
 		free(sub_key);
 		if(sub_list_by_topic!=NULL){
@@ -368,7 +368,7 @@ celix_status_t pubsub_topologyManager_subscriberRemoved(void * handle, service_r
 				if(arrayList_size(sub_list_by_topic)==0){
 					for(k=0;k<arrayList_size(manager->psaList);k++){
 						pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,k);
-						psa->closeAllSubscriptions(psa->admin,sub->scope, sub->topic);
+						psa->closeAllSubscriptions(psa->admin, (char*) properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 					}
 				}
 
@@ -415,7 +415,7 @@ celix_status_t pubsub_topologyManager_pubsubDiscoveryAdded(void* handle, service
 		array_list_pt pubEP_list = (array_list_pt)hashMapIterator_nextValue(iter);
 		for(int i = 0; i < arrayList_size(pubEP_list); i++) {
 			pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pubEP_list,i);
-			if( (strcmp(pubEP->frameworkUUID,fwUUID)==0) && (pubEP->endpoint!=NULL)){
+			if( (strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),fwUUID)==0) && (properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL)){
 				status += disc->announcePublisher(disc->handle,pubEP);
 			}
 		}
@@ -433,7 +433,7 @@ celix_status_t pubsub_topologyManager_pubsubDiscoveryAdded(void* handle, service
 		for(i=0;i<arrayList_size(l);i++){
 			pubsub_endpoint_pt subEp = (pubsub_endpoint_pt)arrayList_get(l,i);
 
-			disc->interestedInTopic(disc->handle, subEp->scope, subEp->topic);
+			disc->interestedInTopic(disc->handle, properties_get(subEp->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 		}
 	}
 	hashMapIterator_destroy(iter);
@@ -486,7 +486,7 @@ celix_status_t pubsub_topologyManager_publisherTrackerAdded(void *handle, array_
 		if(pubsubEndpoint_createFromListenerHookInfo(info, &pub, true) == CELIX_SUCCESS){
 
 			celixThreadMutex_lock(&manager->publicationsLock);
-			char *pub_key = createScopeTopicKey(pub->scope, pub->topic);
+			char *pub_key = createScopeTopicKey(properties_get(pub->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pub->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 			array_list_pt pub_list_by_topic = hashMap_get(manager->publications, pub_key);
 			if(pub_list_by_topic==NULL){
 				arrayList_create(&pub_list_by_topic);
@@ -558,7 +558,7 @@ celix_status_t pubsub_topologyManager_publisherTrackerRemoved(void *handle, arra
 			celixThreadMutex_lock(&manager->psaListLock);
 			celixThreadMutex_lock(&manager->publicationsLock);
 
-			char *pub_key = createScopeTopicKey(pubcmp->scope, pubcmp->topic);
+			char *pub_key = createScopeTopicKey(properties_get(pubcmp->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubcmp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 			array_list_pt pub_list_by_topic = hashMap_get(manager->publications,pub_key);
 			if(pub_list_by_topic!=NULL){
 				for(j=0;j<arrayList_size(pub_list_by_topic);j++){
@@ -591,7 +591,7 @@ celix_status_t pubsub_topologyManager_publisherTrackerRemoved(void *handle, arra
 						if(arrayList_size(pub_list_by_topic)==0){
 							for(k=0;k<arrayList_size(manager->psaList);k++){
 								pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,k);
-								psa->closeAllPublications(psa->admin,pub->scope, pub->topic);
+								psa->closeAllPublications(psa->admin, (char*) properties_get(pub->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(pub->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 							}
 						}
 
@@ -617,13 +617,16 @@ celix_status_t pubsub_topologyManager_publisherTrackerRemoved(void *handle, arra
 
 celix_status_t pubsub_topologyManager_announcePublisher(void *handle, pubsub_endpoint_pt pubEP){
 	celix_status_t status = CELIX_SUCCESS;
-	printf("PSTM: New publisher discovered for topic %s [fwUUID=%s, ep=%s]\n",pubEP->topic,pubEP->frameworkUUID,pubEP->endpoint);
+	printf("PSTM: New publisher discovered for topic %s [fwUUID=%s, ep=%s]\n",
+		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+		   properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 
 	pubsub_topology_manager_pt manager = handle;
 	celixThreadMutex_lock(&manager->psaListLock);
 	celixThreadMutex_lock(&manager->publicationsLock);
 
-	char *pub_key = createScopeTopicKey(pubEP->scope, pubEP->topic);
+	char *pub_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 
 	array_list_pt pub_list_by_topic = hashMap_get(manager->publications,pub_key);
 	if(pub_list_by_topic==NULL){
@@ -666,17 +669,20 @@ celix_status_t pubsub_topologyManager_announcePublisher(void *handle, pubsub_end
 
 celix_status_t pubsub_topologyManager_removePublisher(void *handle, pubsub_endpoint_pt pubEP){
 	celix_status_t status = CELIX_SUCCESS;
-	printf("PSTM: Publisher removed for topic %s [fwUUID=%s, ep=%s]\n",pubEP->topic,pubEP->frameworkUUID,pubEP->endpoint);
+	printf("PSTM: Publisher removed for topic %s [fwUUID=%s, ep=%s]\n",
+		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
+		   properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
+		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 
 	pubsub_topology_manager_pt manager = handle;
 	celixThreadMutex_lock(&manager->psaListLock);
 	celixThreadMutex_lock(&manager->publicationsLock);
 	int i;
 
-	char *pub_key = createScopeTopicKey(pubEP->scope, pubEP->topic);
+	char *pub_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 	array_list_pt pub_list_by_topic = hashMap_get(manager->publications,pub_key);
 	if(pub_list_by_topic==NULL){
-		printf("PSTM: ERROR: Cannot find topic for known endpoint [%s,%s,%s]. Something is inconsistent.\n",pub_key,pubEP->frameworkUUID,pubEP->endpoint);
+		printf("PSTM: ERROR: Cannot find topic for known endpoint [%s,%s,%s]. Something is inconsistent.\n",pub_key,properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 		status = CELIX_ILLEGAL_STATE;
 	}
 	else{
@@ -704,7 +710,7 @@ celix_status_t pubsub_topologyManager_removePublisher(void *handle, pubsub_endpo
 
 				for(i=0;i<arrayList_size(manager->psaList);i++){
 					pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,i);
-					psa->closeAllPublications(psa->admin,p->scope, p->topic);
+					psa->closeAllPublications(psa->admin, (char*) properties_get(p->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(p->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 				}
 			}
 

http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/utils/private/src/properties.c
----------------------------------------------------------------------
diff --git a/utils/private/src/properties.c b/utils/private/src/properties.c
index 1e097a0..860b9bb 100644
--- a/utils/private/src/properties.c
+++ b/utils/private/src/properties.c
@@ -212,6 +212,11 @@ void properties_set(properties_pt properties, const char* key, const char* value
 	free(oldValue);
 }
 
+void properties_unset(properties_pt properties, const char* key) {
+	char* oldValue = hashMap_remove(properties, key);
+	free(oldValue);
+}
+
 static void updateBuffers(char **key, char ** value, char **output, int outputPos, int *key_len, int *value_len) {
 	if (*output == *key) {
 		if (outputPos == (*key_len) - 1) {

http://git-wip-us.apache.org/repos/asf/celix/blob/9094f554/utils/public/include/properties.h
----------------------------------------------------------------------
diff --git a/utils/public/include/properties.h b/utils/public/include/properties.h
index 5c6dc4d..582a242 100644
--- a/utils/public/include/properties.h
+++ b/utils/public/include/properties.h
@@ -56,6 +56,8 @@ UTILS_EXPORT const char *properties_getWithDefault(properties_pt properties, con
 
 UTILS_EXPORT void properties_set(properties_pt properties, const char *key, const char *value);
 
+UTILS_EXPORT void properties_unset(properties_pt properties, const char *key);
+
 UTILS_EXPORT celix_status_t properties_copy(properties_pt properties, properties_pt *copy);
 
 #define PROPERTIES_FOR_EACH(props, key) \


[3/4] celix git commit: Merge branch 'endpoint-format' into develop

Posted by rl...@apache.org.
http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_admin_zmq/src/pubsub_admin_impl.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_admin_zmq/src/pubsub_admin_impl.c
index 2dcec25,0000000..9929437
mode 100644,000000..100644
--- a/pubsub/pubsub_admin_zmq/src/pubsub_admin_impl.c
+++ b/pubsub/pubsub_admin_zmq/src/pubsub_admin_impl.c
@@@ -1,1040 -1,0 +1,1059 @@@
 +/**
 + *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_admin_impl.c
 + *
 + *  \date       Sep 30, 2011
 + *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
 + *  \copyright	Apache License, Version 2.0
 + */
 +
 +#include "pubsub_admin_impl.h"
 +#include <zmq.h>
 +
 +#include <stdio.h>
 +#include <stdlib.h>
 +
 +#include <arpa/inet.h>
 +#include <sys/socket.h>
 +#include <netdb.h>
 +
 +#ifndef ANDROID
 +#include <ifaddrs.h>
 +#endif
 +
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <unistd.h>
 +#include <string.h>
 +
 +#include "constants.h"
 +#include "utils.h"
 +#include "hash_map.h"
 +#include "array_list.h"
 +#include "bundle_context.h"
 +#include "bundle.h"
 +#include "service_reference.h"
 +#include "service_registration.h"
 +#include "log_helper.h"
 +#include "log_service.h"
 +#include "celix_threads.h"
 +#include "service_factory.h"
 +
 +#include "topic_subscription.h"
 +#include "topic_publication.h"
 +#include "pubsub_endpoint.h"
 +#include "pubsub_utils.h"
 +#include "pubsub/subscriber.h"
 +
 +#define MAX_KEY_FOLDER_PATH_LENGTH 512
 +
 +static const char *DEFAULT_IP = "127.0.0.1";
 +
 +static celix_status_t pubsubAdmin_getIpAdress(const char* interface, char** ip);
 +static celix_status_t pubsubAdmin_addSubscriptionToPendingList(pubsub_admin_pt admin,pubsub_endpoint_pt subEP);
 +static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP);
 +
 +static celix_status_t pubsubAdmin_getBestSerializer(pubsub_admin_pt admin,pubsub_endpoint_pt ep, pubsub_serializer_service_t **serSvc);
 +static void connectTopicPubSubToSerializer(pubsub_admin_pt admin,pubsub_serializer_service_t *serializer,void *topicPubSub,bool isPublication);
 +static void disconnectTopicPubSubFromSerializer(pubsub_admin_pt admin,void *topicPubSub,bool isPublication);
 +
 +celix_status_t pubsubAdmin_create(bundle_context_pt context, pubsub_admin_pt *admin) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +#ifdef BUILD_WITH_ZMQ_SECURITY
 +	if (!zsys_has_curve()){
 +		printf("PSA_ZMQ: zeromq curve unsupported\n");
 +		return CELIX_SERVICE_EXCEPTION;
 +	}
 +#endif
 +
 +	*admin = calloc(1, sizeof(**admin));
 +
 +	if (!*admin) {
 +		status = CELIX_ENOMEM;
 +	}
 +	else{
 +
 +		const char *ip = NULL;
 +		char *detectedIp = NULL;
 +		(*admin)->bundle_context= context;
 +		(*admin)->localPublications = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
 +		(*admin)->subscriptions = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
 +		(*admin)->pendingSubscriptions = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
 +		(*admin)->externalPublications = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
 +		(*admin)->topicSubscriptionsPerSerializer = hashMap_create(NULL, NULL, NULL, NULL);
 +		(*admin)->topicPublicationsPerSerializer  = hashMap_create(NULL, NULL, NULL, NULL);
 +		arrayList_create(&((*admin)->noSerializerSubscriptions));
 +		arrayList_create(&((*admin)->noSerializerPublications));
 +		arrayList_create(&((*admin)->serializerList));
 +
 +		celixThreadMutex_create(&(*admin)->localPublicationsLock, NULL);
 +		celixThreadMutex_create(&(*admin)->subscriptionsLock, NULL);
 +		celixThreadMutex_create(&(*admin)->externalPublicationsLock, NULL);
 +		celixThreadMutex_create(&(*admin)->serializerListLock, NULL);
 +		celixThreadMutex_create(&(*admin)->usedSerializersLock, NULL);
 +
 +		celixThreadMutexAttr_create(&(*admin)->noSerializerPendingsAttr);
 +		celixThreadMutexAttr_settype(&(*admin)->noSerializerPendingsAttr, CELIX_THREAD_MUTEX_RECURSIVE);
 +		celixThreadMutex_create(&(*admin)->noSerializerPendingsLock, &(*admin)->noSerializerPendingsAttr);
 +
 +		celixThreadMutexAttr_create(&(*admin)->pendingSubscriptionsAttr);
 +		celixThreadMutexAttr_settype(&(*admin)->pendingSubscriptionsAttr, CELIX_THREAD_MUTEX_RECURSIVE);
 +		celixThreadMutex_create(&(*admin)->pendingSubscriptionsLock, &(*admin)->pendingSubscriptionsAttr);
 +
 +		if (logHelper_create(context, &(*admin)->loghelper) == CELIX_SUCCESS) {
 +			logHelper_start((*admin)->loghelper);
 +		}
 +
 +		bundleContext_getProperty(context,PSA_IP , &ip);
 +
 +#ifndef ANDROID
 +		if (ip == NULL) {
 +			const char *interface = NULL;
 +
 +			bundleContext_getProperty(context, PSA_ITF, &interface);
 +			if (pubsubAdmin_getIpAdress(interface, &detectedIp) != CELIX_SUCCESS) {
 +				logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "PSA_ZMQ: Could not retrieve IP adress for interface %s", interface);
 +			}
 +
 +			ip = detectedIp;
 +		}
 +#endif
 +
 +		if (ip != NULL) {
 +			logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "PSA_ZMQ: Using %s for service annunciation", ip);
 +			(*admin)->ipAddress = strdup(ip);
 +		}
 +		else {
 +			logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "PSA_ZMQ: No IP address for service annunciation set. Using %s", DEFAULT_IP);
 +			(*admin)->ipAddress = strdup(DEFAULT_IP);
 +		}
 +
 +		if (detectedIp != NULL) {
 +			free(detectedIp);
 +		}
 +
 +		const char* basePortStr = NULL;
 +		const char* maxPortStr = NULL;
 +		char* endptrBase = NULL;
 +		char* endptrMax = NULL;
 +		bundleContext_getPropertyWithDefault(context, PSA_ZMQ_BASE_PORT, "PSA_ZMQ_DEFAULT_BASE_PORT", &basePortStr);
 +		bundleContext_getPropertyWithDefault(context, PSA_ZMQ_MAX_PORT, "PSA_ZMQ_DEFAULT_MAX_PORT", &maxPortStr);
 +		(*admin)->basePort = strtol(basePortStr, &endptrBase, 10);
 +		(*admin)->maxPort = strtol(maxPortStr, &endptrMax, 10);
 +		if (*endptrBase != '\0') {
 +			(*admin)->basePort = PSA_ZMQ_DEFAULT_BASE_PORT;
 +		}
 +		if (*endptrMax != '\0') {
 +			(*admin)->maxPort = PSA_ZMQ_DEFAULT_MAX_PORT;
 +		}
 +
 +		printf("PSA Using base port %u to max port %u\n", (*admin)->basePort, (*admin)->maxPort);
 +
 +		// Disable Signal Handling by CZMQ
 +		setenv("ZSYS_SIGHANDLER", "false", true);
 +
 +		const char *nrZmqThreads = NULL;
 +		bundleContext_getProperty(context, "PSA_NR_ZMQ_THREADS", &nrZmqThreads);
 +
 +		if(nrZmqThreads != NULL) {
 +			char *endPtr = NULL;
 +			unsigned int nrThreads = strtoul(nrZmqThreads, &endPtr, 10);
 +			if(endPtr != nrZmqThreads && nrThreads > 0 && nrThreads < 50) {
 +				zsys_set_io_threads(nrThreads);
 +				logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "PSA_ZMQ: Using %d threads for ZMQ", nrThreads);
 +				printf("PSA_ZMQ: Using %d threads for ZMQ\n", 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
 +
 +	}
 +
 +	return status;
 +}
 +
 +
 +celix_status_t pubsubAdmin_destroy(pubsub_admin_pt admin)
 +{
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	free(admin->ipAddress);
 +
 +	celixThreadMutex_lock(&admin->pendingSubscriptionsLock);
 +	hash_map_iterator_pt iter = hashMapIterator_create(admin->pendingSubscriptions);
 +	while(hashMapIterator_hasNext(iter)){
 +		hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
 +		free((char*)hashMapEntry_getKey(entry));
 +		arrayList_destroy((array_list_pt)hashMapEntry_getValue(entry));
 +	}
 +	hashMapIterator_destroy(iter);
 +	hashMap_destroy(admin->pendingSubscriptions,false,false);
 +	celixThreadMutex_unlock(&admin->pendingSubscriptionsLock);
 +
 +	celixThreadMutex_lock(&admin->subscriptionsLock);
 +	hashMap_destroy(admin->subscriptions,false,false);
 +	celixThreadMutex_unlock(&admin->subscriptionsLock);
 +
 +	celixThreadMutex_lock(&admin->localPublicationsLock);
 +	hashMap_destroy(admin->localPublications,true,false);
 +	celixThreadMutex_unlock(&admin->localPublicationsLock);
 +
 +	celixThreadMutex_lock(&admin->externalPublicationsLock);
 +	iter = hashMapIterator_create(admin->externalPublications);
 +	while(hashMapIterator_hasNext(iter)){
 +		hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
 +		free((char*)hashMapEntry_getKey(entry));
 +		arrayList_destroy((array_list_pt)hashMapEntry_getValue(entry));
 +	}
 +	hashMapIterator_destroy(iter);
 +	hashMap_destroy(admin->externalPublications,false,false);
 +	celixThreadMutex_unlock(&admin->externalPublicationsLock);
 +
 +	celixThreadMutex_lock(&admin->serializerListLock);
 +	arrayList_destroy(admin->serializerList);
 +	celixThreadMutex_unlock(&admin->serializerListLock);
 +
 +	celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +	arrayList_destroy(admin->noSerializerSubscriptions);
 +	arrayList_destroy(admin->noSerializerPublications);
 +	celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +
 +
 +	celixThreadMutex_lock(&admin->usedSerializersLock);
 +
 +	iter = hashMapIterator_create(admin->topicSubscriptionsPerSerializer);
 +	while(hashMapIterator_hasNext(iter)){
 +		arrayList_destroy((array_list_pt)hashMapIterator_nextValue(iter));
 +	}
 +	hashMapIterator_destroy(iter);
 +	hashMap_destroy(admin->topicSubscriptionsPerSerializer,false,false);
 +
 +	iter = hashMapIterator_create(admin->topicPublicationsPerSerializer);
 +	while(hashMapIterator_hasNext(iter)){
 +		arrayList_destroy((array_list_pt)hashMapIterator_nextValue(iter));
 +	}
 +	hashMapIterator_destroy(iter);
 +	hashMap_destroy(admin->topicPublicationsPerSerializer,false,false);
 +
 +	celixThreadMutex_unlock(&admin->usedSerializersLock);
 +
 +	celixThreadMutex_destroy(&admin->usedSerializersLock);
 +	celixThreadMutex_destroy(&admin->serializerListLock);
 +	celixThreadMutex_destroy(&admin->pendingSubscriptionsLock);
 +
 +	celixThreadMutexAttr_destroy(&admin->noSerializerPendingsAttr);
 +	celixThreadMutex_destroy(&admin->noSerializerPendingsLock);
 +
 +	celixThreadMutexAttr_destroy(&admin->pendingSubscriptionsAttr);
 +	celixThreadMutex_destroy(&admin->subscriptionsLock);
 +
 +	celixThreadMutex_destroy(&admin->localPublicationsLock);
 +	celixThreadMutex_destroy(&admin->externalPublicationsLock);
 +
 +	logHelper_stop(admin->loghelper);
 +
 +	logHelper_destroy(&admin->loghelper);
 +
 +#ifdef BUILD_WITH_ZMQ_SECURITY
 +	if (admin->zmq_auth != NULL){
 +		zactor_destroy(&(admin->zmq_auth));
 +	}
 +#endif
 +
 +	free(admin);
 +
 +	return status;
 +}
 +
 +static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	celixThreadMutex_lock(&admin->subscriptionsLock);
 +
 +	topic_subscription_pt any_sub = hashMap_get(admin->subscriptions,PUBSUB_ANY_SUB_TOPIC);
 +
 +	if(any_sub==NULL){
 +
 +		int i;
 +		pubsub_serializer_service_t *best_serializer = NULL;
 +		if( (status=pubsubAdmin_getBestSerializer(admin, subEP, &best_serializer)) == CELIX_SUCCESS){
 +			status = pubsub_topicSubscriptionCreate(admin->bundle_context, PUBSUB_SUBSCRIBER_SCOPE_DEFAULT, PUBSUB_ANY_SUB_TOPIC, best_serializer, &any_sub);
 +		}
 +		else{
- 			printf("PSA_ZMQ: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",subEP->topic);
++			printf("PSA_ZMQ: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",
++				   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +			celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +			arrayList_add(admin->noSerializerSubscriptions,subEP);
 +			celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +		}
 +
 +		if (status == CELIX_SUCCESS){
 +
 +			/* Connect all internal publishers */
 +			celixThreadMutex_lock(&admin->localPublicationsLock);
 +			hash_map_iterator_pt lp_iter =hashMapIterator_create(admin->localPublications);
 +			while(hashMapIterator_hasNext(lp_iter)){
 +				service_factory_pt factory = (service_factory_pt)hashMapIterator_nextValue(lp_iter);
 +				topic_publication_pt topic_pubs = (topic_publication_pt)factory->handle;
 +				array_list_pt topic_publishers = pubsub_topicPublicationGetPublisherList(topic_pubs);
 +
 +				if(topic_publishers!=NULL){
 +					for(i=0;i<arrayList_size(topic_publishers);i++){
 +						pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(topic_publishers,i);
- 						if(pubEP->endpoint !=NULL){
- 							status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint);
++						if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
++							status += pubsub_topicSubscriptionConnectPublisher(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +						}
 +					}
 +					arrayList_destroy(topic_publishers);
 +				}
 +			}
 +			hashMapIterator_destroy(lp_iter);
 +			celixThreadMutex_unlock(&admin->localPublicationsLock);
 +
 +			/* Connect also all external publishers */
 +			celixThreadMutex_lock(&admin->externalPublicationsLock);
 +			hash_map_iterator_pt extp_iter =hashMapIterator_create(admin->externalPublications);
 +			while(hashMapIterator_hasNext(extp_iter)){
 +				array_list_pt ext_pub_list = (array_list_pt)hashMapIterator_nextValue(extp_iter);
 +				if(ext_pub_list!=NULL){
 +					for(i=0;i<arrayList_size(ext_pub_list);i++){
 +						pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- 						if(pubEP->endpoint !=NULL){
- 							status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint);
++						if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
++							status += pubsub_topicSubscriptionConnectPublisher(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +						}
 +					}
 +				}
 +			}
 +			hashMapIterator_destroy(extp_iter);
 +			celixThreadMutex_unlock(&admin->externalPublicationsLock);
 +
 +
 +			pubsub_topicSubscriptionAddSubscriber(any_sub,subEP);
 +
 +			status += pubsub_topicSubscriptionStart(any_sub);
 +
 +		}
 +
 +		if (status == CELIX_SUCCESS){
 +			hashMap_put(admin->subscriptions,strdup(PUBSUB_ANY_SUB_TOPIC),any_sub);
 +			connectTopicPubSubToSerializer(admin, best_serializer, any_sub, false);
 +		}
 +
 +	}
 +
 +	celixThreadMutex_unlock(&admin->subscriptionsLock);
 +
 +	return status;
 +}
 +
 +celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
 +	celix_status_t status = CELIX_SUCCESS;
 +
- 	printf("PSA_ZMQ: Received subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",subEP->frameworkUUID,subEP->serviceID,subEP->scope, subEP->topic);
++	printf("PSA_ZMQ: Received subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",
++		   properties_get(subEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++		   subEP->serviceID,
++		   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++		   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
- 	if(strcmp(subEP->topic,PUBSUB_ANY_SUB_TOPIC)==0){
++	if(strcmp(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),PUBSUB_ANY_SUB_TOPIC)==0){
 +		return pubsubAdmin_addAnySubscription(admin,subEP);
 +	}
 +
 +	/* Check if we already know some publisher about this topic, otherwise let's put the subscription in the pending hashmap */
 +	celixThreadMutex_lock(&admin->pendingSubscriptionsLock);
 +	celixThreadMutex_lock(&admin->subscriptionsLock);
 +	celixThreadMutex_lock(&admin->localPublicationsLock);
 +	celixThreadMutex_lock(&admin->externalPublicationsLock);
 +
- 	char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic);
++	char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
 +	service_factory_pt factory = (service_factory_pt)hashMap_get(admin->localPublications,scope_topic);
 +	array_list_pt ext_pub_list = (array_list_pt)hashMap_get(admin->externalPublications,scope_topic);
 +
 +	if(factory==NULL && ext_pub_list==NULL){ //No (local or external) publishers yet for this topic
 +		pubsubAdmin_addSubscriptionToPendingList(admin,subEP);
 +	}
 +	else{
 +		int i;
 +		topic_subscription_pt subscription = hashMap_get(admin->subscriptions, scope_topic);
 +
 +		if(subscription == NULL) {
 +			pubsub_serializer_service_t *best_serializer = NULL;
 +			if( (status=pubsubAdmin_getBestSerializer(admin, subEP, &best_serializer)) == CELIX_SUCCESS){
- 				status += pubsub_topicSubscriptionCreate(admin->bundle_context,subEP->scope, subEP->topic, best_serializer, &subscription);
++				status += pubsub_topicSubscriptionCreate(admin->bundle_context, (char*) properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC), best_serializer, &subscription);
 +			}
 +			else{
- 				printf("PSA_ZMQ: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",subEP->topic);
++				printf("PSA_ZMQ: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",
++					   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +				celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +				arrayList_add(admin->noSerializerSubscriptions,subEP);
 +				celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +			}
 +
 +			if (status==CELIX_SUCCESS){
 +
 +				/* Try to connect internal publishers */
 +				if(factory!=NULL){
 +					topic_publication_pt topic_pubs = (topic_publication_pt)factory->handle;
 +					array_list_pt topic_publishers = pubsub_topicPublicationGetPublisherList(topic_pubs);
 +
 +					if(topic_publishers!=NULL){
 +						for(i=0;i<arrayList_size(topic_publishers);i++){
 +							pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(topic_publishers,i);
- 							if(pubEP->endpoint !=NULL){
- 								status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint);
++							if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
++								status += pubsub_topicSubscriptionConnectPublisher(subscription,(char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +							}
 +						}
 +						arrayList_destroy(topic_publishers);
 +					}
 +
 +				}
 +
 +				/* Look also for external publishers */
 +				if(ext_pub_list!=NULL){
 +					for(i=0;i<arrayList_size(ext_pub_list);i++){
 +						pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- 						if(pubEP->endpoint !=NULL){
- 							status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint);
++						if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
++							status += pubsub_topicSubscriptionConnectPublisher(subscription,(char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +						}
 +					}
 +				}
 +
 +				pubsub_topicSubscriptionAddSubscriber(subscription,subEP);
 +
 +				status += pubsub_topicSubscriptionStart(subscription);
 +
 +			}
 +
 +			if(status==CELIX_SUCCESS){
 +
 +				hashMap_put(admin->subscriptions,strdup(scope_topic),subscription);
 +
 +				connectTopicPubSubToSerializer(admin, best_serializer, subscription, false);
 +			}
 +		}
 +
 +		if (status == CELIX_SUCCESS){
 +			pubsub_topicIncreaseNrSubscribers(subscription);
 +		}
 +	}
 +
 +	free(scope_topic);
 +	celixThreadMutex_unlock(&admin->externalPublicationsLock);
 +	celixThreadMutex_unlock(&admin->localPublicationsLock);
 +	celixThreadMutex_unlock(&admin->subscriptionsLock);
 +	celixThreadMutex_unlock(&admin->pendingSubscriptionsLock);
 +
 +	return status;
 +
 +}
 +
 +celix_status_t pubsubAdmin_removeSubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
 +	celix_status_t status = CELIX_SUCCESS;
 +
- 	printf("PSA_ZMQ: Removing subscription [FWUUID=%s bundleID=%ld topic=%s]\n",subEP->frameworkUUID,subEP->serviceID,subEP->topic);
++	printf("PSA_ZMQ: Removing subscription [FWUUID=%s bundleID=%ld topic=%s]\n",
++		   properties_get(subEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++		   subEP->serviceID,
++		   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
- 	char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic);
++	char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
 +	celixThreadMutex_lock(&admin->subscriptionsLock);
 +	topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic);
 +	if(sub!=NULL){
 +		pubsub_topicDecreaseNrSubscribers(sub);
 +		if(pubsub_topicGetNrSubscribers(sub) == 0) {
 +			status = pubsub_topicSubscriptionRemoveSubscriber(sub,subEP);
 +		}
 +	}
 +	celixThreadMutex_unlock(&admin->subscriptionsLock);
 +
 +	if(sub==NULL){
 +		/* Maybe the endpoint was pending */
 +		celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +		if(!arrayList_removeElement(admin->noSerializerSubscriptions, subEP)){
 +			status = CELIX_ILLEGAL_STATE;
 +		}
 +		celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +	}
 +
 +	free(scope_topic);
 +
 +
 +
 +	return status;
 +
 +}
 +
 +celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin, pubsub_endpoint_pt pubEP) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
- 	printf("PSA_ZMQ: Received publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n", pubEP->frameworkUUID, pubEP->serviceID, pubEP->scope, pubEP->topic);
++	printf("PSA_ZMQ: Received publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",
++		   properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++		   pubEP->serviceID,
++		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
 +	const char* fwUUID = NULL;
 +
 +	bundleContext_getProperty(admin->bundle_context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &fwUUID);
 +	if (fwUUID == NULL) {
 +		printf("PSA_ZMQ: Cannot retrieve fwUUID.\n");
 +		return CELIX_INVALID_BUNDLE_CONTEXT;
 +	}
 +
- 	char *scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic);
++	char *scope_topic = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
- 	if ((strcmp(pubEP->frameworkUUID, fwUUID) == 0) && (pubEP->endpoint == NULL)) {
++	if ((strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID), fwUUID) == 0) &&
++			(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) == NULL)) {
 +
 +		celixThreadMutex_lock(&admin->localPublicationsLock);
 +
 +		service_factory_pt factory = (service_factory_pt) hashMap_get(admin->localPublications, scope_topic);
 +
 +		if (factory == NULL) {
 +			topic_publication_pt pub = NULL;
 +			pubsub_serializer_service_t *best_serializer = NULL;
 +			if( (status=pubsubAdmin_getBestSerializer(admin, pubEP, &best_serializer)) == CELIX_SUCCESS){
 +				status = pubsub_topicPublicationCreate(admin->bundle_context, pubEP, best_serializer, admin->ipAddress, admin->basePort, admin->maxPort, &pub);
 +			}
 +			else{
- 				printf("PSA_ZMQ: Cannot find a serializer for publishing topic %s. Adding it to pending list.\n", pubEP->topic);
++				printf("PSA_ZMQ: Cannot find a serializer for publishing topic %s. Adding it to pending list.\n",
++					   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +				celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +				arrayList_add(admin->noSerializerPublications,pubEP);
 +				celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +			}
 +
 +			if (status == CELIX_SUCCESS) {
 +				status = pubsub_topicPublicationStart(admin->bundle_context, pub, &factory);
 +				if (status == CELIX_SUCCESS && factory != NULL) {
 +					hashMap_put(admin->localPublications, strdup(scope_topic), factory);
 +					connectTopicPubSubToSerializer(admin, best_serializer, pub, true);
 +				}
 +			} else {
- 				printf("PSA_ZMQ: Cannot create a topicPublication for scope=%s, topic=%s (bundle %ld).\n", pubEP->scope, pubEP->topic, pubEP->serviceID);
++				printf("PSA_ZMQ: Cannot create a topicPublication for scope=%s, topic=%s (bundle %ld).\n",
++					   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++					   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++					   pubEP->serviceID);
 +			}
 +		} else {
 +			//just add the new EP to the list
 +			topic_publication_pt pub = (topic_publication_pt) factory->handle;
 +			pubsub_topicPublicationAddPublisherEP(pub, pubEP);
 +		}
 +
 +		celixThreadMutex_unlock(&admin->localPublicationsLock);
 +	}
 +	else{
 +
 +		celixThreadMutex_lock(&admin->externalPublicationsLock);
 +		array_list_pt ext_pub_list = (array_list_pt) hashMap_get(admin->externalPublications, scope_topic);
 +		if (ext_pub_list == NULL) {
 +			arrayList_create(&ext_pub_list);
 +			hashMap_put(admin->externalPublications, strdup(scope_topic), ext_pub_list);
 +		}
 +
 +		arrayList_add(ext_pub_list, pubEP);
 +
 +		celixThreadMutex_unlock(&admin->externalPublicationsLock);
 +	}
 +
 +	/* Re-evaluate the pending subscriptions */
 +	celixThreadMutex_lock(&admin->pendingSubscriptionsLock);
 +
 +	hash_map_entry_pt pendingSub = hashMap_getEntry(admin->pendingSubscriptions, scope_topic);
 +	if (pendingSub != NULL) { //There were pending subscription for the just published topic. Let's connect them.
 +		char* topic = (char*) hashMapEntry_getKey(pendingSub);
 +		array_list_pt pendingSubList = (array_list_pt) hashMapEntry_getValue(pendingSub);
 +		int i;
 +		for (i = 0; i < arrayList_size(pendingSubList); i++) {
 +			pubsub_endpoint_pt subEP = (pubsub_endpoint_pt) arrayList_get(pendingSubList, i);
 +			pubsubAdmin_addSubscription(admin, subEP);
 +		}
 +		hashMap_remove(admin->pendingSubscriptions, scope_topic);
 +		arrayList_clear(pendingSubList);
 +		arrayList_destroy(pendingSubList);
 +		free(topic);
 +	}
 +
 +	celixThreadMutex_unlock(&admin->pendingSubscriptionsLock);
 +
 +	/* Connect the new publisher to the subscription for his topic, if there is any */
 +	celixThreadMutex_lock(&admin->subscriptionsLock);
 +
 +	topic_subscription_pt sub = (topic_subscription_pt) hashMap_get(admin->subscriptions, scope_topic);
- 	if (sub != NULL && pubEP->endpoint != NULL) {
- 		pubsub_topicSubscriptionAddConnectPublisherToPendingList(sub, pubEP->endpoint);
++	if (sub != NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) != NULL) {
++		pubsub_topicSubscriptionAddConnectPublisherToPendingList(sub, (char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +	}
 +
 +	/* And check also for ANY subscription */
 +	topic_subscription_pt any_sub = (topic_subscription_pt) hashMap_get(admin->subscriptions, PUBSUB_ANY_SUB_TOPIC);
- 	if (any_sub != NULL && pubEP->endpoint != NULL) {
- 		pubsub_topicSubscriptionAddConnectPublisherToPendingList(any_sub, pubEP->endpoint);
++	if (any_sub != NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) != NULL) {
++		pubsub_topicSubscriptionAddConnectPublisherToPendingList(any_sub, (char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +	}
 +
 +	free(scope_topic);
 +
 +	celixThreadMutex_unlock(&admin->subscriptionsLock);
 +
 +	return status;
 +
 +}
 +
 +celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoint_pt pubEP){
 +	celix_status_t status = CELIX_SUCCESS;
 +	int count = 0;
 +
- 	printf("PSA_ZMQ: Removing publication [FWUUID=%s bundleID=%ld topic=%s]\n",pubEP->frameworkUUID,pubEP->serviceID,pubEP->topic);
++	printf("PSA_ZMQ: Removing publication [FWUUID=%s bundleID=%ld topic=%s]\n",
++		   properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++		   pubEP->serviceID,
++		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
 +	const char* fwUUID = NULL;
 +
 +	bundleContext_getProperty(admin->bundle_context,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID);
 +	if(fwUUID==NULL){
 +		printf("PSA_ZMQ: Cannot retrieve fwUUID.\n");
 +		return CELIX_INVALID_BUNDLE_CONTEXT;
 +	}
- 	char *scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic);
++	char *scope_topic = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
- 	if(strcmp(pubEP->frameworkUUID,fwUUID)==0){
++	if(strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),fwUUID)==0){
 +
 +		celixThreadMutex_lock(&admin->localPublicationsLock);
 +		service_factory_pt factory = (service_factory_pt)hashMap_get(admin->localPublications,scope_topic);
 +		if(factory!=NULL){
 +			topic_publication_pt pub = (topic_publication_pt)factory->handle;
 +			pubsub_topicPublicationRemovePublisherEP(pub,pubEP);
 +		}
 +		celixThreadMutex_unlock(&admin->localPublicationsLock);
 +
 +		if(factory==NULL){
 +			/* Maybe the endpoint was pending */
 +			celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +			if(!arrayList_removeElement(admin->noSerializerPublications, pubEP)){
 +				status = CELIX_ILLEGAL_STATE;
 +			}
 +			celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +		}
 +	}
 +	else{
 +
 +		celixThreadMutex_lock(&admin->externalPublicationsLock);
 +		array_list_pt ext_pub_list = (array_list_pt)hashMap_get(admin->externalPublications,scope_topic);
 +		if(ext_pub_list!=NULL){
 +			int i;
 +			bool found = false;
 +			for(i=0;!found && i<arrayList_size(ext_pub_list);i++){
 +				pubsub_endpoint_pt p  = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
 +				found = pubsubEndpoint_equals(pubEP,p);
 +				if (found){
 +					arrayList_remove(ext_pub_list,i);
 +				}
 +			}
 +			// Check if there are more publishers on the same endpoint (happens when 1 celix-instance with multiple bundles publish in same topic)
 +			for(i=0; i<arrayList_size(ext_pub_list);i++) {
 +				pubsub_endpoint_pt p  = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- 				if (strcmp(pubEP->endpoint,p->endpoint) == 0) {
++				if (strcmp(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL),properties_get(p->endpoint_props, PUBSUB_ENDPOINT_URL)) == 0) {
 +					count++;
 +				}
 +			}
 +
 +			if(arrayList_size(ext_pub_list)==0){
 +				hash_map_entry_pt entry = hashMap_getEntry(admin->externalPublications,scope_topic);
 +				char* topic = (char*)hashMapEntry_getKey(entry);
 +				array_list_pt list = (array_list_pt)hashMapEntry_getValue(entry);
 +				hashMap_remove(admin->externalPublications,topic);
 +				arrayList_destroy(list);
 +				free(topic);
 +			}
 +		}
 +
 +		celixThreadMutex_unlock(&admin->externalPublicationsLock);
 +	}
 +
 +	/* Check if this publisher was connected to one of our subscribers*/
 +	celixThreadMutex_lock(&admin->subscriptionsLock);
 +
 +	topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic);
- 	if(sub!=NULL && pubEP->endpoint!=NULL && count == 0){
- 		pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub,pubEP->endpoint);
++	if(sub!=NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL && count == 0){
++		pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub,(char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +	}
 +
 +	/* And check also for ANY subscription */
 +	topic_subscription_pt any_sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,PUBSUB_ANY_SUB_TOPIC);
- 	if(any_sub!=NULL && pubEP->endpoint!=NULL && count == 0){
- 		pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(any_sub,pubEP->endpoint);
++	if(any_sub!=NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL && count == 0){
++		pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(any_sub,(char*)properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +	}
 +
 +	free(scope_topic);
 +	celixThreadMutex_unlock(&admin->subscriptionsLock);
 +
 +	return status;
 +
 +}
 +
 +celix_status_t pubsubAdmin_closeAllPublications(pubsub_admin_pt admin, char *scope, char* topic){
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	printf("PSA_ZMQ: Closing all publications\n");
 +
 +	celixThreadMutex_lock(&admin->localPublicationsLock);
 +	char *scope_topic = createScopeTopicKey(scope, topic);
 +	hash_map_entry_pt pubsvc_entry = (hash_map_entry_pt)hashMap_getEntry(admin->localPublications,scope_topic);
 +	if(pubsvc_entry!=NULL){
 +		char* key = (char*)hashMapEntry_getKey(pubsvc_entry);
 +		service_factory_pt factory= (service_factory_pt)hashMapEntry_getValue(pubsvc_entry);
 +		topic_publication_pt pub = (topic_publication_pt)factory->handle;
 +		status += pubsub_topicPublicationStop(pub);
 +		disconnectTopicPubSubFromSerializer(admin, pub, true);
 +		status += pubsub_topicPublicationDestroy(pub);
 +		hashMap_remove(admin->localPublications,scope_topic);
 +		free(key);
 +		free(factory);
 +	}
 +	free(scope_topic);
 +	celixThreadMutex_unlock(&admin->localPublicationsLock);
 +
 +	return status;
 +
 +}
 +
 +celix_status_t pubsubAdmin_closeAllSubscriptions(pubsub_admin_pt admin,char* scope,char* topic){
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	printf("PSA_ZMQ: Closing all subscriptions\n");
 +
 +	celixThreadMutex_lock(&admin->subscriptionsLock);
 +	char *scope_topic = createScopeTopicKey(scope, topic);
 +	hash_map_entry_pt sub_entry = (hash_map_entry_pt)hashMap_getEntry(admin->subscriptions,scope_topic);
 +	if(sub_entry!=NULL){
 +		char* topic = (char*)hashMapEntry_getKey(sub_entry);
 +
 +		topic_subscription_pt ts = (topic_subscription_pt)hashMapEntry_getValue(sub_entry);
 +		status += pubsub_topicSubscriptionStop(ts);
 +		disconnectTopicPubSubFromSerializer(admin, ts, false);
 +		status += pubsub_topicSubscriptionDestroy(ts);
 +		hashMap_remove(admin->subscriptions,scope_topic);
 +		free(topic);
 +
 +	}
 +	free(scope_topic);
 +	celixThreadMutex_unlock(&admin->subscriptionsLock);
 +
 +	return status;
 +
 +}
 +
 +
 +#ifndef ANDROID
 +static celix_status_t pubsubAdmin_getIpAdress(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
 +
 +static celix_status_t pubsubAdmin_addSubscriptionToPendingList(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
 +	celix_status_t status = CELIX_SUCCESS;
- 	char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic);
++	char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +	array_list_pt pendingListPerTopic = hashMap_get(admin->pendingSubscriptions,scope_topic);
 +	if(pendingListPerTopic==NULL){
 +		arrayList_create(&pendingListPerTopic);
 +		hashMap_put(admin->pendingSubscriptions,strdup(scope_topic),pendingListPerTopic);
 +	}
 +	arrayList_add(pendingListPerTopic,subEP);
 +	free(scope_topic);
 +	return status;
 +}
 +
 +celix_status_t pubsubAdmin_serializerAdded(void * handle, service_reference_pt reference, void * service){
 +	/* Assumption: serializers are all available at startup.
 +	 * If a new (possibly better) serializer is installed and started, already created topic_publications/subscriptions will not be destroyed and recreated */
 +
 +	celix_status_t status = CELIX_SUCCESS;
 +	int i=0;
 +
 +	const char *serType = NULL;
 +	serviceReference_getProperty(reference, PUBSUB_SERIALIZER_TYPE_KEY,&serType);
 +	if(serType == NULL){
 +		printf("Serializer serviceReference %p has no pubsub_serializer.type property specified\n",reference);
 +		return CELIX_SERVICE_EXCEPTION;
 +	}
 +
 +	pubsub_admin_pt admin = (pubsub_admin_pt)handle;
 +	celixThreadMutex_lock(&admin->serializerListLock);
 +	arrayList_add(admin->serializerList, reference);
 +	celixThreadMutex_unlock(&admin->serializerListLock);
 +
 +	/* Now let's re-evaluate the pending */
 +	celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +
 +	for(i=0;i<arrayList_size(admin->noSerializerSubscriptions);i++){
 +		pubsub_endpoint_pt ep = (pubsub_endpoint_pt)arrayList_get(admin->noSerializerSubscriptions,i);
 +		pubsub_serializer_service_t *best_serializer = NULL;
 +		pubsubAdmin_getBestSerializer(admin, ep, &best_serializer);
 +		if(best_serializer != NULL){ /* Finally we have a valid serializer! */
 +			pubsubAdmin_addSubscription(admin, ep);
 +		}
 +	}
 +
 +	for(i=0;i<arrayList_size(admin->noSerializerPublications);i++){
 +		pubsub_endpoint_pt ep = (pubsub_endpoint_pt)arrayList_get(admin->noSerializerPublications,i);
 +		pubsub_serializer_service_t *best_serializer = NULL;
 +		pubsubAdmin_getBestSerializer(admin, ep, &best_serializer);
 +		if(best_serializer != NULL){ /* Finally we have a valid serializer! */
 +			pubsubAdmin_addPublication(admin, ep);
 +		}
 +	}
 +
 +	celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +
 +	printf("PSA_ZMQ: %s serializer added\n",serType);
 +
 +	return status;
 +}
 +
 +celix_status_t pubsubAdmin_serializerRemoved(void * handle, service_reference_pt reference, void * service){
 +
 +	pubsub_admin_pt admin = (pubsub_admin_pt)handle;
 +	int i=0, j=0;
 +	const char *serType = NULL;
 +
 +	serviceReference_getProperty(reference, PUBSUB_SERIALIZER_TYPE_KEY,&serType);
 +	if(serType == NULL){
 +		printf("Serializer serviceReference %p has no pubsub_serializer.type property specified\n",reference);
 +		return CELIX_SERVICE_EXCEPTION;
 +	}
 +
 +	celixThreadMutex_lock(&admin->serializerListLock);
 +	/* Remove the serializer from the list */
 +	arrayList_removeElement(admin->serializerList, reference);
 +	celixThreadMutex_unlock(&admin->serializerListLock);
 +
 +
 +	celixThreadMutex_lock(&admin->usedSerializersLock);
 +	array_list_pt topicPubList = (array_list_pt)hashMap_remove(admin->topicPublicationsPerSerializer, service);
 +	array_list_pt topicSubList = (array_list_pt)hashMap_remove(admin->topicSubscriptionsPerSerializer, service);
 +	celixThreadMutex_unlock(&admin->usedSerializersLock);
 +
 +	/* Now destroy the topicPublications, but first put back the pubsub_endpoints back to the noSerializer pending list */
 +	if(topicPubList!=NULL){
 +		for(i=0;i<arrayList_size(topicPubList);i++){
 +			topic_publication_pt topicPub = (topic_publication_pt)arrayList_get(topicPubList,i);
 +			/* Stop the topic publication */
 +			pubsub_topicPublicationStop(topicPub);
 +			/* Get the endpoints that are going to be orphan */
 +			array_list_pt pubList = pubsub_topicPublicationGetPublisherList(topicPub);
 +			for(j=0;j<arrayList_size(pubList);j++){
 +				pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pubList,j);
 +				/* Remove the publication */
 +				pubsubAdmin_removePublication(admin, pubEP);
 +				/* Reset the endpoint field, so that will be recreated from scratch when a new serializer will be found */
- 				if(pubEP->endpoint!=NULL){
- 					free(pubEP->endpoint);
- 					pubEP->endpoint = NULL;
++				if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL){
++					properties_unset(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL);
 +				}
 +				/* Add the orphan endpoint to the noSerializer pending list */
 +				celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +				arrayList_add(admin->noSerializerPublications,pubEP);
 +				celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +			}
 +			arrayList_destroy(pubList);
 +
 +			/* Cleanup also the localPublications hashmap*/
 +			celixThreadMutex_lock(&admin->localPublicationsLock);
 +			hash_map_iterator_pt iter = hashMapIterator_create(admin->localPublications);
 +			char *key = NULL;
 +			service_factory_pt factory = NULL;
 +			while(hashMapIterator_hasNext(iter)){
 +				hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
 +				factory = (service_factory_pt)hashMapEntry_getValue(entry);
 +				topic_publication_pt pub = (topic_publication_pt)factory->handle;
 +				if(pub==topicPub){
 +					key = (char*)hashMapEntry_getKey(entry);
 +					break;
 +				}
 +			}
 +			hashMapIterator_destroy(iter);
 +			if(key!=NULL){
 +				hashMap_remove(admin->localPublications, key);
 +				free(factory);
 +				free(key);
 +			}
 +			celixThreadMutex_unlock(&admin->localPublicationsLock);
 +
 +			/* Finally destroy the topicPublication */
 +			pubsub_topicPublicationDestroy(topicPub);
 +		}
 +		arrayList_destroy(topicPubList);
 +	}
 +
 +	/* Now destroy the topicSubscriptions, but first put back the pubsub_endpoints back to the noSerializer pending list */
 +	if(topicSubList!=NULL){
 +		for(i=0;i<arrayList_size(topicSubList);i++){
 +			topic_subscription_pt topicSub = (topic_subscription_pt)arrayList_get(topicSubList,i);
 +			/* Stop the topic subscription */
 +			pubsub_topicSubscriptionStop(topicSub);
 +			/* Get the endpoints that are going to be orphan */
 +			array_list_pt subList = pubsub_topicSubscriptionGetSubscribersList(topicSub);
 +			for(j=0;j<arrayList_size(subList);j++){
 +				pubsub_endpoint_pt subEP = (pubsub_endpoint_pt)arrayList_get(subList,j);
 +				/* Remove the subscription */
 +				pubsubAdmin_removeSubscription(admin, subEP);
 +				/* Reset the endpoint field, so that will be recreated from scratch when a new serializer will be found */
- 				if(subEP->endpoint!=NULL){
- 					free(subEP->endpoint);
- 					subEP->endpoint = NULL;
++				if(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL){
++					properties_unset(subEP->endpoint_props, PUBSUB_ENDPOINT_URL);
 +				}
 +				/* Add the orphan endpoint to the noSerializer pending list */
 +				celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +				arrayList_add(admin->noSerializerSubscriptions,subEP);
 +				celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +			}
 +
 +			/* Cleanup also the subscriptions hashmap*/
 +			celixThreadMutex_lock(&admin->subscriptionsLock);
 +			hash_map_iterator_pt iter = hashMapIterator_create(admin->subscriptions);
 +			char *key = NULL;
 +			while(hashMapIterator_hasNext(iter)){
 +				hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
 +				topic_subscription_pt sub = (topic_subscription_pt)hashMapEntry_getValue(entry);
 +				if(sub==topicSub){
 +					key = (char*)hashMapEntry_getKey(entry);
 +					break;
 +				}
 +			}
 +			hashMapIterator_destroy(iter);
 +			if(key!=NULL){
 +				hashMap_remove(admin->subscriptions, key);
 +				free(key);
 +			}
 +			celixThreadMutex_unlock(&admin->subscriptionsLock);
 +
 +			/* Finally destroy the topicSubscription */
 +			pubsub_topicSubscriptionDestroy(topicSub);
 +		}
 +		arrayList_destroy(topicSubList);
 +	}
 +
 +
 +
 +	printf("PSA_ZMQ: %s serializer removed\n",serType);
 +
 +
 +	return CELIX_SUCCESS;
 +}
 +
 +celix_status_t pubsubAdmin_matchEndpoint(pubsub_admin_pt admin, pubsub_endpoint_pt endpoint, double* score){
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	celixThreadMutex_lock(&admin->serializerListLock);
 +	status = pubsub_admin_match(endpoint->topic_props,PUBSUB_ADMIN_TYPE,admin->serializerList,score);
 +	celixThreadMutex_unlock(&admin->serializerListLock);
 +
 +	return status;
 +}
 +
 +/* This one recall the same logic as in the match function */
 +static celix_status_t pubsubAdmin_getBestSerializer(pubsub_admin_pt admin,pubsub_endpoint_pt ep, pubsub_serializer_service_t **serSvc){
 +
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	celixThreadMutex_lock(&admin->serializerListLock);
 +	status = pubsub_admin_get_best_serializer(ep->topic_props, admin->serializerList, serSvc);
 +	celixThreadMutex_unlock(&admin->serializerListLock);
 +
 +	return status;
 +
 +}
 +
 +static void connectTopicPubSubToSerializer(pubsub_admin_pt admin,pubsub_serializer_service_t *serializer,void *topicPubSub,bool isPublication){
 +
 +	celixThreadMutex_lock(&admin->usedSerializersLock);
 +
 +	hash_map_pt map = isPublication?admin->topicPublicationsPerSerializer:admin->topicSubscriptionsPerSerializer;
 +	array_list_pt list = (array_list_pt)hashMap_get(map,serializer);
 +	if(list==NULL){
 +		arrayList_create(&list);
 +		hashMap_put(map,serializer,list);
 +	}
 +	arrayList_add(list,topicPubSub);
 +
 +	celixThreadMutex_unlock(&admin->usedSerializersLock);
 +
 +}
 +
 +static void disconnectTopicPubSubFromSerializer(pubsub_admin_pt admin,void *topicPubSub,bool isPublication){
 +
 +	celixThreadMutex_lock(&admin->usedSerializersLock);
 +
 +	hash_map_pt map = isPublication?admin->topicPublicationsPerSerializer:admin->topicSubscriptionsPerSerializer;
 +	hash_map_iterator_pt iter = hashMapIterator_create(map);
 +	while(hashMapIterator_hasNext(iter)){
 +		array_list_pt list = (array_list_pt)hashMapIterator_nextValue(iter);
 +		if(arrayList_removeElement(list, topicPubSub)){ //Found it!
 +			break;
 +		}
 +	}
 +	hashMapIterator_destroy(iter);
 +
 +	celixThreadMutex_unlock(&admin->usedSerializersLock);
 +
 +}

http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_admin_zmq/src/topic_publication.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_admin_zmq/src/topic_publication.c
index b612605,0000000..873cec2
mode 100644,000000..100644
--- a/pubsub/pubsub_admin_zmq/src/topic_publication.c
+++ b/pubsub/pubsub_admin_zmq/src/topic_publication.c
@@@ -1,630 -1,0 +1,631 @@@
 +/**
 + *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 <czmq.h>
 +/* The following undefs prevent the collision between:
 + * - sys/syslog.h (which is included within czmq)
 + * - celix/dfi/dfi_log_util.h
 + */
 +#undef LOG_DEBUG
 +#undef LOG_WARNING
 +#undef LOG_INFO
 +#undef LOG_WARNING
 +
 +#include <stdlib.h>
 +#include <string.h>
 +#include <unistd.h>
 +
 +#include "array_list.h"
 +#include "celixbool.h"
 +#include "service_registration.h"
 +#include "utils.h"
 +#include "service_factory.h"
 +#include "version.h"
 +
 +#include "pubsub_common.h"
 +#include "pubsub_utils.h"
 +#include "pubsub/publisher.h"
 +
 +#include "topic_publication.h"
 +
 +#include "pubsub_serializer.h"
 +
 +#ifdef BUILD_WITH_ZMQ_SECURITY
 +	#include "zmq_crypto.h"
 +
 +	#define MAX_CERT_PATH_LENGTH 512
 +#endif
 +
 +#define EP_ADDRESS_LEN		32
 +#define ZMQ_BIND_MAX_RETRY	5
 +
 +#define FIRST_SEND_DELAY	2
 +
 +struct topic_publication {
 +	zsock_t* zmq_socket;
 +	celix_thread_mutex_t socket_lock; //Protects zmq_socket access
 +	zcert_t * zmq_cert;
 +	char* endpoint;
 +	service_registration_pt svcFactoryReg;
 +	array_list_pt pub_ep_list; //List<pubsub_endpoint>
 +	hash_map_pt boundServices; //<bundle_pt,bound_service>
 +	pubsub_serializer_service_t *serializer;
 +	celix_thread_mutex_t tp_lock;
 +};
 +
 +typedef struct publish_bundle_bound_service {
 +	topic_publication_pt parent;
 +	pubsub_publisher_t service;
 +	bundle_pt bundle;
 +	char *topic;
 +	hash_map_pt msgTypes;
 +	unsigned short getCount;
 +	celix_thread_mutex_t mp_lock; //Protects publish_bundle_bound_service data structure
 +	bool mp_send_in_progress;
 +	array_list_pt mp_parts;
 +}* publish_bundle_bound_service_pt;
 +
 +/* Note: correct locking order is
 + * 1. tp_lock
 + * 2. mp_lock
 + * 3. socket_lock
 + *
 + * tp_lock and socket_lock are independent.
 + */
 +
 +typedef struct pubsub_msg{
 +	pubsub_msg_header_pt header;
 +	char* payload;
 +	int payloadSize;
 +}* pubsub_msg_pt;
 +
 +static unsigned int rand_range(unsigned int min, unsigned int max);
 +
 +static celix_status_t pubsub_topicPublicationGetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service);
 +static celix_status_t pubsub_topicPublicationUngetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service);
 +
 +static publish_bundle_bound_service_pt pubsub_createPublishBundleBoundService(topic_publication_pt tp,bundle_pt bundle);
 +static void pubsub_destroyPublishBundleBoundService(publish_bundle_bound_service_pt boundSvc);
 +
 +static int pubsub_topicPublicationSend(void* handle,unsigned int msgTypeId, const void *msg);
 +static int pubsub_topicPublicationSendMultipart(void *handle, unsigned int msgTypeId, const void *inMsg, int flags);
 +static int pubsub_localMsgTypeIdForUUID(void* handle, const char* msgType, unsigned int* msgTypeId);
 +
 +static void delay_first_send_for_late_joiners(void);
 +
 +celix_status_t pubsub_topicPublicationCreate(bundle_context_pt bundle_context, pubsub_endpoint_pt pubEP, pubsub_serializer_service_t *best_serializer, char* bindIP, unsigned int basePort, unsigned int maxPort, topic_publication_pt *out){
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +#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* socket = zsock_new (ZMQ_PUB);
 +	if(socket==NULL){
 +		#ifdef BUILD_WITH_ZMQ_SECURITY
 +			if (pubEP->is_secure){
 +				zcert_destroy(&pub_cert);
 +			}
 +		#endif
 +
 +        perror("Error for zmq_socket");
 +		return CELIX_SERVICE_EXCEPTION;
 +	}
 +#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
 +
 +	int rv = -1, retry=0;
 +	char* ep = malloc(EP_ADDRESS_LEN);
 +    char bindAddress[EP_ADDRESS_LEN];
 +
 +	while(rv==-1 && retry<ZMQ_BIND_MAX_RETRY){
 +		/* Randomized part due to same bundle publishing on different topics */
 +		unsigned int port = rand_range(basePort,maxPort);
 +		memset(ep,0,EP_ADDRESS_LEN);
 +        memset(bindAddress, 0, EP_ADDRESS_LEN);
 +
 +		snprintf(ep,EP_ADDRESS_LEN,"tcp://%s:%u",bindIP,port);
-         snprintf(bindAddress, EP_ADDRESS_LEN, "tcp://0.0.0.0:%u", port); //NOTE using a different bind addres than endpoint address
++        snprintf(bindAddress, EP_ADDRESS_LEN, "tcp://0.0.0.0:%u", port); //NOTE using a different bind address than endpoint address
 +		rv = zsock_bind (socket, "%s", bindAddress);
 +        if (rv == -1) {
 +            perror("Error for zmq_bind");
 +        }
 +		retry++;
 +	}
 +
 +	if(rv == -1){
 +		free(ep);
 +		return CELIX_SERVICE_EXCEPTION;
 +	}
 +
 +	/* ZMQ stuffs are all fine at this point. Let's create and initialize the structure */
 +
 +	topic_publication_pt pub = calloc(1,sizeof(*pub));
 +
 +	arrayList_create(&(pub->pub_ep_list));
 +	pub->boundServices = hashMap_create(NULL,NULL,NULL,NULL);
 +	celixThreadMutex_create(&(pub->tp_lock),NULL);
 +
 +	pub->endpoint = ep;
 +	pub->zmq_socket = socket;
 +	pub->serializer = best_serializer;
 +
 +	celixThreadMutex_create(&(pub->socket_lock),NULL);
 +
 +#ifdef BUILD_WITH_ZMQ_SECURITY
 +	if (pubEP->is_secure){
 +		pub->zmq_cert = pub_cert;
 +	}
 +#endif
 +
 +	pubsub_topicPublicationAddPublisherEP(pub,pubEP);
 +
 +	*out = pub;
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_topicPublicationDestroy(topic_publication_pt pub){
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	celixThreadMutex_lock(&(pub->tp_lock));
 +
 +	free(pub->endpoint);
 +	arrayList_destroy(pub->pub_ep_list);
 +
 +	hash_map_iterator_pt iter = hashMapIterator_create(pub->boundServices);
 +	while(hashMapIterator_hasNext(iter)){
 +		publish_bundle_bound_service_pt bound = hashMapIterator_nextValue(iter);
 +		pubsub_destroyPublishBundleBoundService(bound);
 +	}
 +	hashMapIterator_destroy(iter);
 +	hashMap_destroy(pub->boundServices,false,false);
 +
 +	pub->svcFactoryReg = NULL;
 +	pub->serializer = NULL;
 +#ifdef BUILD_WITH_ZMQ_SECURITY
 +	zcert_destroy(&(pub->zmq_cert));
 +#endif
 +
 +	celixThreadMutex_unlock(&(pub->tp_lock));
 +
 +	celixThreadMutex_destroy(&(pub->tp_lock));
 +
 +	celixThreadMutex_lock(&(pub->socket_lock));
 +	zsock_destroy(&(pub->zmq_socket));
 +	celixThreadMutex_unlock(&(pub->socket_lock));
 +
 +	celixThreadMutex_destroy(&(pub->socket_lock));
 +
 +	free(pub);
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_topicPublicationStart(bundle_context_pt bundle_context,topic_publication_pt pub,service_factory_pt* svcFactory){
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	/* Let's register the new service */
 +
 +	pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pub->pub_ep_list,0);
 +
 +	if(pubEP!=NULL){
 +		service_factory_pt factory = calloc(1, sizeof(*factory));
 +		factory->handle = pub;
 +		factory->getService = pubsub_topicPublicationGetService;
 +		factory->ungetService = pubsub_topicPublicationUngetService;
 +
 +		properties_pt props = properties_create();
- 		properties_set(props,PUBSUB_PUBLISHER_TOPIC,pubEP->topic);
- 		properties_set(props,PUBSUB_PUBLISHER_SCOPE,pubEP->scope);
++		properties_set(props,PUBSUB_PUBLISHER_TOPIC,properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
++		properties_set(props,PUBSUB_PUBLISHER_SCOPE,properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE));
 +		properties_set(props,"service.version", PUBSUB_PUBLISHER_SERVICE_VERSION);
 +
 +		status = bundleContext_registerServiceFactory(bundle_context,PUBSUB_PUBLISHER_SERVICE_NAME,factory,props,&(pub->svcFactoryReg));
 +
 +		if(status != CELIX_SUCCESS){
 +			properties_destroy(props);
- 			printf("PSA_ZMQ_PSA_ZMQ_TP: Cannot register ServiceFactory for topic %s (bundle %ld).\n",pubEP->topic,pubEP->serviceID);
++			printf("PSA_ZMQ_PSA_ZMQ_TP: Cannot register ServiceFactory for topic %s (bundle %ld).\n",
++				   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),pubEP->serviceID);
 +		}
 +		else{
 +			*svcFactory = factory;
 +		}
 +	}
 +	else{
 +		printf("PSA_ZMQ_PSA_ZMQ_TP: Cannot find pubsub_endpoint after adding it...Should never happen!\n");
 +		status = CELIX_SERVICE_EXCEPTION;
 +	}
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_topicPublicationStop(topic_publication_pt pub){
 +	return serviceRegistration_unregister(pub->svcFactoryReg);
 +}
 +
 +celix_status_t pubsub_topicPublicationAddPublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep){
 +
 +	celixThreadMutex_lock(&(pub->tp_lock));
- 	ep->endpoint = strdup(pub->endpoint);
++    pubsubEndpoint_setField(ep, PUBSUB_ENDPOINT_URL, pub->endpoint);
 +	arrayList_add(pub->pub_ep_list,ep);
 +	celixThreadMutex_unlock(&(pub->tp_lock));
 +
 +	return CELIX_SUCCESS;
 +}
 +
 +celix_status_t pubsub_topicPublicationRemovePublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep){
 +
 +	celixThreadMutex_lock(&(pub->tp_lock));
 +	for (int i = 0; i < arrayList_size(pub->pub_ep_list); i++) {
 +	        pubsub_endpoint_pt e = arrayList_get(pub->pub_ep_list, i);
 +	        if(pubsubEndpoint_equals(ep, e)) {
 +	            arrayList_removeElement(pub->pub_ep_list,ep);
 +	            break;
 +	        }
 +	}
 +	celixThreadMutex_unlock(&(pub->tp_lock));
 +
 +	return CELIX_SUCCESS;
 +}
 +
 +array_list_pt pubsub_topicPublicationGetPublisherList(topic_publication_pt pub){
 +	array_list_pt list = NULL;
 +	celixThreadMutex_lock(&(pub->tp_lock));
 +	list = arrayList_clone(pub->pub_ep_list);
 +	celixThreadMutex_unlock(&(pub->tp_lock));
 +	return list;
 +}
 +
 +
 +static celix_status_t pubsub_topicPublicationGetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service) {
 +	celix_status_t  status = CELIX_SUCCESS;
 +
 +	topic_publication_pt publish = (topic_publication_pt)handle;
 +
 +	celixThreadMutex_lock(&(publish->tp_lock));
 +
 +	publish_bundle_bound_service_pt bound = (publish_bundle_bound_service_pt)hashMap_get(publish->boundServices,bundle);
 +	if(bound==NULL){
 +		bound = pubsub_createPublishBundleBoundService(publish,bundle);
 +		if(bound!=NULL){
 +			hashMap_put(publish->boundServices,bundle,bound);
 +		}
 +	}
 +	else{
 +		bound->getCount++;
 +	}
 +
 +	*service = &bound->service;
 +
 +	celixThreadMutex_unlock(&(publish->tp_lock));
 +
 +	return status;
 +}
 +
 +static celix_status_t pubsub_topicPublicationUngetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service)  {
 +
 +	topic_publication_pt publish = (topic_publication_pt)handle;
 +
 +	celixThreadMutex_lock(&(publish->tp_lock));
 +
 +	publish_bundle_bound_service_pt bound = (publish_bundle_bound_service_pt)hashMap_get(publish->boundServices,bundle);
 +	if(bound!=NULL){
 +
 +		bound->getCount--;
 +		if(bound->getCount==0){
 +			pubsub_destroyPublishBundleBoundService(bound);
 +			hashMap_remove(publish->boundServices,bundle);
 +		}
 +
 +	}
 +	else{
 +		long bundleId = -1;
 +		bundle_getBundleId(bundle,&bundleId);
 +		printf("PSA_ZMQ_TP: Unexpected ungetService call for bundle %ld.\n", bundleId);
 +	}
 +
 +	/* service should be never used for unget, so let's set the pointer to NULL */
 +	*service = NULL;
 +
 +	celixThreadMutex_unlock(&(publish->tp_lock));
 +
 +	return CELIX_SUCCESS;
 +}
 +
 +static bool send_pubsub_msg(zsock_t* zmq_socket, pubsub_msg_pt msg, bool last){
 +
 +	bool ret = true;
 +
 +	zframe_t* headerMsg = zframe_new(msg->header, sizeof(struct pubsub_msg_header));
 +	if (headerMsg == NULL) ret=false;
 +	zframe_t* payloadMsg = zframe_new(msg->payload, msg->payloadSize);
 +	if (payloadMsg == NULL) ret=false;
 +
 +	delay_first_send_for_late_joiners();
 +
 +	if( zframe_send(&headerMsg,zmq_socket, ZFRAME_MORE) == -1) ret=false;
 +
 +	if(!last){
 +		if( zframe_send(&payloadMsg,zmq_socket, ZFRAME_MORE) == -1) ret=false;
 +	}
 +	else{
 +		if( zframe_send(&payloadMsg,zmq_socket, 0) == -1) ret=false;
 +	}
 +
 +	if (!ret){
 +		zframe_destroy(&headerMsg);
 +		zframe_destroy(&payloadMsg);
 +	}
 +
 +	free(msg->header);
 +	free(msg->payload);
 +	free(msg);
 +
 +	return ret;
 +
 +}
 +
 +static bool send_pubsub_mp_msg(zsock_t* zmq_socket, array_list_pt mp_msg_parts){
 +
 +	bool ret = true;
 +
 +	unsigned int i = 0;
 +	unsigned int mp_num = arrayList_size(mp_msg_parts);
 +	for(;i<mp_num;i++){
 +		ret = ret && send_pubsub_msg(zmq_socket, (pubsub_msg_pt)arrayList_get(mp_msg_parts,i), (i==mp_num-1));
 +	}
 +	arrayList_clear(mp_msg_parts);
 +
 +	return ret;
 +
 +}
 +
 +static int pubsub_topicPublicationSend(void* handle, unsigned int msgTypeId, const void *msg) {
 +
 +	return pubsub_topicPublicationSendMultipart(handle,msgTypeId,msg, PUBSUB_PUBLISHER_FIRST_MSG | PUBSUB_PUBLISHER_LAST_MSG);
 +
 +}
 +
 +static int pubsub_topicPublicationSendMultipart(void *handle, unsigned int msgTypeId, const void *inMsg, int flags){
 +
 +	int status = 0;
 +
 +	publish_bundle_bound_service_pt bound = (publish_bundle_bound_service_pt) handle;
 +
 +	celixThreadMutex_lock(&(bound->parent->tp_lock));
 +	celixThreadMutex_lock(&(bound->mp_lock));
 +	if( (flags & PUBSUB_PUBLISHER_FIRST_MSG) && !(flags & PUBSUB_PUBLISHER_LAST_MSG) && bound->mp_send_in_progress){ //means a real mp_msg
 +		printf("PSA_ZMQ_TP: Multipart send already in progress. Cannot process a new one.\n");
 +		celixThreadMutex_unlock(&(bound->mp_lock));
 +		celixThreadMutex_unlock(&(bound->parent->tp_lock));
 +		return -3;
 +	}
 +
 +	pubsub_msg_serializer_t* msgSer = (pubsub_msg_serializer_t*)hashMap_get(bound->msgTypes, (void*)(uintptr_t)msgTypeId);
 +
 +	if (msgSer!= NULL) {
 +		int major=0, minor=0;
 +
 +		pubsub_msg_header_pt msg_hdr = calloc(1,sizeof(struct pubsub_msg_header));
 +		strncpy(msg_hdr->topic,bound->topic,MAX_TOPIC_LEN-1);
 +		msg_hdr->type = msgTypeId;
 +
 +		if (msgSer->msgVersion != NULL){
 +			version_getMajor(msgSer->msgVersion, &major);
 +			version_getMinor(msgSer->msgVersion, &minor);
 +			msg_hdr->major = major;
 +			msg_hdr->minor = minor;
 +		}
 +
 +		void *serializedOutput = NULL;
 +		size_t serializedOutputLen = 0;
 +		msgSer->serialize(msgSer,inMsg,&serializedOutput, &serializedOutputLen);
 +
 +		pubsub_msg_pt msg = calloc(1,sizeof(struct pubsub_msg));
 +		msg->header = msg_hdr;
 +		msg->payload = (char*)serializedOutput;
 +		msg->payloadSize = serializedOutputLen;
 +		bool snd = true;
 +
 +		switch(flags){
 +		case PUBSUB_PUBLISHER_FIRST_MSG:
 +			bound->mp_send_in_progress = true;
 +			arrayList_add(bound->mp_parts,msg);
 +			break;
 +		case PUBSUB_PUBLISHER_PART_MSG:
 +			if(!bound->mp_send_in_progress){
 +				printf("PSA_ZMQ_TP: ERROR: received msg part without the first part.\n");
 +				status = -4;
 +			}
 +			else{
 +				arrayList_add(bound->mp_parts,msg);
 +			}
 +			break;
 +		case PUBSUB_PUBLISHER_LAST_MSG:
 +			if(!bound->mp_send_in_progress){
 +				printf("PSA_ZMQ_TP: ERROR: received end msg without the first part.\n");
 +				status = -4;
 +			}
 +			else{
 +				arrayList_add(bound->mp_parts,msg);
 +				snd = send_pubsub_mp_msg(bound->parent->zmq_socket,bound->mp_parts);
 +				bound->mp_send_in_progress = false;
 +			}
 +			break;
 +		case PUBSUB_PUBLISHER_FIRST_MSG | PUBSUB_PUBLISHER_LAST_MSG:	//Normal send case
 +			snd = send_pubsub_msg(bound->parent->zmq_socket,msg,true);
 +			break;
 +		default:
 +			printf("PSA_ZMQ_TP: ERROR: Invalid MP flags combination\n");
 +			status = -4;
 +			break;
 +		}
 +
 +		if(status==-4){
 +			free(msg);
 +		}
 +
 +		if(!snd){
 +			printf("PSA_ZMQ_TP: Failed to send %s message %u.\n",flags == (PUBSUB_PUBLISHER_FIRST_MSG | PUBSUB_PUBLISHER_LAST_MSG) ? "single" : "multipart", msgTypeId);
 +		}
 +
 +	} else {
 +        printf("PSA_ZMQ_TP: No msg serializer available for msg type id %d\n", msgTypeId);
 +		status=-1;
 +	}
 +
 +	celixThreadMutex_unlock(&(bound->mp_lock));
 +	celixThreadMutex_unlock(&(bound->parent->tp_lock));
 +
 +	return status;
 +
 +}
 +
 +static int pubsub_localMsgTypeIdForUUID(void* handle, const char* msgType, unsigned int* msgTypeId){
 +	*msgTypeId = utils_stringHash(msgType);
 +	return 0;
 +}
 +
 +
 +static unsigned int rand_range(unsigned int min, unsigned int max){
 +
 +	double scaled = (double)(((double)random())/((double)RAND_MAX));
 +	return (max-min+1)*scaled + min;
 +
 +}
 +
 +static publish_bundle_bound_service_pt pubsub_createPublishBundleBoundService(topic_publication_pt tp,bundle_pt bundle){
 +
 +	//PRECOND lock on tp->lock
 +
 +	publish_bundle_bound_service_pt bound = calloc(1, sizeof(*bound));
 +
 +	if (bound != NULL) {
 +
 +		bound->parent = tp;
 +		bound->bundle = bundle;
 +		bound->getCount = 1;
 +		bound->mp_send_in_progress = false;
 +		celixThreadMutex_create(&bound->mp_lock,NULL);
 +
 +		if(tp->serializer != NULL){
 +			tp->serializer->createSerializerMap(tp->serializer->handle,bundle,&bound->msgTypes);
 +		}
 +
 +		arrayList_create(&bound->mp_parts);
 +
 +		pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(bound->parent->pub_ep_list,0);
- 		bound->topic=strdup(pubEP->topic);
++		bound->topic=strdup(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
 +		bound->service.handle = bound;
 +		bound->service.localMsgTypeIdForMsgType = pubsub_localMsgTypeIdForUUID;
 +		bound->service.send = pubsub_topicPublicationSend;
 +		bound->service.sendMultipart = pubsub_topicPublicationSendMultipart;
 +
 +	}
 +
 +	return bound;
 +}
 +
 +static void pubsub_destroyPublishBundleBoundService(publish_bundle_bound_service_pt boundSvc){
 +
 +	//PRECOND lock on tp->lock
 +
 +	celixThreadMutex_lock(&boundSvc->mp_lock);
 +
 +
 +	if(boundSvc->parent->serializer != NULL && boundSvc->msgTypes != NULL){
 +		boundSvc->parent->serializer->destroySerializerMap(boundSvc->parent->serializer->handle, boundSvc->msgTypes);
 +	}
 +
 +	if(boundSvc->mp_parts!=NULL){
 +		arrayList_destroy(boundSvc->mp_parts);
 +	}
 +
 +	if(boundSvc->topic!=NULL){
 +		free(boundSvc->topic);
 +	}
 +
 +	celixThreadMutex_unlock(&boundSvc->mp_lock);
 +	celixThreadMutex_destroy(&boundSvc->mp_lock);
 +
 +	free(boundSvc);
 +
 +}
 +
 +static void delay_first_send_for_late_joiners(){
 +
 +	static bool firstSend = true;
 +
 +	if(firstSend){
 +		printf("PSA_ZMQ_TP: Delaying first send for late joiners...\n");
 +		sleep(FIRST_SEND_DELAY);
 +		firstSend = false;
 +	}
 +}

http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_discovery/src/etcd_watcher.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_discovery/src/etcd_watcher.c
index 3c3a5a8,0000000..726269a
mode 100644,000000..100644
--- a/pubsub/pubsub_discovery/src/etcd_watcher.c
+++ b/pubsub/pubsub_discovery/src/etcd_watcher.c
@@@ -1,290 -1,0 +1,344 @@@
 +/**
 + *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 <stdbool.h>
 +#include <stdlib.h>
 +#include <unistd.h>
 +#include <string.h>
++#include <jansson.h>
 +
 +#include "celix_log.h"
 +#include "constants.h"
 +
 +#include "etcd.h"
 +#include "etcd_watcher.h"
 +
 +#include "pubsub_discovery.h"
 +#include "pubsub_discovery_impl.h"
 +
 +
 +
 +#define MAX_ROOTNODE_LENGTH             128
 +#define MAX_LOCALNODE_LENGTH            4096
 +#define MAX_FIELD_LENGTH                128
 +
 +#define CFG_ETCD_ROOT_PATH              "PUBSUB_DISCOVERY_ETCD_ROOT_PATH"
 +#define DEFAULT_ETCD_ROOTPATH           "pubsub/discovery"
 +
 +#define CFG_ETCD_SERVER_IP              "PUBSUB_DISCOVERY_ETCD_SERVER_IP"
 +#define DEFAULT_ETCD_SERVER_IP          "127.0.0.1"
 +
 +#define CFG_ETCD_SERVER_PORT            "PUBSUB_DISCOVERY_ETCD_SERVER_PORT"
 +#define DEFAULT_ETCD_SERVER_PORT        2379
 +
 +// be careful - this should be higher than the curl timeout
 +#define CFG_ETCD_TTL                    "DISCOVERY_ETCD_TTL"
 +#define DEFAULT_ETCD_TTL                30
 +
 +
 +struct etcd_watcher {
 +	pubsub_discovery_pt pubsub_discovery;
 +
 +	celix_thread_mutex_t watcherLock;
 +	celix_thread_t watcherThread;
 +
 +	char *scope;
 +	char *topic;
 +	volatile bool running;
 +};
 +
 +struct etcd_writer {
 +	pubsub_discovery_pt pubsub_discovery;
 +	celix_thread_mutex_t localPubsLock;
 +	array_list_pt localPubs;
 +	volatile bool running;
 +	celix_thread_t writerThread;
 +};
 +
 +
 +// note that the rootNode shouldn't have a leading slash
 +static celix_status_t etcdWatcher_getTopicRootPath(bundle_context_pt context, const char *scope, const char *topic, char* rootNode, int rootNodeLen) {
 +	celix_status_t status = CELIX_SUCCESS;
 +	const char* rootPath = NULL;
 +
 +	if (((bundleContext_getProperty(context, CFG_ETCD_ROOT_PATH, &rootPath)) != CELIX_SUCCESS) || (!rootPath)) {
 +		snprintf(rootNode, rootNodeLen, "%s/%s/%s", DEFAULT_ETCD_ROOTPATH, scope, topic);
 +	} else {
 +		snprintf(rootNode, rootNodeLen, "%s/%s/%s", rootPath, scope, topic);
 +	}
 +
 +	return status;
 +}
 +
 +static celix_status_t etcdWatcher_getRootPath(bundle_context_pt context, char* rootNode) {
 +	celix_status_t status = CELIX_SUCCESS;
 +	const char* rootPath = NULL;
 +
 +	if (((bundleContext_getProperty(context, CFG_ETCD_ROOT_PATH, &rootPath)) != CELIX_SUCCESS) || (!rootPath)) {
 +		strncpy(rootNode, DEFAULT_ETCD_ROOTPATH, MAX_ROOTNODE_LENGTH);
 +	} else {
 +		strncpy(rootNode, rootPath, MAX_ROOTNODE_LENGTH);
 +	}
 +
 +	return status;
 +}
 +
 +
 +static void add_node(const char *key, const char *value, void* arg) {
 +	pubsub_discovery_pt ps_discovery = (pubsub_discovery_pt) arg;
 +	pubsub_endpoint_pt pubEP = NULL;
 +	celix_status_t status = etcdWatcher_getPublisherEndpointFromKey(ps_discovery, key, value, &pubEP);
 +	if(!status && pubEP) {
 +		pubsub_discovery_addNode(ps_discovery, pubEP);
 +	}
 +}
 +
 +static celix_status_t etcdWatcher_addAlreadyExistingPublishers(pubsub_discovery_pt ps_discovery, const char *rootPath, long long * highestModified) {
 +	celix_status_t status = CELIX_SUCCESS;
 +	if(etcd_get_directory(rootPath, add_node, ps_discovery, highestModified)) {
 +		status = CELIX_ILLEGAL_ARGUMENT;
 +	}
 +	return status;
 +}
 +
 +// gets everything from provided key
 +celix_status_t etcdWatcher_getPublisherEndpointFromKey(pubsub_discovery_pt pubsub_discovery, const char* etcdKey, const char* etcdValue, pubsub_endpoint_pt* pubEP) {
 +
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	char rootPath[MAX_ROOTNODE_LENGTH];
 +	char *expr = NULL;
 +	char scope[MAX_FIELD_LENGTH];
 +	char topic[MAX_FIELD_LENGTH];
 +	char fwUUID[MAX_FIELD_LENGTH];
 +	char serviceId[MAX_FIELD_LENGTH];
 +
 +	memset(rootPath,0,MAX_ROOTNODE_LENGTH);
 +	memset(topic,0,MAX_FIELD_LENGTH);
 +	memset(fwUUID,0,MAX_FIELD_LENGTH);
 +	memset(serviceId,0,MAX_FIELD_LENGTH);
 +
 +	etcdWatcher_getRootPath(pubsub_discovery->context, rootPath);
 +
 +	asprintf(&expr, "/%s/%%[^/]/%%[^/]/%%[^/]/%%[^/].*", rootPath);
 +	if(expr) {
 +		int foundItems = sscanf(etcdKey, expr, scope, topic, fwUUID, serviceId);
 +		free(expr);
 +		if (foundItems != 4) { // Could happen when a directory is removed, just don't process this.
 +			status = CELIX_ILLEGAL_STATE;
 +		}
 +		else{
- 			status = pubsubEndpoint_create(fwUUID,scope,topic,strtol(serviceId,NULL,10),etcdValue,NULL,pubEP);
++
++			// etcdValue contains the json formatted string
++			json_error_t error;
++			json_t* jsonRoot = json_loads(etcdValue, JSON_DECODE_ANY, &error);
++
++			const char* endpoint_serializer = NULL;
++			const char* endpoint_admin_type = NULL;
++			const char* endpoint_url = NULL;
++			const char* endpoint_type = NULL;
++
++			if (json_is_object(jsonRoot)){
++
++				void *iter = json_object_iter(jsonRoot);
++
++				const char *key;
++				json_t *value;
++
++				while (iter) {
++					key = json_object_iter_key(iter);
++					value = json_object_iter_value(iter);
++
++					if (strcmp(key, PUBSUB_ENDPOINT_SERIALIZER) == 0) {
++						endpoint_serializer = json_string_value(value);
++					} else if (strcmp(key, PUBSUB_ENDPOINT_ADMIN_TYPE) == 0) {
++						endpoint_admin_type = json_string_value(value);
++					} else if (strcmp(key, PUBSUB_ENDPOINT_URL) == 0) {
++						endpoint_url = json_string_value(value);
++					} else if (strcmp(key, PUBSUB_ENDPOINT_TYPE) == 0) {
++						endpoint_type = json_string_value(value);
++					}
++
++					iter = json_object_iter_next(jsonRoot, iter);
++				}
++
++				if (endpoint_url == NULL) {
++					printf("EW: No endpoint found in json object!\n");
++					endpoint_url = etcdValue;
++				}
++
++			} else {
++				endpoint_url = etcdValue;
++			}
++
++			status = pubsubEndpoint_create(fwUUID,scope,topic,strtol(serviceId,NULL,10),endpoint_url,NULL,pubEP);
++
++            if (status == CELIX_SUCCESS) {
++                status += pubsubEndpoint_setField(*pubEP, PUBSUB_ENDPOINT_SERIALIZER, endpoint_serializer);
++                status += pubsubEndpoint_setField(*pubEP, PUBSUB_ENDPOINT_ADMIN_TYPE, endpoint_admin_type);
++                status += pubsubEndpoint_setField(*pubEP, PUBSUB_ENDPOINT_TYPE, endpoint_type);
++            }
++
++			if (jsonRoot != NULL) {
++				json_decref(jsonRoot);
++			}
 +		}
 +	}
 +	return status;
 +}
 +
 +/*
 + * performs (blocking) etcd_watch calls to check for
 + * changing discovery endpoint information within etcd.
 + */
 +static void* etcdWatcher_run(void* data) {
 +	etcd_watcher_pt watcher = (etcd_watcher_pt) data;
 +	time_t timeBeforeWatch = time(NULL);
 +	char rootPath[MAX_ROOTNODE_LENGTH];
 +	long long highestModified = 0;
 +
 +	pubsub_discovery_pt ps_discovery = watcher->pubsub_discovery;
 +	bundle_context_pt context = ps_discovery->context;
 +
 +	memset(rootPath, 0, MAX_ROOTNODE_LENGTH);
 +
 +	//TODO: add topic to etcd key
 +	etcdWatcher_getTopicRootPath(context, watcher->scope, watcher->topic, rootPath, MAX_ROOTNODE_LENGTH);
 +	etcdWatcher_addAlreadyExistingPublishers(ps_discovery, rootPath, &highestModified);
 +
 +	while ((celixThreadMutex_lock(&watcher->watcherLock) == CELIX_SUCCESS) && watcher->running) {
 +
 +		char *rkey = NULL;
 +		char *value = NULL;
 +		char *preValue = NULL;
 +		char *action = NULL;
 +		long long modIndex;
 +
 +		celixThreadMutex_unlock(&watcher->watcherLock);
 +
 +		if (etcd_watch(rootPath, highestModified + 1, &action, &preValue, &value, &rkey, &modIndex) == 0 && action != NULL) {
 +			pubsub_endpoint_pt pubEP = NULL;
 +			if ((strcmp(action, "set") == 0) || (strcmp(action, "create") == 0)) {
 +				if (etcdWatcher_getPublisherEndpointFromKey(ps_discovery, rkey, value, &pubEP) == CELIX_SUCCESS) {
 +					pubsub_discovery_addNode(ps_discovery, pubEP);
 +				}
 +			} else if (strcmp(action, "delete") == 0) {
 +				if (etcdWatcher_getPublisherEndpointFromKey(ps_discovery, rkey, preValue, &pubEP) == CELIX_SUCCESS) {
 +					pubsub_discovery_removeNode(ps_discovery, pubEP);
 +				}
 +			} else if (strcmp(action, "expire") == 0) {
 +				if (etcdWatcher_getPublisherEndpointFromKey(ps_discovery, rkey, preValue, &pubEP) == CELIX_SUCCESS) {
 +					pubsub_discovery_removeNode(ps_discovery, pubEP);
 +				}
 +			} else if (strcmp(action, "update") == 0) {
 +				if (etcdWatcher_getPublisherEndpointFromKey(ps_discovery, rkey, value, &pubEP) == CELIX_SUCCESS) {
 +					pubsub_discovery_addNode(ps_discovery, pubEP);
 +				}
 +			} else {
 +				fw_log(logger, OSGI_FRAMEWORK_LOG_INFO, "Unexpected action: %s", action);
 +			}
 +			highestModified = modIndex;
 +		} else if (time(NULL) - timeBeforeWatch <= (DEFAULT_ETCD_TTL / 4)) {
 +			sleep(DEFAULT_ETCD_TTL / 4);
 +		}
 +
 +		FREE_MEM(action);
 +		FREE_MEM(value);
 +		FREE_MEM(preValue);
 +		FREE_MEM(rkey);
 +
 +		/* prevent busy waiting, in case etcd_watch returns false */
 +
 +
 +		if (time(NULL) - timeBeforeWatch > (DEFAULT_ETCD_TTL / 4)) {
 +			timeBeforeWatch = time(NULL);
 +		}
 +
 +	}
 +
 +	if (watcher->running == false) {
 +		celixThreadMutex_unlock(&watcher->watcherLock);
 +	}
 +
 +	return NULL;
 +}
 +
 +celix_status_t etcdWatcher_create(pubsub_discovery_pt pubsub_discovery, bundle_context_pt context, const char *scope, const char *topic, etcd_watcher_pt *watcher) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +
 +	if (pubsub_discovery == NULL) {
 +		return CELIX_BUNDLE_EXCEPTION;
 +	}
 +
 +	(*watcher) = calloc(1, sizeof(struct etcd_watcher));
 +
 +	if(*watcher == NULL){
 +		return CELIX_ENOMEM;
 +	}
 +
 +	(*watcher)->pubsub_discovery = pubsub_discovery;
 +	(*watcher)->scope = strdup(scope);
 +	(*watcher)->topic = strdup(topic);
 +
 +
 +	celixThreadMutex_create(&(*watcher)->watcherLock, NULL);
 +
 +	celixThreadMutex_lock(&(*watcher)->watcherLock);
 +
 +	status = celixThread_create(&(*watcher)->watcherThread, NULL, etcdWatcher_run, *watcher);
 +	if (status == CELIX_SUCCESS) {
 +		(*watcher)->running = true;
 +	}
 +
 +	celixThreadMutex_unlock(&(*watcher)->watcherLock);
 +
 +
 +	return status;
 +}
 +
 +celix_status_t etcdWatcher_destroy(etcd_watcher_pt watcher) {
 +
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	char rootPath[MAX_ROOTNODE_LENGTH];
 +	etcdWatcher_getTopicRootPath(watcher->pubsub_discovery->context, watcher->scope, watcher->topic, rootPath, MAX_ROOTNODE_LENGTH);
 +	celixThreadMutex_destroy(&(watcher->watcherLock));
 +
 +	free(watcher->scope);
 +	free(watcher->topic);
 +	free(watcher);
 +
 +	return status;
 +}
 +
 +celix_status_t etcdWatcher_stop(etcd_watcher_pt watcher){
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	celixThreadMutex_lock(&(watcher->watcherLock));
 +	watcher->running = false;
 +	celixThreadMutex_unlock(&(watcher->watcherLock));
 +
 +	celixThread_join(watcher->watcherThread, NULL);
 +
 +	return status;
 +
 +}
 +
 +

http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_discovery/src/etcd_writer.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_discovery/src/etcd_writer.c
index 1c423f3,0000000..e820e50
mode 100644,000000..100644
--- a/pubsub/pubsub_discovery/src/etcd_writer.c
+++ b/pubsub/pubsub_discovery/src/etcd_writer.c
@@@ -1,189 -1,0 +1,221 @@@
 +/**
 + *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 <stdbool.h>
 +#include <stdlib.h>
 +#include <unistd.h>
 +#include <string.h>
++#include <jansson.h>
 +
 +#include "celix_log.h"
 +#include "constants.h"
 +
 +#include "etcd.h"
 +#include "etcd_writer.h"
 +
 +#include "pubsub_discovery.h"
 +#include "pubsub_discovery_impl.h"
 +
 +#define MAX_ROOTNODE_LENGTH		128
 +
 +#define CFG_ETCD_ROOT_PATH		"PUBSUB_DISCOVERY_ETCD_ROOT_PATH"
 +#define DEFAULT_ETCD_ROOTPATH	"pubsub/discovery"
 +
 +#define CFG_ETCD_SERVER_IP		"PUBSUB_DISCOVERY_ETCD_SERVER_IP"
 +#define DEFAULT_ETCD_SERVER_IP	"127.0.0.1"
 +
 +#define CFG_ETCD_SERVER_PORT	"PUBSUB_DISCOVERY_ETCD_SERVER_PORT"
 +#define DEFAULT_ETCD_SERVER_PORT 2379
 +
 +// be careful - this should be higher than the curl timeout
 +#define CFG_ETCD_TTL   "DISCOVERY_ETCD_TTL"
 +#define DEFAULT_ETCD_TTL 30
 +
 +struct etcd_writer {
 +	pubsub_discovery_pt pubsub_discovery;
 +	celix_thread_mutex_t localPubsLock;
 +	array_list_pt localPubs;
 +	volatile bool running;
 +	celix_thread_t writerThread;
 +};
 +
 +
 +static const char* etcdWriter_getRootPath(bundle_context_pt context);
 +static void* etcdWriter_run(void* data);
 +
 +
 +etcd_writer_pt etcdWriter_create(pubsub_discovery_pt disc) {
 +	etcd_writer_pt writer = calloc(1, sizeof(*writer));
 +	if(writer) {
 +		celixThreadMutex_create(&writer->localPubsLock, NULL);
 +		arrayList_create(&writer->localPubs);
 +		writer->pubsub_discovery = disc;
 +		writer->running = true;
 +		celixThread_create(&writer->writerThread, NULL, etcdWriter_run, writer);
 +	}
 +	return writer;
 +}
 +
 +void etcdWriter_destroy(etcd_writer_pt writer) {
 +	char dir[MAX_ROOTNODE_LENGTH];
 +	const char *rootPath = etcdWriter_getRootPath(writer->pubsub_discovery->context);
 +
 +	writer->running = false;
 +	celixThread_join(writer->writerThread, NULL);
 +
 +	celixThreadMutex_lock(&writer->localPubsLock);
 +	for(int i = 0; i < arrayList_size(writer->localPubs); i++) {
 +		pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(writer->localPubs,i);
 +		memset(dir,0,MAX_ROOTNODE_LENGTH);
- 		snprintf(dir,MAX_ROOTNODE_LENGTH,"%s/%s/%s/%s",rootPath,pubEP->scope,pubEP->topic,pubEP->frameworkUUID);
++		snprintf(dir,MAX_ROOTNODE_LENGTH,"%s/%s/%s/%s",
++				 rootPath,
++				 properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++				 properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++				 properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID));
++
 +		etcd_del(dir);
 +		pubsubEndpoint_destroy(pubEP);
 +	}
 +	arrayList_destroy(writer->localPubs);
 +
 +	celixThreadMutex_unlock(&writer->localPubsLock);
 +	celixThreadMutex_destroy(&(writer->localPubsLock));
 +
 +	free(writer);
 +}
 +
 +celix_status_t etcdWriter_addPublisherEndpoint(etcd_writer_pt writer, pubsub_endpoint_pt pubEP, bool storeEP){
 +	celix_status_t status = CELIX_BUNDLE_EXCEPTION;
 +
 +	if(storeEP){
 +		const char *fwUUID = NULL;
 +		bundleContext_getProperty(writer->pubsub_discovery->context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &fwUUID);
- 		if(fwUUID && strcmp(pubEP->frameworkUUID, fwUUID) == 0) {
++		if(fwUUID && strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID), fwUUID) == 0) {
 +			celixThreadMutex_lock(&writer->localPubsLock);
 +			pubsub_endpoint_pt p = NULL;
 +			pubsubEndpoint_clone(pubEP, &p);
 +			arrayList_add(writer->localPubs,p);
 +			celixThreadMutex_unlock(&writer->localPubsLock);
 +		}
 +	}
 +
 +	char *key;
 +
 +	const char* ttlStr = NULL;
 +	int ttl = 0;
 +
 +	// determine ttl
 +	if ((bundleContext_getProperty(writer->pubsub_discovery->context, CFG_ETCD_TTL, &ttlStr) != CELIX_SUCCESS) || !ttlStr) {
 +		ttl = DEFAULT_ETCD_TTL;
 +	} else {
 +		char* endptr = NULL;
 +		errno = 0;
 +		ttl = strtol(ttlStr, &endptr, 10);
 +		if (*endptr || errno != 0) {
 +			ttl = DEFAULT_ETCD_TTL;
 +		}
 +	}
 +
 +	const char *rootPath = etcdWriter_getRootPath(writer->pubsub_discovery->context);
 +
- 	asprintf(&key,"%s/%s/%s/%s/%ld",rootPath,pubEP->scope,pubEP->topic,pubEP->frameworkUUID,pubEP->serviceID);
- 
- 	if(!etcd_set(key,pubEP->endpoint,ttl,false)){
++	asprintf(&key,"%s/%s/%s/%s/%ld",
++			 rootPath,
++			 properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++			 properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++			 properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++			 pubEP->serviceID);
++
++    char serviceID [sizeof(pubEP->serviceID)];
++    snprintf(serviceID, sizeof(pubEP->serviceID), "%ld", pubEP->serviceID);
++	json_t* jsonEndpoint = json_pack("{s:s,s:s,s:s,s:s,s:s,s:s,s:s}",
++									 PUBSUB_ENDPOINT_SERVICE_ID, serviceID,
++									 PUBSUB_ENDPOINT_SERIALIZER, "serializer.json", //TODO: Serializer not (yet) stored in endpoint
++									 PUBSUB_ENDPOINT_ADMIN_TYPE, "zmq", //TODO: PSA type not (yet) stored in endpoint
++									 PUBSUB_ENDPOINT_URL, properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL),
++									 PUBSUB_ENDPOINT_TYPE, "publisher", //TODO: Check if necessary
++									 PUBSUB_ENDPOINT_TOPIC, properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++									 PUBSUB_ENDPOINT_SCOPE, properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE)
++	);
++	char* jsonEndpointStr = json_dumps(jsonEndpoint, JSON_COMPACT);
++
++	if (!etcd_set(key,jsonEndpointStr,ttl,false)) {
 +		status = CELIX_ILLEGAL_ARGUMENT;
 +	}
 +	FREE_MEM(key);
++	FREE_MEM(jsonEndpointStr);
++	json_decref(jsonEndpoint);
++
 +	return status;
 +}
 +
 +celix_status_t etcdWriter_deletePublisherEndpoint(etcd_writer_pt writer, pubsub_endpoint_pt pubEP) {
 +	celix_status_t status = CELIX_SUCCESS;
 +	char *key = NULL;
 +
 +	const char *rootPath = etcdWriter_getRootPath(writer->pubsub_discovery->context);
 +
- 	asprintf(&key, "%s/%s/%s/%s/%ld", rootPath, pubEP->scope, pubEP->topic, pubEP->frameworkUUID, pubEP->serviceID);
++	asprintf(&key, "%s/%s/%s/%s/%ld",
++			 rootPath,
++			 properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++			 properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++			 properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++			 pubEP->serviceID);
 +
 +	celixThreadMutex_lock(&writer->localPubsLock);
 +	for (unsigned int i = 0; i < arrayList_size(writer->localPubs); i++) {
 +		pubsub_endpoint_pt ep = arrayList_get(writer->localPubs, i);
 +		if (pubsubEndpoint_equals(ep, pubEP)) {
 +			arrayList_remove(writer->localPubs, i);
 +			pubsubEndpoint_destroy(ep);
 +			break;
 +		}
 +	}
 +	celixThreadMutex_unlock(&writer->localPubsLock);
 +
 +	if (etcd_del(key)) {
 +		printf("Failed to remove key %s from ETCD\n",key);
 +		status = CELIX_ILLEGAL_ARGUMENT;
 +	}
 +	FREE_MEM(key);
 +	return status;
 +}
 +
 +static void* etcdWriter_run(void* data) {
 +	etcd_writer_pt writer = (etcd_writer_pt)data;
 +	while(writer->running) {
 +		celixThreadMutex_lock(&writer->localPubsLock);
 +		for(int i=0; i < arrayList_size(writer->localPubs); i++) {
 +			etcdWriter_addPublisherEndpoint(writer,(pubsub_endpoint_pt)arrayList_get(writer->localPubs,i),false);
 +		}
 +		celixThreadMutex_unlock(&writer->localPubsLock);
 +		sleep(DEFAULT_ETCD_TTL / 2);
 +	}
 +
 +	return NULL;
 +}
 +
 +static const char* etcdWriter_getRootPath(bundle_context_pt context) {
 +	const char* rootPath = NULL;
 +	bundleContext_getProperty(context, CFG_ETCD_ROOT_PATH, &rootPath);
 +	if(rootPath == NULL) {
 +		rootPath = DEFAULT_ETCD_ROOTPATH;
 +	}
 +	return rootPath;
 +}
 +


[2/4] celix git commit: Merge branch 'endpoint-format' into develop

Posted by rl...@apache.org.
http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_discovery/src/pubsub_discovery_impl.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_discovery/src/pubsub_discovery_impl.c
index 94a8e11,0000000..e3e9704
mode 100644,000000..100644
--- a/pubsub/pubsub_discovery/src/pubsub_discovery_impl.c
+++ b/pubsub/pubsub_discovery/src/pubsub_discovery_impl.c
@@@ -1,457 -1,0 +1,460 @@@
 +/**
 + *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 <stdlib.h>
 +#include <unistd.h>
 +#include <stdbool.h>
 +#include <netdb.h>
 +#include <netinet/in.h>
 +
 +#include "constants.h"
 +#include "celix_threads.h"
 +#include "bundle_context.h"
 +#include "array_list.h"
 +#include "utils.h"
 +#include "celix_errno.h"
 +#include "filter.h"
 +#include "service_reference.h"
 +#include "service_registration.h"
 +
 +#include "publisher_endpoint_announce.h"
 +#include "etcd_common.h"
 +#include "etcd_watcher.h"
 +#include "etcd_writer.h"
 +#include "pubsub_endpoint.h"
 +#include "pubsub_discovery_impl.h"
 +
 +/* Discovery activator functions */
 +celix_status_t pubsub_discovery_create(bundle_context_pt context, pubsub_discovery_pt *ps_discovery) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	*ps_discovery = calloc(1, sizeof(**ps_discovery));
 +
 +	if (*ps_discovery == NULL) {
 +		status = CELIX_ENOMEM;
 +	}
 +	else{
 +		(*ps_discovery)->context = context;
 +		(*ps_discovery)->discoveredPubs = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
 +		(*ps_discovery)->listenerReferences = hashMap_create(serviceReference_hashCode, NULL, serviceReference_equals2, NULL);
 +		(*ps_discovery)->watchers = hashMap_create(utils_stringHash,NULL,utils_stringEquals, NULL);
 +		celixThreadMutex_create(&(*ps_discovery)->listenerReferencesMutex, NULL);
 +		celixThreadMutex_create(&(*ps_discovery)->discoveredPubsMutex, NULL);
 +		celixThreadMutex_create(&(*ps_discovery)->watchersMutex, NULL);
 +	}
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_discovery_destroy(pubsub_discovery_pt ps_discovery) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	celixThreadMutex_lock(&ps_discovery->discoveredPubsMutex);
 +
 +	hash_map_iterator_pt iter = hashMapIterator_create(ps_discovery->discoveredPubs);
 +
 +	while (hashMapIterator_hasNext(iter)) {
 +		array_list_pt pubEP_list = (array_list_pt) hashMapIterator_nextValue(iter);
 +
 +		for(int i=0; i < arrayList_size(pubEP_list); i++) {
 +			pubsubEndpoint_destroy(((pubsub_endpoint_pt)arrayList_get(pubEP_list,i)));
 +		}
 +		arrayList_destroy(pubEP_list);
 +	}
 +
 +	hashMapIterator_destroy(iter);
 +
 +	hashMap_destroy(ps_discovery->discoveredPubs, true, false);
 +	ps_discovery->discoveredPubs = NULL;
 +
 +	celixThreadMutex_unlock(&ps_discovery->discoveredPubsMutex);
 +
 +	celixThreadMutex_destroy(&ps_discovery->discoveredPubsMutex);
 +
 +
 +	celixThreadMutex_lock(&ps_discovery->listenerReferencesMutex);
 +
 +	hashMap_destroy(ps_discovery->listenerReferences, false, false);
 +	ps_discovery->listenerReferences = NULL;
 +
 +	celixThreadMutex_unlock(&ps_discovery->listenerReferencesMutex);
 +
 +	celixThreadMutex_destroy(&ps_discovery->listenerReferencesMutex);
 +
 +	free(ps_discovery);
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_discovery_start(pubsub_discovery_pt ps_discovery) {
 +    celix_status_t status = CELIX_SUCCESS;
 +    status = etcdCommon_init(ps_discovery->context);
 +    ps_discovery->writer = etcdWriter_create(ps_discovery);
 +
 +    return status;
 +}
 +
 +celix_status_t pubsub_discovery_stop(pubsub_discovery_pt ps_discovery) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    const char* fwUUID = NULL;
 +
 +    bundleContext_getProperty(ps_discovery->context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &fwUUID);
 +    if (fwUUID == NULL) {
 +        printf("PSD: Cannot retrieve fwUUID.\n");
 +        return CELIX_INVALID_BUNDLE_CONTEXT;
 +    }
 +
 +    celixThreadMutex_lock(&ps_discovery->watchersMutex);
 +
 +    hash_map_iterator_pt iter = hashMapIterator_create(ps_discovery->watchers);
 +    while (hashMapIterator_hasNext(iter)) {
 +        struct watcher_info * wi = hashMapIterator_nextValue(iter);
 +        etcdWatcher_stop(wi->watcher);
 +    }
 +    hashMapIterator_destroy(iter);
 +
 +    celixThreadMutex_lock(&ps_discovery->discoveredPubsMutex);
 +
 +    /* Unexport all publishers for the local framework, and also delete from ETCD publisher belonging to the local framework */
 +
 +    iter = hashMapIterator_create(ps_discovery->discoveredPubs);
 +    while (hashMapIterator_hasNext(iter)) {
 +        array_list_pt pubEP_list = (array_list_pt) hashMapIterator_nextValue(iter);
 +
 +        int i;
 +        for (i = 0; i < arrayList_size(pubEP_list); i++) {
 +            pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt) arrayList_get(pubEP_list, i);
-             if (strcmp(pubEP->frameworkUUID, fwUUID) == 0) {
++            if (strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID), fwUUID) == 0) {
 +                etcdWriter_deletePublisherEndpoint(ps_discovery->writer, pubEP);
 +            } else {
 +                pubsub_discovery_informPublishersListeners(ps_discovery, pubEP, false);
 +                arrayList_remove(pubEP_list, i);
 +                pubsubEndpoint_destroy(pubEP);
 +                i--;
 +            }
 +        }
 +    }
 +
 +    hashMapIterator_destroy(iter);
 +
 +    celixThreadMutex_unlock(&ps_discovery->discoveredPubsMutex);
 +    etcdWriter_destroy(ps_discovery->writer);
 +
 +    iter = hashMapIterator_create(ps_discovery->watchers);
 +    while (hashMapIterator_hasNext(iter)) {
 +        struct watcher_info * wi = hashMapIterator_nextValue(iter);
 +        etcdWatcher_destroy(wi->watcher);
 +    }
 +    hashMapIterator_destroy(iter);
 +    hashMap_destroy(ps_discovery->watchers, true, true);
 +    celixThreadMutex_unlock(&ps_discovery->watchersMutex);
 +    return status;
 +}
 +
 +/* Functions called by the etcd_watcher */
 +
 +celix_status_t pubsub_discovery_addNode(pubsub_discovery_pt pubsub_discovery, pubsub_endpoint_pt pubEP) {
 +	celix_status_t status = CELIX_SUCCESS;
 +	bool inform=false;
 +	celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
 +
- 	char *pubs_key = createScopeTopicKey(pubEP->scope, pubEP->topic);
++	char *pubs_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +	array_list_pt pubEP_list = (array_list_pt)hashMap_get(pubsub_discovery->discoveredPubs,pubs_key);
 +	if(pubEP_list==NULL){
 +		arrayList_create(&pubEP_list);
 +		arrayList_add(pubEP_list,pubEP);
 +		hashMap_put(pubsub_discovery->discoveredPubs,strdup(pubs_key),pubEP_list);
 +		inform=true;
 +	}
 +	else{
 +		int i;
 +		bool found = false;
 +		for(i=0;i<arrayList_size(pubEP_list) && !found;i++){
 +			found = pubsubEndpoint_equals(pubEP,(pubsub_endpoint_pt)arrayList_get(pubEP_list,i));
 +		}
 +		if(found){
 +			pubsubEndpoint_destroy(pubEP);
 +		}
 +		else{
 +			arrayList_add(pubEP_list,pubEP);
 +			inform=true;
 +    	}
 +	}
 +	free(pubs_key);
 +
 +	celixThreadMutex_unlock(&pubsub_discovery->discoveredPubsMutex);
 +
 +	if(inform){
 +	    status = pubsub_discovery_informPublishersListeners(pubsub_discovery,pubEP,true);
 +	}
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_discovery_removeNode(pubsub_discovery_pt pubsub_discovery, pubsub_endpoint_pt pubEP) {
 +    celix_status_t status = CELIX_SUCCESS;
 +    pubsub_endpoint_pt p = NULL;
 +    bool found = false;
 +
 +    celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
-     char *pubs_key = createScopeTopicKey(pubEP->scope, pubEP->topic);
++    char *pubs_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +    array_list_pt pubEP_list = (array_list_pt) hashMap_get(pubsub_discovery->discoveredPubs, pubs_key);
 +    free(pubs_key);
 +    if (pubEP_list == NULL) {
-         printf("PSD: Cannot find any registered publisher for topic %s. Something is not consistent.\n", pubEP->topic);
++        printf("PSD: Cannot find any registered publisher for topic %s. Something is not consistent.\n",
++			   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +        status = CELIX_ILLEGAL_STATE;
 +    } else {
 +        int i;
 +
 +        for (i = 0; !found && i < arrayList_size(pubEP_list); i++) {
 +            p = arrayList_get(pubEP_list, i);
 +            found = pubsubEndpoint_equals(pubEP, p);
 +            if (found) {
 +                arrayList_remove(pubEP_list, i);
 +                pubsubEndpoint_destroy(p);
 +            }
 +        }
 +    }
 +
 +    celixThreadMutex_unlock(&pubsub_discovery->discoveredPubsMutex);
 +    if (found) {
 +        status = pubsub_discovery_informPublishersListeners(pubsub_discovery, pubEP, false);
 +    }
 +    pubsubEndpoint_destroy(pubEP);
 +
 +    return status;
 +}
 +
 +/* Callback to the pubsub_topology_manager */
 +celix_status_t pubsub_discovery_informPublishersListeners(pubsub_discovery_pt pubsub_discovery, pubsub_endpoint_pt pubEP, bool epAdded) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	// Inform listeners of new publisher endpoint
 +	celixThreadMutex_lock(&pubsub_discovery->listenerReferencesMutex);
 +
 +	if (pubsub_discovery->listenerReferences != NULL) {
 +		hash_map_iterator_pt iter = hashMapIterator_create(pubsub_discovery->listenerReferences);
 +		while (hashMapIterator_hasNext(iter)) {
 +			service_reference_pt reference = hashMapIterator_nextKey(iter);
 +
 +			publisher_endpoint_announce_pt listener = NULL;
 +
 +			bundleContext_getService(pubsub_discovery->context, reference, (void**) &listener);
 +            if (epAdded) {
 +                listener->announcePublisher(listener->handle, pubEP);
 +            } else {
 +                listener->removePublisher(listener->handle, pubEP);
 +            }
 +            bundleContext_ungetService(pubsub_discovery->context, reference, NULL);
 +		}
 +		hashMapIterator_destroy(iter);
 +	}
 +
 +	celixThreadMutex_unlock(&pubsub_discovery->listenerReferencesMutex);
 +
 +	return status;
 +}
 +
 +
 +/* Service's functions implementation */
 +celix_status_t pubsub_discovery_announcePublisher(void *handle, pubsub_endpoint_pt pubEP) {
 +	celix_status_t status = CELIX_SUCCESS;
- 	printf("pubsub_discovery_announcePublisher : %s / %s\n", pubEP->topic, pubEP->endpoint);
++	printf("pubsub_discovery_announcePublisher : %s / %s\n",
++		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +	pubsub_discovery_pt pubsub_discovery = (pubsub_discovery_pt) handle;
 +
 +	celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
 +
- 	char *pub_key = createScopeTopicKey(pubEP->scope,pubEP->topic);
++	char *pub_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +	array_list_pt pubEP_list = (array_list_pt)hashMap_get(pubsub_discovery->discoveredPubs,pub_key);
 +
 +	if(pubEP_list==NULL){
 +		arrayList_create(&pubEP_list);
 +		hashMap_put(pubsub_discovery->discoveredPubs,strdup(pub_key),pubEP_list);
 +	}
 +	free(pub_key);
 +	pubsub_endpoint_pt p = NULL;
 +	pubsubEndpoint_clone(pubEP, &p);
 +
 +	arrayList_add(pubEP_list,p);
 +
 +	status = etcdWriter_addPublisherEndpoint(pubsub_discovery->writer,p,true);
 +
 +	celixThreadMutex_unlock(&pubsub_discovery->discoveredPubsMutex);
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_discovery_removePublisher(void *handle, pubsub_endpoint_pt pubEP) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	pubsub_discovery_pt pubsub_discovery = (pubsub_discovery_pt) handle;
 +
 +	celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
 +
- 	char *pub_key = createScopeTopicKey(pubEP->scope,pubEP->topic);
++	char *pub_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +	array_list_pt pubEP_list = (array_list_pt)hashMap_get(pubsub_discovery->discoveredPubs,pub_key);
 +	free(pub_key);
 +	if(pubEP_list==NULL){
- 		printf("PSD: Cannot find any registered publisher for topic %s. Something is not consistent.\n",pubEP->topic);
++		printf("PSD: Cannot find any registered publisher for topic %s. Something is not consistent.\n",properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +		status = CELIX_ILLEGAL_STATE;
 +	}
 +	else{
 +
 +		int i;
 +		bool found = false;
 +		pubsub_endpoint_pt p = NULL;
 +
 +		for(i=0;!found && i<arrayList_size(pubEP_list);i++){
 +			p = (pubsub_endpoint_pt)arrayList_get(pubEP_list,i);
 +			found = pubsubEndpoint_equals(pubEP,p);
 +		}
 +
 +		if(!found){
 +			printf("PSD: Trying to remove a not existing endpoint. Something is not consistent.\n");
 +			status = CELIX_ILLEGAL_STATE;
 +		}
 +		else{
 +
 +			arrayList_removeElement(pubEP_list,p);
 +
 +			status = etcdWriter_deletePublisherEndpoint(pubsub_discovery->writer,p);
 +
 +			pubsubEndpoint_destroy(p);
 +		}
 +	}
 +
 +	celixThreadMutex_unlock(&pubsub_discovery->discoveredPubsMutex);
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_discovery_interestedInTopic(void *handle, const char* scope, const char* topic) {
 +    pubsub_discovery_pt pubsub_discovery = (pubsub_discovery_pt) handle;
 +
 +    char *scope_topic_key = createScopeTopicKey(scope, topic);
 +    celixThreadMutex_lock(&pubsub_discovery->watchersMutex);
 +    struct watcher_info * wi = hashMap_get(pubsub_discovery->watchers, scope_topic_key);
 +    if(wi) {
 +        wi->nr_references++;
 +        free(scope_topic_key);
 +    } else {
 +        wi = calloc(1, sizeof(*wi));
 +        etcdWatcher_create(pubsub_discovery, pubsub_discovery->context, scope, topic, &wi->watcher);
 +        wi->nr_references = 1;
 +        hashMap_put(pubsub_discovery->watchers, scope_topic_key, wi);
 +    }
 +
 +    celixThreadMutex_unlock(&pubsub_discovery->watchersMutex);
 +
 +    return CELIX_SUCCESS;
 +}
 +
 +celix_status_t pubsub_discovery_uninterestedInTopic(void *handle, const char* scope, const char* topic) {
 +    pubsub_discovery_pt pubsub_discovery = (pubsub_discovery_pt) handle;
 +
 +    char *scope_topic_key = createScopeTopicKey(scope, topic);
 +    celixThreadMutex_lock(&pubsub_discovery->watchersMutex);
 +
 +    hash_map_entry_pt entry =  hashMap_getEntry(pubsub_discovery->watchers, scope_topic_key);
 +    if(entry) {
 +        struct watcher_info * wi = hashMapEntry_getValue(entry);
 +        wi->nr_references--;
 +        if(wi->nr_references == 0) {
 +            char *key = hashMapEntry_getKey(entry);
 +            hashMap_remove(pubsub_discovery->watchers, scope_topic_key);
 +            free(key);
 +            free(scope_topic_key);
 +            etcdWatcher_stop(wi->watcher);
 +            etcdWatcher_destroy(wi->watcher);
 +            free(wi);
 +        }
 +    } else {
 +        fprintf(stderr, "[DISC] Inconsistency error: Removing unknown topic %s\n", topic);
 +    }
 +    celixThreadMutex_unlock(&pubsub_discovery->watchersMutex);
 +    return CELIX_SUCCESS;
 +}
 +
 +/* pubsub_topology_manager tracker callbacks */
 +
 +celix_status_t pubsub_discovery_tmPublisherAnnounceAdded(void * handle, service_reference_pt reference, void * service) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	pubsub_discovery_pt pubsub_discovery = (pubsub_discovery_pt)handle;
 +	publisher_endpoint_announce_pt listener = (publisher_endpoint_announce_pt)service;
 +
 +	celixThreadMutex_lock(&pubsub_discovery->discoveredPubsMutex);
 +	celixThreadMutex_lock(&pubsub_discovery->listenerReferencesMutex);
 +
 +	/* Notify the PSTM about discovered publisher endpoints */
 +	hash_map_iterator_pt iter = hashMapIterator_create(pubsub_discovery->discoveredPubs);
 +	while(hashMapIterator_hasNext(iter)){
 +		array_list_pt pubEP_list = (array_list_pt)hashMapIterator_nextValue(iter);
 +		int i;
 +		for(i=0;i<arrayList_size(pubEP_list);i++){
 +			pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pubEP_list,i);
 +			status += listener->announcePublisher(listener->handle, pubEP);
 +		}
 +	}
 +
 +	hashMapIterator_destroy(iter);
 +
 +	hashMap_put(pubsub_discovery->listenerReferences, reference, NULL);
 +
 +	celixThreadMutex_unlock(&pubsub_discovery->listenerReferencesMutex);
 +	celixThreadMutex_unlock(&pubsub_discovery->discoveredPubsMutex);
 +
 +	printf("PSD: pubsub_tm_announce_publisher added.\n");
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_discovery_tmPublisherAnnounceModified(void * handle, service_reference_pt reference, void * service) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	status = pubsub_discovery_tmPublisherAnnounceRemoved(handle, reference, service);
 +	if (status == CELIX_SUCCESS) {
 +		status = pubsub_discovery_tmPublisherAnnounceAdded(handle, reference, service);
 +	}
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_discovery_tmPublisherAnnounceRemoved(void * handle, service_reference_pt reference, void * service) {
 +	celix_status_t status = CELIX_SUCCESS;
 +	pubsub_discovery_pt pubsub_discovery = handle;
 +
 +	celixThreadMutex_lock(&pubsub_discovery->listenerReferencesMutex);
 +
 +	if (pubsub_discovery->listenerReferences != NULL) {
 +		if (hashMap_remove(pubsub_discovery->listenerReferences, reference)) {
 +			printf("PSD: pubsub_tm_announce_publisher removed.\n");
 +		}
 +	}
 +	celixThreadMutex_unlock(&pubsub_discovery->listenerReferencesMutex);
 +
 +	return status;
 +}
 +

http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_spi/include/pubsub_endpoint.h
----------------------------------------------------------------------
diff --cc pubsub/pubsub_spi/include/pubsub_endpoint.h
index 4c39d2f,0000000..598d673
mode 100644,000000..100644
--- a/pubsub/pubsub_spi/include/pubsub_endpoint.h
+++ b/pubsub/pubsub_spi/include/pubsub_endpoint.h
@@@ -1,58 -1,0 +1,65 @@@
 +/**
 + *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_endpoint.h
 + *
 + *  \date       Sep 21, 2015
 + *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
 + *  \copyright	Apache License, Version 2.0
 + */
 +
 +#ifndef PUBSUB_ENDPOINT_H_
 +#define PUBSUB_ENDPOINT_H_
 +
 +#include "service_reference.h"
 +#include "listener_hook_service.h"
 +#include "properties.h"
 +
 +#include "pubsub/publisher.h"
 +#include "pubsub/subscriber.h"
 +
++#define PUBSUB_ENDPOINT_ID              "pubsub.endpoint.id"
++#define PUBSUB_ENDPOINT_SERVICE_ID      "service.id"
++#define PUBSUB_ENDPOINT_SERIALIZER      "serializer"
++#define PUBSUB_ENDPOINT_ADMIN_TYPE      "pubsub.admin.type"
++#define PUBSUB_ENDPOINT_URL             "pubsub.endpoint"
++#define PUBSUB_ENDPOINT_TOPIC           "pubsub.topic"
++#define PUBSUB_ENDPOINT_SCOPE           "pubsub.scope"
++#define PUBSUB_ENDPOINT_TYPE            "pubsub.type"
++
 +struct pubsub_endpoint {
-     char *frameworkUUID;
-     char *scope;
-     char *topic;
-     long serviceID;
-     char* endpoint;
-     bool is_secure;
++    long serviceID;         //optional
++    bool is_secure;         //optional
++    properties_pt endpoint_props;
 +    properties_pt topic_props;
 +};
 +
 +typedef struct pubsub_endpoint *pubsub_endpoint_pt;
 +
 +celix_status_t pubsubEndpoint_create(const char* fwUUID, const char* scope, const char* topic, long serviceId,const char* endpoint,properties_pt topic_props,pubsub_endpoint_pt* psEp);
 +celix_status_t pubsubEndpoint_createFromServiceReference(service_reference_pt reference,pubsub_endpoint_pt* psEp, bool isPublisher);
 +celix_status_t pubsubEndpoint_createFromListenerHookInfo(listener_hook_info_pt info,pubsub_endpoint_pt* psEp, bool isPublisher);
 +celix_status_t pubsubEndpoint_clone(pubsub_endpoint_pt in, pubsub_endpoint_pt *out);
 +celix_status_t pubsubEndpoint_destroy(pubsub_endpoint_pt psEp);
 +bool pubsubEndpoint_equals(pubsub_endpoint_pt psEp1,pubsub_endpoint_pt psEp2);
++celix_status_t pubsubEndpoint_setField(pubsub_endpoint_pt ep, const char* key, const char* value);
 +
 +char *createScopeTopicKey(const char* scope, const char* topic);
 +
 +#endif /* PUBSUB_ENDPOINT_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_spi/src/pubsub_endpoint.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_spi/src/pubsub_endpoint.c
index c3fd293,0000000..d3b746e
mode 100644,000000..100644
--- a/pubsub/pubsub_spi/src/pubsub_endpoint.c
+++ b/pubsub/pubsub_spi/src/pubsub_endpoint.c
@@@ -1,254 -1,0 +1,282 @@@
 +/**
 + *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.
 + */
 +/*
 + * endpoint_description.c
 + *
 + *  \date       25 Jul 2014
 + *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
 + *  \copyright  Apache License, Version 2.0
 + */
 +
 +#include <string.h>
 +#include <stdlib.h>
++#include <uuid/uuid.h>
 +
 +#include "celix_errno.h"
 +#include "celix_log.h"
 +
 +#include "pubsub_common.h"
 +#include "pubsub_endpoint.h"
 +#include "constants.h"
 +
 +#include "pubsub_utils.h"
 +
 +
 +static void pubsubEndpoint_setFields(pubsub_endpoint_pt psEp, const char* fwUUID, const char* scope, const char* topic, long serviceId,const char* endpoint,properties_pt topic_props, bool cloneProps);
 +static properties_pt pubsubEndpoint_getTopicProperties(bundle_pt bundle, const char *topic, bool isPublisher);
 +
 +static void pubsubEndpoint_setFields(pubsub_endpoint_pt psEp, const char* fwUUID, const char* scope, const char* topic, long serviceId,const char* endpoint,properties_pt topic_props, bool cloneProps){
 +
++	if (psEp->endpoint_props == NULL) {
++		psEp->endpoint_props = properties_create();
++	}
++
++	char endpointUuid[37];
++
++	uuid_t endpointUid;
++	uuid_generate(endpointUid);
++	uuid_unparse(endpointUid, endpointUuid);
++	properties_set(psEp->endpoint_props, PUBSUB_ENDPOINT_ID, endpointUuid);
++
 +	if (fwUUID != NULL) {
- 		psEp->frameworkUUID = strdup(fwUUID);
++		properties_set(psEp->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID, fwUUID);
 +	}
 +
 +	if (scope != NULL) {
- 		psEp->scope = strdup(scope);
++		properties_set(psEp->endpoint_props, PUBSUB_ENDPOINT_SCOPE, scope);
 +	}
 +
 +	if (topic != NULL) {
- 		psEp->topic = strdup(topic);
++		properties_set(psEp->endpoint_props, PUBSUB_ENDPOINT_TOPIC, topic);
 +	}
 +
 +	psEp->serviceID = serviceId;
 +
 +	if(endpoint != NULL) {
- 		psEp->endpoint = strdup(endpoint);
++		properties_set(psEp->endpoint_props, PUBSUB_ENDPOINT_URL, endpoint);
 +	}
 +
 +	if(topic_props != NULL){
 +		if(cloneProps){
 +			properties_copy(topic_props, &(psEp->topic_props));
 +		}
 +		else{
 +			psEp->topic_props = topic_props;
 +		}
 +	}
 +}
 +
 +static properties_pt pubsubEndpoint_getTopicProperties(bundle_pt bundle, const char *topic, bool isPublisher){
 +
 +	properties_pt topic_props = NULL;
 +
 +	bool isSystemBundle = false;
 +	bundle_isSystemBundle(bundle, &isSystemBundle);
 +	long bundleId = -1;
 +	bundle_isSystemBundle(bundle, &isSystemBundle);
 +	bundle_getBundleId(bundle,&bundleId);
 +
 +	if(isSystemBundle == false) {
 +
 +		char *bundleRoot = NULL;
 +		char* topicPropertiesPath = NULL;
 +		bundle_getEntry(bundle, ".", &bundleRoot);
 +
 +		if(bundleRoot != NULL){
 +
 +			asprintf(&topicPropertiesPath, "%s/META-INF/topics/%s/%s.properties", bundleRoot, isPublisher?"pub":"sub", topic);
 +			topic_props = properties_load(topicPropertiesPath);
 +			if(topic_props==NULL){
 +				printf("PSEP: Could not load properties for %s on topic %s, bundleId=%ld\n", isPublisher?"publication":"subscription", topic,bundleId);
 +			}
 +
 +			free(topicPropertiesPath);
 +			free(bundleRoot);
 +		}
 +	}
 +
 +	return topic_props;
 +}
 +
++celix_status_t pubsubEndpoint_setField(pubsub_endpoint_pt ep, const char* key, const char* value) {
++	celix_status_t status = CELIX_SUCCESS;
++
++	if (ep->endpoint_props == NULL) {
++		printf("PUBSUB_EP: No endpoint_props for endpoint available!\n");
++		return CELIX_ILLEGAL_STATE;
++	}
++
++	if (key != NULL && value != NULL) {
++		properties_set(ep->endpoint_props, key, value);
++	}
++
++	return status;
++}
++
 +celix_status_t pubsubEndpoint_create(const char* fwUUID, const char* scope, const char* topic, long serviceId,const char* endpoint,properties_pt topic_props,pubsub_endpoint_pt* psEp){
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	*psEp = calloc(1, sizeof(**psEp));
 +
 +	pubsubEndpoint_setFields(*psEp, fwUUID, scope, topic, serviceId, endpoint, topic_props, true);
 +
 +	return status;
 +
 +}
 +
 +celix_status_t pubsubEndpoint_clone(pubsub_endpoint_pt in, pubsub_endpoint_pt *out){
 +	celix_status_t status = CELIX_SUCCESS;
 +
- 	*out = calloc(1,sizeof(**out));
++    pubsub_endpoint_pt ep = calloc(1,sizeof(*ep));
 +
- 	pubsubEndpoint_setFields(*out, in->frameworkUUID, in->scope, in->topic, in->serviceID, in->endpoint, in->topic_props, true);
++	status = properties_copy(in->endpoint_props, &(ep->endpoint_props));
++
++    if (in->topic_props != NULL) {
++        status += properties_copy(in->topic_props, &(ep->topic_props));
++    }
++
++	ep->serviceID = in->serviceID;
++	ep->is_secure = in->is_secure;
++
++    if (status == CELIX_SUCCESS) {
++        *out = ep;
++    } else {
++        pubsubEndpoint_destroy(ep);
++    }
 +
 +	return status;
 +
 +}
 +
 +celix_status_t pubsubEndpoint_createFromServiceReference(service_reference_pt reference, pubsub_endpoint_pt* psEp, bool isPublisher){
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	pubsub_endpoint_pt ep = calloc(1,sizeof(*ep));
 +
 +	bundle_pt bundle = NULL;
 +	bundle_context_pt ctxt = NULL;
 +	const char* fwUUID = NULL;
 +	serviceReference_getBundle(reference,&bundle);
 +	bundle_getContext(bundle,&ctxt);
 +	bundleContext_getProperty(ctxt,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID);
 +
 +	const char* scope = NULL;
 +	serviceReference_getProperty(reference, PUBSUB_SUBSCRIBER_SCOPE,&scope);
 +
 +	const char* topic = NULL;
 +	serviceReference_getProperty(reference, PUBSUB_SUBSCRIBER_TOPIC,&topic);
 +
 +	const char* serviceId = NULL;
 +	serviceReference_getProperty(reference,(char*)OSGI_FRAMEWORK_SERVICE_ID,&serviceId);
 +
 +	/* TODO: is topic_props==NULL a fatal error such that EP cannot be created? */
 +	properties_pt topic_props = pubsubEndpoint_getTopicProperties(bundle, topic, isPublisher);
 +
 +	pubsubEndpoint_setFields(ep, fwUUID, scope!=NULL?scope:PUBSUB_SUBSCRIBER_SCOPE_DEFAULT, topic, strtol(serviceId,NULL,10), NULL, topic_props, false);
 +
- 	if (!ep->frameworkUUID || !ep->serviceID || !ep->scope || !ep->topic) {
++	if (!properties_get(ep->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID) ||
++			!ep->serviceID ||
++			!properties_get(ep->endpoint_props, PUBSUB_ENDPOINT_SCOPE) ||
++			!properties_get(ep->endpoint_props, PUBSUB_ENDPOINT_TOPIC)) {
++
 +		fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "PUBSUB_ENDPOINT: incomplete description!.");
 +		status = CELIX_BUNDLE_EXCEPTION;
 +		pubsubEndpoint_destroy(ep);
 +		*psEp = NULL;
 +	}
 +	else{
 +		*psEp = ep;
 +	}
 +
 +	return status;
 +
 +}
 +
 +celix_status_t pubsubEndpoint_createFromListenerHookInfo(listener_hook_info_pt info,pubsub_endpoint_pt* psEp, bool isPublisher){
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	const char* fwUUID=NULL;
 +	bundleContext_getProperty(info->context,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID);
 +
 +	if(fwUUID==NULL){
 +		return CELIX_BUNDLE_EXCEPTION;
 +	}
 +
 +	char* topic = pubsub_getTopicFromFilter(info->filter);
 +	if(topic==NULL){
 +		return CELIX_BUNDLE_EXCEPTION;
 +	}
 +
 +	*psEp = calloc(1, sizeof(**psEp));
 +
 +	char* scope = pubsub_getScopeFromFilter(info->filter);
 +	if(scope == NULL) {
 +		scope = strdup(PUBSUB_PUBLISHER_SCOPE_DEFAULT);
 +	}
 +
 +	bundle_pt bundle = NULL;
 +	long bundleId = -1;
 +	bundleContext_getBundle(info->context,&bundle);
 +
 +	bundle_getBundleId(bundle,&bundleId);
 +
 +	properties_pt topic_props = pubsubEndpoint_getTopicProperties(bundle, topic, isPublisher);
 +
 +	/* TODO: is topic_props==NULL a fatal error such that EP cannot be created? */
 +	pubsubEndpoint_setFields(*psEp, fwUUID, scope!=NULL?scope:PUBSUB_SUBSCRIBER_SCOPE_DEFAULT, topic, bundleId, NULL, topic_props, false);
 +
 +	free(topic);
 +	free(scope);
 +
 +
 +	return status;
 +}
 +
 +celix_status_t pubsubEndpoint_destroy(pubsub_endpoint_pt psEp){
 +
- 	if(psEp->frameworkUUID!=NULL){
- 		free(psEp->frameworkUUID);
- 		psEp->frameworkUUID = NULL;
- 	}
- 
- 	if(psEp->scope!=NULL){
- 		free(psEp->scope);
- 		psEp->scope = NULL;
- 	}
- 
- 	if(psEp->topic!=NULL){
- 		free(psEp->topic);
- 		psEp->topic = NULL;
- 	}
- 
- 	if(psEp->endpoint!=NULL){
- 		free(psEp->endpoint);
- 		psEp->endpoint = NULL;
- 	}
- 
 +	if(psEp->topic_props != NULL){
 +		properties_destroy(psEp->topic_props);
 +	}
 +
++	if (psEp->endpoint_props != NULL) {
++		properties_destroy(psEp->endpoint_props);
++    }
++
 +	free(psEp);
 +
 +	return CELIX_SUCCESS;
 +
 +}
 +
 +bool pubsubEndpoint_equals(pubsub_endpoint_pt psEp1,pubsub_endpoint_pt psEp2){
 +
- 	return ((strcmp(psEp1->frameworkUUID,psEp2->frameworkUUID)==0) &&
- 			(strcmp(psEp1->scope,psEp2->scope)==0) &&
- 			(strcmp(psEp1->topic,psEp2->topic)==0) &&
++	return ((strcmp(properties_get(psEp1->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),properties_get(psEp2->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID))==0) &&
++			(strcmp(properties_get(psEp1->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(psEp2->endpoint_props, PUBSUB_ENDPOINT_SCOPE))==0) &&
++			(strcmp(properties_get(psEp1->endpoint_props, PUBSUB_ENDPOINT_TOPIC),properties_get(psEp2->endpoint_props, PUBSUB_ENDPOINT_TOPIC))==0) &&
 +			(psEp1->serviceID == psEp2->serviceID) /*&&
 +			((psEp1->endpoint==NULL && psEp2->endpoint==NULL)||(strcmp(psEp1->endpoint,psEp2->endpoint)==0))*/
 +	);
 +}
 +
 +char *createScopeTopicKey(const char* scope, const char* topic) {
 +	char *result = NULL;
 +	asprintf(&result, "%s:%s", scope, topic);
 +
 +	return result;
 +}

http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c
index 2ac75c9,0000000..a63b275
mode 100644,000000..100644
--- a/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c
+++ b/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c
@@@ -1,721 -1,0 +1,727 @@@
 +/**
 + *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_topology_manager.c
 + *
 + *  \date       Sep 29, 2011
 + *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
 + *  \copyright	Apache License, Version 2.0
 + */
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <stdbool.h>
 +
 +#include "hash_map.h"
 +#include "array_list.h"
 +#include "bundle_context.h"
 +#include "constants.h"
 +#include "module.h"
 +#include "bundle.h"
 +#include "filter.h"
 +#include "listener_hook_service.h"
 +#include "utils.h"
 +#include "service_reference.h"
 +#include "service_registration.h"
 +#include "log_service.h"
 +#include "log_helper.h"
 +
 +#include "publisher_endpoint_announce.h"
 +#include "pubsub_topology_manager.h"
 +#include "pubsub_endpoint.h"
 +#include "pubsub_admin.h"
 +#include "pubsub_utils.h"
 +
 +
 +celix_status_t pubsub_topologyManager_create(bundle_context_pt context, log_helper_pt logHelper, pubsub_topology_manager_pt *manager) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	*manager = calloc(1, sizeof(**manager));
 +	if (!*manager) {
 +		return CELIX_ENOMEM;
 +	}
 +
 +	(*manager)->context = context;
 +
 +	celix_thread_mutexattr_t psaAttr;
 +	celixThreadMutexAttr_create(&psaAttr);
 +	celixThreadMutexAttr_settype(&psaAttr, CELIX_THREAD_MUTEX_RECURSIVE);
 +	status = celixThreadMutex_create(&(*manager)->psaListLock, &psaAttr);
 +	celixThreadMutexAttr_destroy(&psaAttr);
 +
 +	status = celixThreadMutex_create(&(*manager)->publicationsLock, NULL);
 +	status = celixThreadMutex_create(&(*manager)->subscriptionsLock, NULL);
 +	status = celixThreadMutex_create(&(*manager)->discoveryListLock, NULL);
 +
 +	arrayList_create(&(*manager)->psaList);
 +
 +	(*manager)->discoveryList = hashMap_create(serviceReference_hashCode, NULL, serviceReference_equals2, NULL);
 +	(*manager)->publications = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
 +	(*manager)->subscriptions = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
 +
 +	(*manager)->loghelper = logHelper;
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_topologyManager_destroy(pubsub_topology_manager_pt manager) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	celixThreadMutex_lock(&manager->discoveryListLock);
 +	hashMap_destroy(manager->discoveryList, false, false);
 +	celixThreadMutex_unlock(&manager->discoveryListLock);
 +	celixThreadMutex_destroy(&manager->discoveryListLock);
 +
 +	celixThreadMutex_lock(&manager->psaListLock);
 +	arrayList_destroy(manager->psaList);
 +	celixThreadMutex_unlock(&manager->psaListLock);
 +	celixThreadMutex_destroy(&manager->psaListLock);
 +
 +	celixThreadMutex_lock(&manager->publicationsLock);
 +	hash_map_iterator_pt pubit = hashMapIterator_create(manager->publications);
 +	while(hashMapIterator_hasNext(pubit)){
 +		array_list_pt l = (array_list_pt)hashMapIterator_nextValue(pubit);
 +		int i;
 +		for(i=0;i<arrayList_size(l);i++){
 +			pubsubEndpoint_destroy((pubsub_endpoint_pt)arrayList_get(l,i));
 +		}
 +		arrayList_destroy(l);
 +	}
 +	hashMapIterator_destroy(pubit);
 +	hashMap_destroy(manager->publications, true, false);
 +	celixThreadMutex_unlock(&manager->publicationsLock);
 +	celixThreadMutex_destroy(&manager->publicationsLock);
 +
 +	celixThreadMutex_lock(&manager->subscriptionsLock);
 +	hash_map_iterator_pt subit = hashMapIterator_create(manager->subscriptions);
 +	while(hashMapIterator_hasNext(subit)){
 +		array_list_pt l = (array_list_pt)hashMapIterator_nextValue(subit);
 +		int i;
 +		for(i=0;i<arrayList_size(l);i++){
 +			pubsubEndpoint_destroy((pubsub_endpoint_pt)arrayList_get(l,i));
 +		}
 +		arrayList_destroy(l);
 +	}
 +	hashMapIterator_destroy(subit);
 +	hashMap_destroy(manager->subscriptions, true, false);
 +	celixThreadMutex_unlock(&manager->subscriptionsLock);
 +	celixThreadMutex_destroy(&manager->subscriptionsLock);
 +
 +	free(manager);
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_topologyManager_psaAdded(void * handle, service_reference_pt reference, void * service) {
 +	celix_status_t status = CELIX_SUCCESS;
 +	pubsub_topology_manager_pt manager = handle;
 +	int i;
 +
 +	pubsub_admin_service_pt psa = (pubsub_admin_service_pt) service;
 +	logHelper_log(manager->loghelper, OSGI_LOGSERVICE_INFO, "PSTM: Added PSA");
 +
 +	celixThreadMutex_lock(&manager->psaListLock);
 +	arrayList_add(manager->psaList, psa);
 +	celixThreadMutex_unlock(&manager->psaListLock);
 +
 +	// Add already detected subscriptions to new PSA
 +	celixThreadMutex_lock(&manager->subscriptionsLock);
 +	hash_map_iterator_pt subscriptionsIterator = hashMapIterator_create(manager->subscriptions);
 +
 +	while (hashMapIterator_hasNext(subscriptionsIterator)) {
 +		array_list_pt sub_ep_list = hashMapIterator_nextValue(subscriptionsIterator);
 +		for(i=0;i<arrayList_size(sub_ep_list);i++){
 +			status += psa->addSubscription(psa->admin, (pubsub_endpoint_pt)arrayList_get(sub_ep_list,i));
 +		}
 +	}
 +
 +	hashMapIterator_destroy(subscriptionsIterator);
 +
 +	celixThreadMutex_unlock(&manager->subscriptionsLock);
 +
 +	// Add already detected publications to new PSA
 +	status = celixThreadMutex_lock(&manager->publicationsLock);
 +	hash_map_iterator_pt publicationsIterator = hashMapIterator_create(manager->publications);
 +
 +	while (hashMapIterator_hasNext(publicationsIterator)) {
 +		array_list_pt pub_ep_list = hashMapIterator_nextValue(publicationsIterator);
 +		for(i=0;i<arrayList_size(pub_ep_list);i++){
 +			status += psa->addPublication(psa->admin, (pubsub_endpoint_pt)arrayList_get(pub_ep_list,i));
 +		}
 +	}
 +
 +	hashMapIterator_destroy(publicationsIterator);
 +
 +	celixThreadMutex_unlock(&manager->publicationsLock);
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_topologyManager_psaModified(void * handle, service_reference_pt reference, void * service) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	// Nop...
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_topologyManager_psaRemoved(void * handle, service_reference_pt reference, void * service) {
 +	celix_status_t status = CELIX_SUCCESS;
 +	pubsub_topology_manager_pt manager = handle;
 +
 +	pubsub_admin_service_pt psa = (pubsub_admin_service_pt) service;
 +
 +	/* Deactivate all publications */
 +	celixThreadMutex_lock(&manager->publicationsLock);
 +
 +	hash_map_iterator_pt pubit = hashMapIterator_create(manager->publications);
 +	while(hashMapIterator_hasNext(pubit)){
 +		hash_map_entry_pt pub_entry = hashMapIterator_nextEntry(pubit);
 +		char* scope_topic_key = (char*)hashMapEntry_getKey(pub_entry);
 +		// Extract scope/topic name from key
 +		char scope[MAX_SCOPE_LEN];
 +		char topic[MAX_TOPIC_LEN];
 +		sscanf(scope_topic_key, "%[^:]:%s", scope, topic );
 +		array_list_pt pubEP_list = (array_list_pt)hashMapEntry_getValue(pub_entry);
 +
 +		status = psa->closeAllPublications(psa->admin,scope,topic);
 +
 +		if(status==CELIX_SUCCESS){
 +			celixThreadMutex_lock(&manager->discoveryListLock);
 +			hash_map_iterator_pt iter = hashMapIterator_create(manager->discoveryList);
 +			while(hashMapIterator_hasNext(iter)){
 +				service_reference_pt disc_sr = (service_reference_pt)hashMapIterator_nextKey(iter);
 +				publisher_endpoint_announce_pt disc = NULL;
 +				bundleContext_getService(manager->context, disc_sr, (void**) &disc);
 +				const char* fwUUID = NULL;
 +				bundleContext_getProperty(manager->context,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID);
 +				int i;
 +				for(i=0;i<arrayList_size(pubEP_list);i++){
 +					pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pubEP_list,i);
- 					if(strcmp(pubEP->frameworkUUID,fwUUID)==0){
++					if(strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),fwUUID)==0){
 +						disc->removePublisher(disc->handle,pubEP);
 +					}
 +				}
 +				bundleContext_ungetService(manager->context, disc_sr, NULL);
 +			}
 +			hashMapIterator_destroy(iter);
 +			celixThreadMutex_unlock(&manager->discoveryListLock);
 +		}
 +	}
 +	hashMapIterator_destroy(pubit);
 +
 +	celixThreadMutex_unlock(&manager->publicationsLock);
 +
 +	/* Deactivate all subscriptions */
 +	celixThreadMutex_lock(&manager->subscriptionsLock);
 +	hash_map_iterator_pt subit = hashMapIterator_create(manager->subscriptions);
 +	while(hashMapIterator_hasNext(subit)){
 +		// TODO do some error checking
 +		char* scope_topic = (char*)hashMapIterator_nextKey(subit);
 +		char scope[MAX_TOPIC_LEN];
 +		char topic[MAX_TOPIC_LEN];
 +		memset(scope, 0 , MAX_TOPIC_LEN*sizeof(char));
 +		memset(topic, 0 , MAX_TOPIC_LEN*sizeof(char));
 +		sscanf(scope_topic, "%[^:]:%s", scope, topic );
 +		status += psa->closeAllSubscriptions(psa->admin,scope, topic);
 +	}
 +	hashMapIterator_destroy(subit);
 +	celixThreadMutex_unlock(&manager->subscriptionsLock);
 +
 +	celixThreadMutex_lock(&manager->psaListLock);
 +	arrayList_removeElement(manager->psaList, psa);
 +	celixThreadMutex_unlock(&manager->psaListLock);
 +
 +	logHelper_log(manager->loghelper, OSGI_LOGSERVICE_INFO, "PSTM: Removed PSA");
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_topologyManager_subscriberAdded(void * handle, service_reference_pt reference, void * service) {
 +	celix_status_t status = CELIX_SUCCESS;
 +	pubsub_topology_manager_pt manager = handle;
 +	//subscriber_service_pt subscriber = (subscriber_service_pt)service;
 +
 +	pubsub_endpoint_pt sub = NULL;
 +	if(pubsubEndpoint_createFromServiceReference(reference,&sub,false) == CELIX_SUCCESS){
 +		celixThreadMutex_lock(&manager->subscriptionsLock);
- 		char *sub_key = createScopeTopicKey(sub->scope, sub->topic);
++		char *sub_key = createScopeTopicKey(properties_get(sub->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(sub->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
 +		array_list_pt sub_list_by_topic = hashMap_get(manager->subscriptions,sub_key);
 +		if(sub_list_by_topic==NULL){
 +			arrayList_create(&sub_list_by_topic);
 +			hashMap_put(manager->subscriptions,strdup(sub_key),sub_list_by_topic);
 +		}
 +		free(sub_key);
 +		arrayList_add(sub_list_by_topic,sub);
 +
 +		celixThreadMutex_unlock(&manager->subscriptionsLock);
 +
 +		int j;
 +		double score = 0;
 +		double best_score = 0;
 +		pubsub_admin_service_pt best_psa = NULL;
 +		celixThreadMutex_lock(&manager->psaListLock);
 +		for(j=0;j<arrayList_size(manager->psaList);j++){
 +			pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,j);
 +			psa->matchEndpoint(psa->admin,sub,&score);
 +			if(score>best_score){ /* We have a new winner! */
 +				best_score = score;
 +				best_psa = psa;
 +			}
 +		}
 +
 +		if(best_psa != NULL && best_score>0){
 +			best_psa->addSubscription(best_psa->admin,sub);
 +		}
 +
 +		// Inform discoveries for interest in the topic
 +		celixThreadMutex_lock(&manager->discoveryListLock);
 +		hash_map_iterator_pt iter = hashMapIterator_create(manager->discoveryList);
 +		while(hashMapIterator_hasNext(iter)){
 +			service_reference_pt disc_sr = (service_reference_pt)hashMapIterator_nextKey(iter);
 +			publisher_endpoint_announce_pt disc = NULL;
 +			bundleContext_getService(manager->context, disc_sr, (void**) &disc);
- 			disc->interestedInTopic(disc->handle, sub->scope, sub->topic);
++			disc->interestedInTopic(disc->handle, properties_get(sub->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(sub->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +			bundleContext_ungetService(manager->context, disc_sr, NULL);
 +		}
 +		hashMapIterator_destroy(iter);
 +		celixThreadMutex_unlock(&manager->discoveryListLock);
 +
 +		celixThreadMutex_unlock(&manager->psaListLock);
 +	}
 +	else{
 +		status=CELIX_INVALID_BUNDLE_CONTEXT;
 +	}
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_topologyManager_subscriberModified(void * handle, service_reference_pt reference, void * service) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	// Nop...
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_topologyManager_subscriberRemoved(void * handle, service_reference_pt reference, void * service) {
 +	celix_status_t status = CELIX_SUCCESS;
 +	pubsub_topology_manager_pt manager = handle;
 +
 +	pubsub_endpoint_pt subcmp = NULL;
 +	if(pubsubEndpoint_createFromServiceReference(reference,&subcmp,false) == CELIX_SUCCESS){
 +
 +		int j,k;
 +
 +		// Inform discoveries that we not interested in the topic any more
 +		celixThreadMutex_lock(&manager->discoveryListLock);
 +		hash_map_iterator_pt iter = hashMapIterator_create(manager->discoveryList);
 +		while(hashMapIterator_hasNext(iter)){
 +			service_reference_pt disc_sr = (service_reference_pt)hashMapIterator_nextKey(iter);
 +			publisher_endpoint_announce_pt disc = NULL;
 +			bundleContext_getService(manager->context, disc_sr, (void**) &disc);
- 			disc->uninterestedInTopic(disc->handle, subcmp->scope, subcmp->topic);
++			disc->uninterestedInTopic(disc->handle, properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +			bundleContext_ungetService(manager->context, disc_sr, NULL);
 +		}
 +		hashMapIterator_destroy(iter);
 +		celixThreadMutex_unlock(&manager->discoveryListLock);
 +
 +		celixThreadMutex_lock(&manager->subscriptionsLock);
 +		celixThreadMutex_lock(&manager->psaListLock);
 +
- 		char *sub_key = createScopeTopicKey(subcmp->scope,subcmp->topic);
++		char *sub_key = createScopeTopicKey(properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +		array_list_pt sub_list_by_topic = hashMap_get(manager->subscriptions,sub_key);
 +		free(sub_key);
 +		if(sub_list_by_topic!=NULL){
 +			for(j=0;j<arrayList_size(sub_list_by_topic);j++){
 +				pubsub_endpoint_pt sub = arrayList_get(sub_list_by_topic,j);
 +				if(pubsubEndpoint_equals(sub,subcmp)){
 +					for(k=0;k<arrayList_size(manager->psaList);k++){
 +						/* No problem with invoking removal on all psa's, only the one that manage this topic will do something */
 +						pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,k);
 +						psa->removeSubscription(psa->admin,sub);
 +					}
 +
 +				}
 +				arrayList_remove(sub_list_by_topic,j);
 +
 +				/* If it was the last subscriber for this topic, tell PSA to close the ZMQ socket */
 +				if(arrayList_size(sub_list_by_topic)==0){
 +					for(k=0;k<arrayList_size(manager->psaList);k++){
 +						pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,k);
- 						psa->closeAllSubscriptions(psa->admin,sub->scope, sub->topic);
++						psa->closeAllSubscriptions(psa->admin, (char*) properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(subcmp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +					}
 +				}
 +
 +				pubsubEndpoint_destroy(sub);
 +
 +			}
 +		}
 +
 +		celixThreadMutex_unlock(&manager->psaListLock);
 +		celixThreadMutex_unlock(&manager->subscriptionsLock);
 +
 +		pubsubEndpoint_destroy(subcmp);
 +
 +	}
 +	else{
 +		status=CELIX_INVALID_BUNDLE_CONTEXT;
 +	}
 +
 +	return status;
 +
 +}
 +
 +celix_status_t pubsub_topologyManager_pubsubDiscoveryAdded(void* handle, service_reference_pt reference, void* service) {
 +	celix_status_t status = CELIX_SUCCESS;
 +	pubsub_topology_manager_pt manager = (pubsub_topology_manager_pt)handle;
 +	publisher_endpoint_announce_pt disc = (publisher_endpoint_announce_pt)service;
 +
 +	const char* fwUUID = NULL;
 +
 +	bundleContext_getProperty(manager->context,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID);
 +	if(fwUUID==NULL){
 +		printf("PSD: ERRROR: Cannot retrieve fwUUID.\n");
 +		return CELIX_INVALID_BUNDLE_CONTEXT;
 +	}
 +
 +	celixThreadMutex_lock(&manager->publicationsLock);
 +
 +	celixThreadMutex_lock(&manager->discoveryListLock);
 +	hashMap_put(manager->discoveryList, reference, NULL);
 +	celixThreadMutex_unlock(&manager->discoveryListLock);
 +
 +	hash_map_iterator_pt iter = hashMapIterator_create(manager->publications);
 +	while(hashMapIterator_hasNext(iter)){
 +		array_list_pt pubEP_list = (array_list_pt)hashMapIterator_nextValue(iter);
 +		for(int i = 0; i < arrayList_size(pubEP_list); i++) {
 +			pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pubEP_list,i);
- 			if( (strcmp(pubEP->frameworkUUID,fwUUID)==0) && (pubEP->endpoint!=NULL)){
++			if( (strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),fwUUID)==0) && (properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL)){
 +				status += disc->announcePublisher(disc->handle,pubEP);
 +			}
 +		}
 +	}
 +	hashMapIterator_destroy(iter);
 +
 +	celixThreadMutex_unlock(&manager->publicationsLock);
 +
 +	celixThreadMutex_lock(&manager->subscriptionsLock);
 +	iter = hashMapIterator_create(manager->subscriptions);
 +
 +	while(hashMapIterator_hasNext(iter)) {
 +		array_list_pt l = (array_list_pt)hashMapIterator_nextValue(iter);
 +		int i;
 +		for(i=0;i<arrayList_size(l);i++){
 +			pubsub_endpoint_pt subEp = (pubsub_endpoint_pt)arrayList_get(l,i);
 +
- 			disc->interestedInTopic(disc->handle, subEp->scope, subEp->topic);
++			disc->interestedInTopic(disc->handle, properties_get(subEp->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +		}
 +	}
 +	hashMapIterator_destroy(iter);
 +	celixThreadMutex_unlock(&manager->subscriptionsLock);
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_topologyManager_pubsubDiscoveryModified(void * handle, service_reference_pt reference, void * service) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	status = pubsub_topologyManager_pubsubDiscoveryRemoved(handle, reference, service);
 +	if (status == CELIX_SUCCESS) {
 +		status = pubsub_topologyManager_pubsubDiscoveryAdded(handle, reference, service);
 +	}
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_topologyManager_pubsubDiscoveryRemoved(void * handle, service_reference_pt reference, void * service) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	pubsub_topology_manager_pt manager = handle;
 +
 +	celixThreadMutex_lock(&manager->discoveryListLock);
 +
 +
 +	if (hashMap_remove(manager->discoveryList, reference)) {
 +		logHelper_log(manager->loghelper, OSGI_LOGSERVICE_INFO, "EndpointListener Removed");
 +	}
 +
 +	celixThreadMutex_unlock(&manager->discoveryListLock);
 +
 +	return status;
 +}
 +
 +
 +celix_status_t pubsub_topologyManager_publisherTrackerAdded(void *handle, array_list_pt listeners) {
 +
 +	celix_status_t status = CELIX_SUCCESS;
 +	pubsub_topology_manager_pt manager = handle;
 +
 +	int l_index;
 +
 +	for (l_index = 0; l_index < arrayList_size(listeners); l_index++) {
 +
 +		listener_hook_info_pt info = arrayList_get(listeners, l_index);
 +
 +		pubsub_endpoint_pt pub = NULL;
 +		if(pubsubEndpoint_createFromListenerHookInfo(info, &pub, true) == CELIX_SUCCESS){
 +
 +			celixThreadMutex_lock(&manager->publicationsLock);
- 			char *pub_key = createScopeTopicKey(pub->scope, pub->topic);
++			char *pub_key = createScopeTopicKey(properties_get(pub->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pub->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +			array_list_pt pub_list_by_topic = hashMap_get(manager->publications, pub_key);
 +			if(pub_list_by_topic==NULL){
 +				arrayList_create(&pub_list_by_topic);
 +				hashMap_put(manager->publications,strdup(pub_key),pub_list_by_topic);
 +			}
 +			free(pub_key);
 +			arrayList_add(pub_list_by_topic,pub);
 +
 +			celixThreadMutex_unlock(&manager->publicationsLock);
 +
 +			int j;
 +			double score = 0;
 +			double best_score = 0;
 +			pubsub_admin_service_pt best_psa = NULL;
 +			celixThreadMutex_lock(&manager->psaListLock);
 +
 +			for(j=0;j<arrayList_size(manager->psaList);j++){
 +				pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,j);
 +				psa->matchEndpoint(psa->admin,pub,&score);
 +				if(score>best_score){ /* We have a new winner! */
 +					best_score = score;
 +					best_psa = psa;
 +				}
 +			}
 +
 +			if(best_psa != NULL && best_score>0){
 +				status = best_psa->addPublication(best_psa->admin,pub);
 +				if(status==CELIX_SUCCESS){
 +					celixThreadMutex_lock(&manager->discoveryListLock);
 +					hash_map_iterator_pt iter = hashMapIterator_create(manager->discoveryList);
 +					while(hashMapIterator_hasNext(iter)){
 +						service_reference_pt disc_sr = (service_reference_pt)hashMapIterator_nextKey(iter);
 +						publisher_endpoint_announce_pt disc = NULL;
 +						bundleContext_getService(manager->context, disc_sr, (void**) &disc);
 +						disc->announcePublisher(disc->handle,pub);
 +						bundleContext_ungetService(manager->context, disc_sr, NULL);
 +					}
 +					hashMapIterator_destroy(iter);
 +					celixThreadMutex_unlock(&manager->discoveryListLock);
 +				}
 +			}
 +
 +			celixThreadMutex_unlock(&manager->psaListLock);
 +
 +		}
 +
 +	}
 +
 +	return status;
 +
 +}
 +
 +
 +celix_status_t pubsub_topologyManager_publisherTrackerRemoved(void *handle, array_list_pt listeners) {
 +	celix_status_t status = CELIX_SUCCESS;
 +	pubsub_topology_manager_pt manager = handle;
 +
 +	int l_index;
 +
 +	for (l_index = 0; l_index < arrayList_size(listeners); l_index++) {
 +
 +		listener_hook_info_pt info = arrayList_get(listeners, l_index);
 +
 +		pubsub_endpoint_pt pubcmp = NULL;
 +		if(pubsubEndpoint_createFromListenerHookInfo(info,&pubcmp,true) == CELIX_SUCCESS){
 +
 +
 +			int j,k;
 +			celixThreadMutex_lock(&manager->psaListLock);
 +			celixThreadMutex_lock(&manager->publicationsLock);
 +
- 			char *pub_key = createScopeTopicKey(pubcmp->scope, pubcmp->topic);
++			char *pub_key = createScopeTopicKey(properties_get(pubcmp->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubcmp->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +			array_list_pt pub_list_by_topic = hashMap_get(manager->publications,pub_key);
 +			if(pub_list_by_topic!=NULL){
 +				for(j=0;j<arrayList_size(pub_list_by_topic);j++){
 +					pubsub_endpoint_pt pub = arrayList_get(pub_list_by_topic,j);
 +					if(pubsubEndpoint_equals(pub,pubcmp)){
 +						for(k=0;k<arrayList_size(manager->psaList);k++){
 +							pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,k);
 +							status = psa->removePublication(psa->admin,pub);
 +							if(status==CELIX_SUCCESS){ /* We found the one that manages this endpoint */
 +								celixThreadMutex_lock(&manager->discoveryListLock);
 +								hash_map_iterator_pt iter = hashMapIterator_create(manager->discoveryList);
 +								while(hashMapIterator_hasNext(iter)){
 +									service_reference_pt disc_sr = (service_reference_pt)hashMapIterator_nextKey(iter);
 +									publisher_endpoint_announce_pt disc = NULL;
 +									bundleContext_getService(manager->context, disc_sr, (void**) &disc);
 +									disc->removePublisher(disc->handle,pub);
 +									bundleContext_ungetService(manager->context, disc_sr, NULL);
 +								}
 +								hashMapIterator_destroy(iter);
 +								celixThreadMutex_unlock(&manager->discoveryListLock);
 +							}
 +							else if(status ==  CELIX_ILLEGAL_ARGUMENT){ /* Not a real error, just saying this psa does not handle this endpoint */
 +								status = CELIX_SUCCESS;
 +							}
 +						}
 +						//}
 +						arrayList_remove(pub_list_by_topic,j);
 +
 +						/* If it was the last publisher for this topic, tell PSA to close the ZMQ socket and then inform the discovery */
 +						if(arrayList_size(pub_list_by_topic)==0){
 +							for(k=0;k<arrayList_size(manager->psaList);k++){
 +								pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,k);
- 								psa->closeAllPublications(psa->admin,pub->scope, pub->topic);
++								psa->closeAllPublications(psa->admin, (char*) properties_get(pub->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(pub->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +							}
 +						}
 +
 +						pubsubEndpoint_destroy(pub);
 +					}
 +
 +				}
 +			}
 +
 +			celixThreadMutex_unlock(&manager->publicationsLock);
 +			celixThreadMutex_unlock(&manager->psaListLock);
 +
 +			free(pub_key);
 +
 +			pubsubEndpoint_destroy(pubcmp);
 +
 +		}
 +
 +	}
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_topologyManager_announcePublisher(void *handle, pubsub_endpoint_pt pubEP){
 +	celix_status_t status = CELIX_SUCCESS;
- 	printf("PSTM: New publisher discovered for topic %s [fwUUID=%s, ep=%s]\n",pubEP->topic,pubEP->frameworkUUID,pubEP->endpoint);
++	printf("PSTM: New publisher discovered for topic %s [fwUUID=%s, ep=%s]\n",
++		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++		   properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +
 +	pubsub_topology_manager_pt manager = handle;
 +	celixThreadMutex_lock(&manager->psaListLock);
 +	celixThreadMutex_lock(&manager->publicationsLock);
 +
- 	char *pub_key = createScopeTopicKey(pubEP->scope, pubEP->topic);
++	char *pub_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
 +	array_list_pt pub_list_by_topic = hashMap_get(manager->publications,pub_key);
 +	if(pub_list_by_topic==NULL){
 +		arrayList_create(&pub_list_by_topic);
 +		hashMap_put(manager->publications,strdup(pub_key),pub_list_by_topic);
 +	}
 +	free(pub_key);
 +
 +	/* Shouldn't be any other duplicate, since it's filtered out by the discovery */
 +	pubsub_endpoint_pt p = NULL;
 +	pubsubEndpoint_clone(pubEP, &p);
 +	arrayList_add(pub_list_by_topic,p);
 +
 +	int j;
 +	double score = 0;
 +	double best_score = 0;
 +	pubsub_admin_service_pt best_psa = NULL;
 +
 +	for(j=0;j<arrayList_size(manager->psaList);j++){
 +		pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,j);
 +		psa->matchEndpoint(psa->admin,p,&score);
 +		if(score>best_score){ /* We have a new winner! */
 +			best_score = score;
 +			best_psa = psa;
 +		}
 +	}
 +
 +	if(best_psa != NULL && best_score>0){
 +		best_psa->addPublication(best_psa->admin,p);
 +	}
 +	else{
 +		status = CELIX_ILLEGAL_STATE;
 +	}
 +
 +	celixThreadMutex_unlock(&manager->publicationsLock);
 +	celixThreadMutex_unlock(&manager->psaListLock);
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_topologyManager_removePublisher(void *handle, pubsub_endpoint_pt pubEP){
 +	celix_status_t status = CELIX_SUCCESS;
- 	printf("PSTM: Publisher removed for topic %s [fwUUID=%s, ep=%s]\n",pubEP->topic,pubEP->frameworkUUID,pubEP->endpoint);
++	printf("PSTM: Publisher removed for topic %s [fwUUID=%s, ep=%s]\n",
++		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++		   properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +
 +	pubsub_topology_manager_pt manager = handle;
 +	celixThreadMutex_lock(&manager->psaListLock);
 +	celixThreadMutex_lock(&manager->publicationsLock);
 +	int i;
 +
- 	char *pub_key = createScopeTopicKey(pubEP->scope, pubEP->topic);
++	char *pub_key = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +	array_list_pt pub_list_by_topic = hashMap_get(manager->publications,pub_key);
 +	if(pub_list_by_topic==NULL){
- 		printf("PSTM: ERROR: Cannot find topic for known endpoint [%s,%s,%s]. Something is inconsistent.\n",pub_key,pubEP->frameworkUUID,pubEP->endpoint);
++		printf("PSTM: ERROR: Cannot find topic for known endpoint [%s,%s,%s]. Something is inconsistent.\n",pub_key,properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +		status = CELIX_ILLEGAL_STATE;
 +	}
 +	else{
 +
 +		pubsub_endpoint_pt p = NULL;
 +		bool found = false;
 +
 +		for(i=0;!found && i<arrayList_size(pub_list_by_topic);i++){
 +			p = (pubsub_endpoint_pt)arrayList_get(pub_list_by_topic,i);
 +			found = pubsubEndpoint_equals(p,pubEP);
 +		}
 +
 +		if(found && p !=NULL){
 +
 +			for(i=0;i<arrayList_size(manager->psaList);i++){
 +				pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,i);
 +				/* No problem with invoking removal on all psa's, only the one that manage this topic will do something */
 +				psa->removePublication(psa->admin,p);
 +			}
 +
 +			arrayList_removeElement(pub_list_by_topic,p);
 +
 +			/* If it was the last publisher for this topic, tell PSA to close the ZMQ socket */
 +			if(arrayList_size(pub_list_by_topic)==0){
 +
 +				for(i=0;i<arrayList_size(manager->psaList);i++){
 +					pubsub_admin_service_pt psa = (pubsub_admin_service_pt)arrayList_get(manager->psaList,i);
- 					psa->closeAllPublications(psa->admin,p->scope, p->topic);
++					psa->closeAllPublications(psa->admin, (char*) properties_get(p->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(p->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +				}
 +			}
 +
 +			pubsubEndpoint_destroy(p);
 +		}
 +
 +
 +	}
 +	free(pub_key);
 +	celixThreadMutex_unlock(&manager->publicationsLock);
 +	celixThreadMutex_unlock(&manager->psaListLock);
 +
 +
 +	return status;
 +}
 +

http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/utils/include/properties.h
----------------------------------------------------------------------
diff --cc utils/include/properties.h
index 5c6dc4d,0000000..582a242
mode 100644,000000..100644
--- a/utils/include/properties.h
+++ b/utils/include/properties.h
@@@ -1,68 -1,0 +1,70 @@@
 +/**
 + *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.
 + */
 +/*
 + * properties.h
 + *
 + *  \date       Apr 27, 2010
 + *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
 + *  \copyright	Apache License, Version 2.0
 + */
 +
 +#ifndef PROPERTIES_H_
 +#define PROPERTIES_H_
 +
 +#include <stdio.h>
 +
 +#include "hash_map.h"
 +#include "exports.h"
 +#include "celix_errno.h"
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +typedef hash_map_pt properties_pt;
 +typedef hash_map_t properties_t;
 +
 +UTILS_EXPORT properties_pt properties_create(void);
 +
 +UTILS_EXPORT void properties_destroy(properties_pt properties);
 +
 +UTILS_EXPORT properties_pt properties_load(const char *filename);
 +
 +UTILS_EXPORT properties_pt properties_loadWithStream(FILE *stream);
 +
 +UTILS_EXPORT properties_pt properties_loadFromString(const char *input);
 +
 +UTILS_EXPORT void properties_store(properties_pt properties, const char *file, const char *header);
 +
 +UTILS_EXPORT const char *properties_get(properties_pt properties, const char *key);
 +
 +UTILS_EXPORT const char *properties_getWithDefault(properties_pt properties, const char *key, const char *defaultValue);
 +
 +UTILS_EXPORT void properties_set(properties_pt properties, const char *key, const char *value);
 +
++UTILS_EXPORT void properties_unset(properties_pt properties, const char *key);
++
 +UTILS_EXPORT celix_status_t properties_copy(properties_pt properties, properties_pt *copy);
 +
 +#define PROPERTIES_FOR_EACH(props, key) \
 +    for(hash_map_iterator_t iter = hashMapIterator_construct(props); \
 +        hashMapIterator_hasNext(&iter), (key) = (const char*)hashMapIterator_nextKey(&iter);)
 +#ifdef __cplusplus
 +}
 +#endif
 +
 +#endif /* PROPERTIES_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/utils/src/properties.c
----------------------------------------------------------------------
diff --cc utils/src/properties.c
index 1e097a0,0000000..860b9bb
mode 100644,000000..100644
--- a/utils/src/properties.c
+++ b/utils/src/properties.c
@@@ -1,330 -1,0 +1,335 @@@
 +/**
 + *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.
 + */
 +/*
 + * properties.c
 + *
 + *  \date       Apr 27, 2010
 + *  \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 <stdlib.h>
 +#include <ctype.h>
 +#include "celixbool.h"
 +#include "properties.h"
 +#include "utils.h"
 +
 +#define MALLOC_BLOCK_SIZE		5
 +
 +static void parseLine(const char* line, properties_pt props);
 +
 +properties_pt properties_create(void) {
 +	return hashMap_create(utils_stringHash, utils_stringHash, utils_stringEquals, utils_stringEquals);
 +}
 +
 +void properties_destroy(properties_pt properties) {
 +	hash_map_iterator_pt iter = hashMapIterator_create(properties);
 +	while (hashMapIterator_hasNext(iter)) {
 +		hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
 +		free(hashMapEntry_getKey(entry));
 +		free(hashMapEntry_getValue(entry));
 +	}
 +	hashMapIterator_destroy(iter);
 +	hashMap_destroy(properties, false, false);
 +}
 +
 +properties_pt properties_load(const char* filename) {
 +	FILE *file = fopen(filename, "r");
 +	if(file==NULL){
 +		return NULL;
 +	}
 +	properties_pt props = properties_loadWithStream(file);
 +	fclose(file);
 +	return props;
 +}
 +
 +properties_pt properties_loadWithStream(FILE *file) {
 +	properties_pt props = NULL;
 +
 +
 +	if (file != NULL ) {
 +		char *saveptr;
 +		char *filebuffer = NULL;
 +		char *line = NULL;
 +		size_t file_size = 0;
 +
 +		props = properties_create();
 +		fseek(file, 0, SEEK_END);
 +		file_size = ftell(file);
 +		fseek(file, 0, SEEK_SET);
 +
 +		if(file_size > 0){
 +			filebuffer = calloc(file_size + 1, sizeof(char));
 +			if(filebuffer) {
 +				size_t rs = fread(filebuffer, sizeof(char), file_size, file);
 +				if(rs != file_size){
 +					fprintf(stderr,"fread read only %lu bytes out of %lu\n",rs,file_size);
 +				}
 +				filebuffer[file_size]='\0';
 +				line = strtok_r(filebuffer, "\n", &saveptr);
 +				while ( line != NULL ) {
 +					parseLine(line, props);
 +					line = strtok_r(NULL, "\n", &saveptr);
 +				}
 +				free(filebuffer);
 +			}
 +		}
 +	}
 +
 +	return props;
 +}
 +
 +properties_pt properties_loadFromString(const char *input){
 +	properties_pt props = properties_create();
 +
 +	char *in = strdup(input);
 +	char *line = NULL;
 +	char *saveLinePointer = NULL;
 +
 +	bool firstTime = true;
 +	do {
 +		if (firstTime){
 +			line = strtok_r(in, "\n", &saveLinePointer);
 +			firstTime = false;
 +		}else {
 +			line = strtok_r(NULL, "\n", &saveLinePointer);
 +		}
 +
 +		if (line == NULL){
 +			break;
 +		}
 +
 +		parseLine(line, props);
 +	} while(line != NULL);
 +
 +	free(in);
 +
 +	return props;
 +}
 +
 +
 +/**
 + * Header is ignored for now, cannot handle comments yet
 + */
 +void properties_store(properties_pt properties, const char* filename, const char* header) {
 +	FILE *file = fopen ( filename, "w+" );
 +	char *str;
 +
 +	if (file != NULL) {
 +		if (hashMap_size(properties) > 0) {
 +			hash_map_iterator_pt iterator = hashMapIterator_create(properties);
 +			while (hashMapIterator_hasNext(iterator)) {
 +				hash_map_entry_pt entry = hashMapIterator_nextEntry(iterator);
 +				str = hashMapEntry_getKey(entry);
 +				for (int i = 0; i < strlen(str); i += 1) {
 +					if (str[i] == '#' || str[i] == '!' || str[i] == '=' || str[i] == ':') {
 +						fputc('\\', file);
 +					}
 +					fputc(str[i], file);
 +				}
 +
 +				fputc('=', file);
 +
 +				str = hashMapEntry_getValue(entry);
 +				for (int i = 0; i < strlen(str); i += 1) {
 +					if (str[i] == '#' || str[i] == '!' || str[i] == '=' || str[i] == ':') {
 +						fputc('\\', file);
 +					}
 +					fputc(str[i], file);
 +				}
 +
 +				fputc('\n', file);
 +
 +			}
 +			hashMapIterator_destroy(iterator);
 +		}
 +		fclose(file);
 +	} else {
 +		perror("File is null");
 +	}
 +}
 +
 +celix_status_t properties_copy(properties_pt properties, properties_pt *out) {
 +	celix_status_t status = CELIX_SUCCESS;
 +	properties_pt copy = properties_create();
 +
 +	if (copy != NULL) {
 +		hash_map_iterator_pt iter = hashMapIterator_create(properties);
 +		while (hashMapIterator_hasNext(iter)) {
 +			hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
 +			char *key = hashMapEntry_getKey(entry);
 +			char *value = hashMapEntry_getValue(entry);
 +			properties_set(copy, key, value);
 +		}
 +		hashMapIterator_destroy(iter);
 +	} else {
 +		status = CELIX_ENOMEM;
 +	}
 +
 +	if (status == CELIX_SUCCESS) {
 +		*out = copy;
 +	}
 +
 +	return status;
 +}
 +
 +const char* properties_get(properties_pt properties, const char* key) {
 +	return hashMap_get(properties, (void*)key);
 +}
 +
 +const char* properties_getWithDefault(properties_pt properties, const char* key, const char* defaultValue) {
 +	const char* value = properties_get(properties, key);
 +	return value == NULL ? defaultValue : value;
 +}
 +
 +void properties_set(properties_pt properties, const char* key, const char* value) {
 +	hash_map_entry_pt entry = hashMap_getEntry(properties, key);
 +	char* oldValue = NULL;
 +	if (entry != NULL) {
 +		char* oldKey = hashMapEntry_getKey(entry);
 +		oldValue = hashMapEntry_getValue(entry);
 +		hashMap_put(properties, oldKey, strndup(value, 1024*10));
 +	} else {
 +		hashMap_put(properties, strndup(key, 1024*10), strndup(value, 1024*10));
 +	}
 +	free(oldValue);
 +}
 +
++void properties_unset(properties_pt properties, const char* key) {
++	char* oldValue = hashMap_remove(properties, key);
++	free(oldValue);
++}
++
 +static void updateBuffers(char **key, char ** value, char **output, int outputPos, int *key_len, int *value_len) {
 +	if (*output == *key) {
 +		if (outputPos == (*key_len) - 1) {
 +			(*key_len) += MALLOC_BLOCK_SIZE;
 +			*key = realloc(*key, *key_len);
 +			*output = *key;
 +		}
 +	}
 +	else {
 +		if (outputPos == (*value_len) - 1) {
 +			(*value_len) += MALLOC_BLOCK_SIZE;
 +			*value = realloc(*value, *value_len);
 +			*output = *value;
 +		}
 +	}
 +}
 +
 +static void parseLine(const char* line, properties_pt props) {
 +	int linePos = 0;
 +	bool precedingCharIsBackslash = false;
 +	bool isComment = false;
 +	int outputPos = 0;
 +	char *output = NULL;
 +	int key_len = MALLOC_BLOCK_SIZE;
 +	int value_len = MALLOC_BLOCK_SIZE;
 +	linePos = 0;
 +	precedingCharIsBackslash = false;
 +	isComment = false;
 +	output = NULL;
 +	outputPos = 0;
 +
 +	//Ignore empty lines
 +	if (line[0] == '\n' && line[1] == '\0') {
 +		return;
 +	}
 +
 +	char *key = calloc(1, key_len);
 +	char *value = calloc(1, value_len);
 +	key[0] = '\0';
 +	value[0] = '\0';
 +
 +	while (line[linePos] != '\0') {
 +		if (line[linePos] == ' ' || line[linePos] == '\t') {
 +			if (output == NULL) {
 +				//ignore
 +				linePos += 1;
 +				continue;
 +			}
 +		}
 +		else {
 +			if (output == NULL) {
 +				output = key;
 +			}
 +		}
 +		if (line[linePos] == '=' || line[linePos] == ':' || line[linePos] == '#' || line[linePos] == '!') {
 +			if (precedingCharIsBackslash) {
 +				//escaped special character
 +				output[outputPos++] = line[linePos];
 +				updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
 +				precedingCharIsBackslash = false;
 +			}
 +			else {
 +				if (line[linePos] == '#' || line[linePos] == '!') {
 +					if (outputPos == 0) {
 +						isComment = true;
 +						break;
 +					}
 +					else {
 +						output[outputPos++] = line[linePos];
 +						updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
 +					}
 +				}
 +				else { // = or :
 +					if (output == value) { //already have a seperator
 +						output[outputPos++] = line[linePos];
 +						updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
 +					}
 +					else {
 +						output[outputPos++] = '\0';
 +						updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
 +						output = value;
 +						outputPos = 0;
 +					}
 +				}
 +			}
 +		}
 +		else if (line[linePos] == '\\') {
 +			if (precedingCharIsBackslash) { //double backslash -> backslash
 +				output[outputPos++] = '\\';
 +				updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
 +			}
 +			precedingCharIsBackslash = true;
 +		}
 +		else { //normal character
 +			precedingCharIsBackslash = false;
 +			output[outputPos++] = line[linePos];
 +			updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
 +		}
 +		linePos += 1;
 +	}
 +	if (output != NULL) {
 +		output[outputPos] = '\0';
 +	}
 +
 +	if (!isComment) {
 +		//printf("putting 'key'/'value' '%s'/'%s' in properties\n", utils_stringTrim(key), utils_stringTrim(value));
 +		properties_set(props, utils_stringTrim(key), utils_stringTrim(value));
 +	}
 +	if(key) {
 +		free(key);
 +	}
 +	if(value) {
 +		free(value);
 +	}
 +
 +}


[4/4] celix git commit: Merge branch 'endpoint-format' into develop

Posted by rl...@apache.org.
Merge branch 'endpoint-format' into develop


Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/0a5ef69a
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/0a5ef69a
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/0a5ef69a

Branch: refs/heads/develop
Commit: 0a5ef69a6a6a2167953c4ad4fa807142d46ad768
Parents: a8b8410 9094f55
Author: Roy Lenferink <rl...@apache.org>
Authored: Fri Feb 2 14:01:36 2018 +0100
Committer: Roy Lenferink <rl...@apache.org>
Committed: Fri Feb 2 14:01:36 2018 +0100

----------------------------------------------------------------------
 .../pubsub_admin_udp_mc/src/pubsub_admin_impl.c | 103 ++++++++++++-------
 .../pubsub_admin_udp_mc/src/topic_publication.c |  15 +--
 pubsub/pubsub_admin_zmq/src/pubsub_admin_impl.c |  99 +++++++++++-------
 pubsub/pubsub_admin_zmq/src/topic_publication.c |  13 +--
 pubsub/pubsub_discovery/src/etcd_watcher.c      |  56 +++++++++-
 pubsub/pubsub_discovery/src/etcd_writer.c       |  44 ++++++--
 .../src/pubsub_discovery_impl.c                 |  19 ++--
 pubsub/pubsub_spi/include/pubsub_endpoint.h     |  19 ++--
 pubsub/pubsub_spi/src/pubsub_endpoint.c         |  88 ++++++++++------
 .../src/pubsub_topology_manager.c               |  40 ++++---
 utils/include/properties.h                      |   2 +
 utils/src/properties.c                          |   5 +
 12 files changed, 343 insertions(+), 160 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_admin_udp_mc/src/pubsub_admin_impl.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_admin_udp_mc/src/pubsub_admin_impl.c
index 674f817,0000000..a71344a
mode 100644,000000..100644
--- a/pubsub/pubsub_admin_udp_mc/src/pubsub_admin_impl.c
+++ b/pubsub/pubsub_admin_udp_mc/src/pubsub_admin_impl.c
@@@ -1,1039 -1,0 +1,1062 @@@
 +/**
 + *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_admin_impl.c
 + *
 + *  \date       Sep 30, 2011
 + *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
 + *  \copyright	Apache License, Version 2.0
 + */
 +
 +#include <stdio.h>
 +#include <stdlib.h>
 +
 +#ifndef ANDROID
 +#include <ifaddrs.h>
 +#endif
 +
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <unistd.h>
 +#include <string.h>
 +
 +#include <sys/types.h>
 +#include <sys/socket.h>
 +#include <netinet/in.h>
 +#include <arpa/inet.h>
 +#include <netdb.h>
 +
 +#include "constants.h"
 +#include "utils.h"
 +#include "hash_map.h"
 +#include "array_list.h"
 +#include "bundle_context.h"
 +#include "bundle.h"
 +#include "service_reference.h"
 +#include "service_registration.h"
 +#include "log_helper.h"
 +#include "log_service.h"
 +#include "celix_threads.h"
 +#include "service_factory.h"
 +
 +#include "pubsub_admin_impl.h"
 +#include "topic_subscription.h"
 +#include "topic_publication.h"
 +#include "pubsub_endpoint.h"
 +#include "pubsub/subscriber.h"
 +#include "pubsub_admin_match.h"
 +
 +static const char *DEFAULT_MC_IP = "224.100.1.1";
 +static char *DEFAULT_MC_PREFIX = "224.100";
 +
 +static celix_status_t pubsubAdmin_getIpAddress(const char* interface, char** ip);
 +static celix_status_t pubsubAdmin_addSubscriptionToPendingList(pubsub_admin_pt admin,pubsub_endpoint_pt subEP);
 +static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP);
 +
 +static celix_status_t pubsubAdmin_getBestSerializer(pubsub_admin_pt admin,pubsub_endpoint_pt ep, pubsub_serializer_service_t **serSvc);
 +static void connectTopicPubSubToSerializer(pubsub_admin_pt admin,pubsub_serializer_service_t *serializer,void *topicPubSub,bool isPublication);
 +static void disconnectTopicPubSubFromSerializer(pubsub_admin_pt admin,void *topicPubSub,bool isPublication);
 +
 +celix_status_t pubsubAdmin_create(bundle_context_pt context, pubsub_admin_pt *admin) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	*admin = calloc(1, sizeof(**admin));
 +
 +	if (!*admin) {
 +		return CELIX_ENOMEM;
 +	}
 +
 +	char *mc_ip = NULL;
 +	char *if_ip = NULL;
 +	int sendSocket = -1;
 +
 +	if (logHelper_create(context, &(*admin)->loghelper) == CELIX_SUCCESS) {
 +		logHelper_start((*admin)->loghelper);
 +	}
 +	const char *mc_ip_prop = NULL;
 +	bundleContext_getProperty(context,PSA_IP , &mc_ip_prop);
 +	if(mc_ip_prop) {
 +		mc_ip = strdup(mc_ip_prop);
 +	}
 +
 +#ifndef ANDROID
 +	if (mc_ip == NULL) {
 +		const char *mc_prefix = NULL;
 +		const char *interface = NULL;
 +		int b0 = 0, b1 = 0, b2 = 0, b3 = 0;
 +		bundleContext_getProperty(context,PSA_MULTICAST_IP_PREFIX , &mc_prefix);
 +		if(mc_prefix == NULL) {
 +			mc_prefix = DEFAULT_MC_PREFIX;
 +		}
 +
 +		bundleContext_getProperty(context, PSA_ITF, &interface);
 +		if (pubsubAdmin_getIpAddress(interface, &if_ip) != CELIX_SUCCESS) {
 +			logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "PSA_UDP_MC: Could not retrieve IP address for interface %s", interface);
 +		}
 +
 +		printf("IP Detected : %s\n", if_ip);
 +		if(if_ip && sscanf(if_ip, "%i.%i.%i.%i", &b0, &b1, &b2, &b3) != 4) {
 +			logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "PSA_UDP_MC: Could not parse IP address %s", if_ip);
 +			b2 = 1;
 +			b3 = 1;
 +		}
 +
 +		asprintf(&mc_ip, "%s.%d.%d",mc_prefix, b2, b3);
 +
 +		sendSocket = socket(AF_INET, SOCK_DGRAM, 0);
 +		if(sendSocket == -1) {
 +			perror("pubsubAdmin_create:socket");
 +			status = CELIX_SERVICE_EXCEPTION;
 +		}
 +
 +		if(status == CELIX_SUCCESS){
 +			char loop = 1;
 +			if(setsockopt(sendSocket, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) != 0) {
 +				perror("pubsubAdmin_create:setsockopt(IP_MULTICAST_LOOP)");
 +				status = CELIX_SERVICE_EXCEPTION;
 +			}
 +		}
 +
 +		if(status == CELIX_SUCCESS){
 +			struct in_addr multicast_interface;
 +			inet_aton(if_ip, &multicast_interface);
 +			if(setsockopt(sendSocket,  IPPROTO_IP, IP_MULTICAST_IF, &multicast_interface, sizeof(multicast_interface)) != 0) {
 +				perror("pubsubAdmin_create:setsockopt(IP_MULTICAST_IF)");
 +				status = CELIX_SERVICE_EXCEPTION;
 +			}
 +		}
 +
 +	}
 +
 +
 +	if(status != CELIX_SUCCESS){
 +		logHelper_stop((*admin)->loghelper);
 +		logHelper_destroy(&((*admin)->loghelper));
 +		if(sendSocket >=0){
 +			close(sendSocket);
 +		}
 +		if(if_ip != NULL){
 +			free(if_ip);
 +		}
 +		if(mc_ip != NULL){
 +			free(mc_ip);
 +		}
 +		return status;
 +	}
 +	else{
 +		(*admin)->sendSocket = sendSocket;
 +	}
 +
 +#endif
 +
 +	(*admin)->bundle_context= context;
 +	(*admin)->localPublications = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
 +	(*admin)->subscriptions = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
 +	(*admin)->pendingSubscriptions = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
 +	(*admin)->externalPublications = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
 +	(*admin)->topicSubscriptionsPerSerializer = hashMap_create(NULL, NULL, NULL, NULL);
 +	(*admin)->topicPublicationsPerSerializer  = hashMap_create(NULL, NULL, NULL, NULL);
 +	arrayList_create(&((*admin)->noSerializerSubscriptions));
 +	arrayList_create(&((*admin)->noSerializerPublications));
 +	arrayList_create(&((*admin)->serializerList));
 +
 +	celixThreadMutex_create(&(*admin)->localPublicationsLock, NULL);
 +	celixThreadMutex_create(&(*admin)->subscriptionsLock, NULL);
 +	celixThreadMutex_create(&(*admin)->externalPublicationsLock, NULL);
 +	celixThreadMutex_create(&(*admin)->serializerListLock, NULL);
 +	celixThreadMutex_create(&(*admin)->usedSerializersLock, NULL);
 +
 +	celixThreadMutexAttr_create(&(*admin)->noSerializerPendingsAttr);
 +	celixThreadMutexAttr_settype(&(*admin)->noSerializerPendingsAttr, CELIX_THREAD_MUTEX_RECURSIVE);
 +	celixThreadMutex_create(&(*admin)->noSerializerPendingsLock, &(*admin)->noSerializerPendingsAttr);
 +
 +	celixThreadMutexAttr_create(&(*admin)->pendingSubscriptionsAttr);
 +	celixThreadMutexAttr_settype(&(*admin)->pendingSubscriptionsAttr, CELIX_THREAD_MUTEX_RECURSIVE);
 +	celixThreadMutex_create(&(*admin)->pendingSubscriptionsLock, &(*admin)->pendingSubscriptionsAttr);
 +
 +	if (if_ip != NULL) {
 +		logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "PSA_UDP_MC: Using %s as interface for multicast communication", if_ip);
 +		(*admin)->ifIpAddress = if_ip;
 +	} else {
 +		(*admin)->ifIpAddress = strdup("127.0.0.1");
 +	}
 +
 +	if (mc_ip != NULL) {
 +		logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_INFO, "PSA_UDP_MC: Using %s for service annunciation", mc_ip);
 +		(*admin)->mcIpAddress = mc_ip;
 +	}
 +	else {
 +		logHelper_log((*admin)->loghelper, OSGI_LOGSERVICE_WARNING, "PSA_UDP_MC: No IP address for service annunciation set. Using %s", DEFAULT_MC_IP);
 +		(*admin)->mcIpAddress = strdup(DEFAULT_MC_IP);
 +	}
 +
 +	return status;
 +}
 +
 +
 +celix_status_t pubsubAdmin_destroy(pubsub_admin_pt admin)
 +{
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	free(admin->mcIpAddress);
 +	free(admin->ifIpAddress);
 +
 +	celixThreadMutex_lock(&admin->pendingSubscriptionsLock);
 +	hash_map_iterator_pt iter = hashMapIterator_create(admin->pendingSubscriptions);
 +	while(hashMapIterator_hasNext(iter)){
 +		hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
 +		free((char*)hashMapEntry_getKey(entry));
 +		arrayList_destroy((array_list_pt)hashMapEntry_getValue(entry));
 +	}
 +	hashMapIterator_destroy(iter);
 +	hashMap_destroy(admin->pendingSubscriptions,false,false);
 +	celixThreadMutex_unlock(&admin->pendingSubscriptionsLock);
 +
 +	celixThreadMutex_lock(&admin->subscriptionsLock);
 +	hashMap_destroy(admin->subscriptions,false,false);
 +	celixThreadMutex_unlock(&admin->subscriptionsLock);
 +
 +	celixThreadMutex_lock(&admin->localPublicationsLock);
 +	hashMap_destroy(admin->localPublications,true,false);
 +	celixThreadMutex_unlock(&admin->localPublicationsLock);
 +
 +	celixThreadMutex_lock(&admin->externalPublicationsLock);
 +	iter = hashMapIterator_create(admin->externalPublications);
 +	while(hashMapIterator_hasNext(iter)){
 +		hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
 +		free((char*)hashMapEntry_getKey(entry));
 +		arrayList_destroy((array_list_pt)hashMapEntry_getValue(entry));
 +	}
 +	hashMapIterator_destroy(iter);
 +	hashMap_destroy(admin->externalPublications,false,false);
 +	celixThreadMutex_unlock(&admin->externalPublicationsLock);
 +
 +	celixThreadMutex_lock(&admin->serializerListLock);
 +	arrayList_destroy(admin->serializerList);
 +	celixThreadMutex_unlock(&admin->serializerListLock);
 +
 +	celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +	arrayList_destroy(admin->noSerializerSubscriptions);
 +	arrayList_destroy(admin->noSerializerPublications);
 +	celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +
 +	celixThreadMutex_lock(&admin->usedSerializersLock);
 +
 +	iter = hashMapIterator_create(admin->topicSubscriptionsPerSerializer);
 +	while(hashMapIterator_hasNext(iter)){
 +		arrayList_destroy((array_list_pt)hashMapIterator_nextValue(iter));
 +	}
 +	hashMapIterator_destroy(iter);
 +	hashMap_destroy(admin->topicSubscriptionsPerSerializer,false,false);
 +
 +	iter = hashMapIterator_create(admin->topicPublicationsPerSerializer);
 +	while(hashMapIterator_hasNext(iter)){
 +		arrayList_destroy((array_list_pt)hashMapIterator_nextValue(iter));
 +	}
 +	hashMapIterator_destroy(iter);
 +	hashMap_destroy(admin->topicPublicationsPerSerializer,false,false);
 +
 +	celixThreadMutex_unlock(&admin->usedSerializersLock);
 +
 +	celixThreadMutex_destroy(&admin->usedSerializersLock);
 +	celixThreadMutex_destroy(&admin->serializerListLock);
 +
 +	celixThreadMutexAttr_destroy(&admin->noSerializerPendingsAttr);
 +	celixThreadMutex_destroy(&admin->noSerializerPendingsLock);
 +
 +	celixThreadMutex_destroy(&admin->pendingSubscriptionsLock);
 +	celixThreadMutexAttr_destroy(&admin->pendingSubscriptionsAttr);
 +
 +	celixThreadMutex_destroy(&admin->subscriptionsLock);
 +	celixThreadMutex_destroy(&admin->localPublicationsLock);
 +	celixThreadMutex_destroy(&admin->externalPublicationsLock);
 +
 +	logHelper_stop(admin->loghelper);
 +
 +	logHelper_destroy(&admin->loghelper);
 +
 +	free(admin);
 +
 +	return status;
 +}
 +
 +static celix_status_t pubsubAdmin_addAnySubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	celixThreadMutex_lock(&admin->subscriptionsLock);
 +
 +	topic_subscription_pt any_sub = hashMap_get(admin->subscriptions,PUBSUB_ANY_SUB_TOPIC);
 +
 +	if(any_sub==NULL){
 +
 +		int i;
 +		pubsub_serializer_service_t *best_serializer = NULL;
 +		if( (status=pubsubAdmin_getBestSerializer(admin, subEP, &best_serializer)) == CELIX_SUCCESS){
 +			status = pubsub_topicSubscriptionCreate(admin->bundle_context, admin->ifIpAddress, PUBSUB_SUBSCRIBER_SCOPE_DEFAULT, PUBSUB_ANY_SUB_TOPIC, best_serializer, &any_sub);
 +		}
 +		else{
- 			printf("PSA_UDP_MC: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",subEP->topic);
++			printf("PSA_UDP_MC: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",
++				   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
++
 +			celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +			arrayList_add(admin->noSerializerSubscriptions,subEP);
 +			celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +		}
 +
 +		if (status == CELIX_SUCCESS){
 +
 +			/* Connect all internal publishers */
 +			celixThreadMutex_lock(&admin->localPublicationsLock);
 +			hash_map_iterator_pt lp_iter =hashMapIterator_create(admin->localPublications);
 +			while(hashMapIterator_hasNext(lp_iter)){
 +				service_factory_pt factory = (service_factory_pt)hashMapIterator_nextValue(lp_iter);
 +				topic_publication_pt topic_pubs = (topic_publication_pt)factory->handle;
 +				array_list_pt topic_publishers = pubsub_topicPublicationGetPublisherList(topic_pubs);
 +
 +				if(topic_publishers!=NULL){
 +					for(i=0;i<arrayList_size(topic_publishers);i++){
 +						pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(topic_publishers,i);
- 						if(pubEP->endpoint !=NULL){
- 							status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint);
++						if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
++							status += pubsub_topicSubscriptionConnectPublisher(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +						}
 +					}
 +					arrayList_destroy(topic_publishers);
 +				}
 +			}
 +			hashMapIterator_destroy(lp_iter);
 +			celixThreadMutex_unlock(&admin->localPublicationsLock);
 +
 +			/* Connect also all external publishers */
 +			celixThreadMutex_lock(&admin->externalPublicationsLock);
 +			hash_map_iterator_pt extp_iter =hashMapIterator_create(admin->externalPublications);
 +			while(hashMapIterator_hasNext(extp_iter)){
 +				array_list_pt ext_pub_list = (array_list_pt)hashMapIterator_nextValue(extp_iter);
 +				if(ext_pub_list!=NULL){
 +					for(i=0;i<arrayList_size(ext_pub_list);i++){
 +						pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- 						if(pubEP->endpoint !=NULL){
- 							status += pubsub_topicSubscriptionConnectPublisher(any_sub,pubEP->endpoint);
++						if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
++							status += pubsub_topicSubscriptionConnectPublisher(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +						}
 +					}
 +				}
 +			}
 +			hashMapIterator_destroy(extp_iter);
 +			celixThreadMutex_unlock(&admin->externalPublicationsLock);
 +
 +
 +			pubsub_topicSubscriptionAddSubscriber(any_sub,subEP);
 +
 +			status += pubsub_topicSubscriptionStart(any_sub);
 +
 +		}
 +
 +		if (status == CELIX_SUCCESS){
 +			hashMap_put(admin->subscriptions,strdup(PUBSUB_ANY_SUB_TOPIC),any_sub);
 +			connectTopicPubSubToSerializer(admin, best_serializer, any_sub, false);
 +		}
 +
 +	}
 +
 +	celixThreadMutex_unlock(&admin->subscriptionsLock);
 +
 +	return status;
 +}
 +
 +celix_status_t pubsubAdmin_addSubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
 +	celix_status_t status = CELIX_SUCCESS;
 +
- 	printf("PSA_UDP_MC: Received subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",subEP->frameworkUUID,subEP->serviceID,subEP->scope,subEP->topic);
++	printf("PSA_UDP_MC: Received subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",
++		   properties_get(subEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++		   subEP->serviceID,
++		   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++		   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
- 	if(strcmp(subEP->topic,PUBSUB_ANY_SUB_TOPIC)==0){
++	if(strcmp(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),PUBSUB_ANY_SUB_TOPIC)==0){
 +		return pubsubAdmin_addAnySubscription(admin,subEP);
 +	}
 +
 +	/* Check if we already know some publisher about this topic, otherwise let's put the subscription in the pending hashmap */
 +	celixThreadMutex_lock(&admin->pendingSubscriptionsLock);
 +	celixThreadMutex_lock(&admin->subscriptionsLock);
 +	celixThreadMutex_lock(&admin->localPublicationsLock);
 +	celixThreadMutex_lock(&admin->externalPublicationsLock);
 +
- 	char* scope_topic = createScopeTopicKey(subEP->scope,subEP->topic);
++	char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
 +	service_factory_pt factory = (service_factory_pt)hashMap_get(admin->localPublications,scope_topic);
 +	array_list_pt ext_pub_list = (array_list_pt)hashMap_get(admin->externalPublications,scope_topic);
 +
 +	if(factory==NULL && ext_pub_list==NULL){ //No (local or external) publishers yet for this topic
 +		pubsubAdmin_addSubscriptionToPendingList(admin,subEP);
 +	}
 +	else{
 +		int i;
 +		topic_subscription_pt subscription = hashMap_get(admin->subscriptions, scope_topic);
 +
 +		if(subscription == NULL) {
 +			pubsub_serializer_service_t *best_serializer = NULL;
 +			if( (status=pubsubAdmin_getBestSerializer(admin, subEP, &best_serializer)) == CELIX_SUCCESS){
- 				status += pubsub_topicSubscriptionCreate(admin->bundle_context,admin->ifIpAddress, subEP->scope, subEP->topic, best_serializer, &subscription);
++				status += pubsub_topicSubscriptionCreate(admin->bundle_context,admin->ifIpAddress, (char*) properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), (char*) properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC), best_serializer, &subscription);
 +			}
 +			else{
- 				printf("PSA_UDP_MC: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",subEP->topic);
++				printf("PSA_UDP_MC: Cannot find a serializer for subscribing topic %s. Adding it to pending list.\n",
++					   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
++
 +				celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +				arrayList_add(admin->noSerializerSubscriptions,subEP);
 +				celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +			}
 +
 +			if (status==CELIX_SUCCESS){
 +
 +				/* Try to connect internal publishers */
 +				if(factory!=NULL){
 +					topic_publication_pt topic_pubs = (topic_publication_pt)factory->handle;
 +					array_list_pt topic_publishers = pubsub_topicPublicationGetPublisherList(topic_pubs);
 +
 +					if(topic_publishers!=NULL){
 +						for(i=0;i<arrayList_size(topic_publishers);i++){
 +							pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(topic_publishers,i);
- 							if(pubEP->endpoint !=NULL){
- 								status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint);
++							if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
++								status += pubsub_topicSubscriptionConnectPublisher(subscription, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +							}
 +						}
 +						arrayList_destroy(topic_publishers);
 +					}
 +
 +				}
 +
 +				/* Look also for external publishers */
 +				if(ext_pub_list!=NULL){
 +					for(i=0;i<arrayList_size(ext_pub_list);i++){
 +						pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- 						if(pubEP->endpoint !=NULL){
- 							status += pubsub_topicSubscriptionConnectPublisher(subscription,pubEP->endpoint);
++						if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) !=NULL){
++							status += pubsub_topicSubscriptionConnectPublisher(subscription, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +						}
 +					}
 +				}
 +
 +				pubsub_topicSubscriptionAddSubscriber(subscription,subEP);
 +
 +				status += pubsub_topicSubscriptionStart(subscription);
 +
 +			}
 +
 +			if(status==CELIX_SUCCESS){
 +
 +				hashMap_put(admin->subscriptions,strdup(scope_topic),subscription);
 +
 +				connectTopicPubSubToSerializer(admin, best_serializer, subscription, false);
 +			}
 +		}
 +
 +		if (status == CELIX_SUCCESS){
 +			pubsub_topicIncreaseNrSubscribers(subscription);
 +		}
 +	}
 +
 +	free(scope_topic);
 +	celixThreadMutex_unlock(&admin->externalPublicationsLock);
 +	celixThreadMutex_unlock(&admin->localPublicationsLock);
 +	celixThreadMutex_unlock(&admin->subscriptionsLock);
 +	celixThreadMutex_unlock(&admin->pendingSubscriptionsLock);
 +
 +	return status;
 +
 +}
 +
 +celix_status_t pubsubAdmin_removeSubscription(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
 +	celix_status_t status = CELIX_SUCCESS;
 +
- 	printf("PSA_UDP_MC: Removing subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",subEP->frameworkUUID,subEP->serviceID,subEP->scope, subEP->topic);
++	printf("PSA_UDP_MC: Removing subscription [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",
++		   properties_get(subEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++		   subEP->serviceID,
++		   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++		   properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
- 	char* scope_topic = createScopeTopicKey(subEP->scope, subEP->topic);
++	char* scope_topic = createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
 +	celixThreadMutex_lock(&admin->subscriptionsLock);
 +	topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic);
 +	if(sub!=NULL){
 +		pubsub_topicDecreaseNrSubscribers(sub);
 +		if(pubsub_topicGetNrSubscribers(sub) == 0) {
 +			status = pubsub_topicSubscriptionRemoveSubscriber(sub,subEP);
 +		}
 +	}
 +	celixThreadMutex_unlock(&admin->subscriptionsLock);
 +
 +	if(sub==NULL){
 +		/* Maybe the endpoint was pending */
 +		celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +		if(!arrayList_removeElement(admin->noSerializerSubscriptions, subEP)){
 +			status = CELIX_ILLEGAL_STATE;
 +		}
 +		celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +	}
 +
 +	free(scope_topic);
 +
 +
 +
 +	return status;
 +
 +}
 +
 +celix_status_t pubsubAdmin_addPublication(pubsub_admin_pt admin,pubsub_endpoint_pt pubEP){
 +	celix_status_t status = CELIX_SUCCESS;
 +
- 	printf("PSA_UDP_MC: Received publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",pubEP->frameworkUUID,pubEP->serviceID,pubEP->scope, pubEP->topic);
++	printf("PSA_UDP_MC: Received publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",
++		   properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++		   pubEP->serviceID,
++		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
 +	const char* fwUUID = NULL;
 +
 +	bundleContext_getProperty(admin->bundle_context,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID);
 +	if(fwUUID==NULL){
 +		printf("PSA_UDP_MC: Cannot retrieve fwUUID.\n");
 +		return CELIX_INVALID_BUNDLE_CONTEXT;
 +	}
- 	char* scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic);
++	char* scope_topic = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
- 	if ((strcmp(pubEP->frameworkUUID, fwUUID) == 0) && (pubEP->endpoint == NULL)) {
++	if ((strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID), fwUUID) == 0) && (properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) == NULL)) {
 +
 +		celixThreadMutex_lock(&admin->localPublicationsLock);
 +
 +		service_factory_pt factory = (service_factory_pt) hashMap_get(admin->localPublications, scope_topic);
 +
 +		if (factory == NULL) {
 +			topic_publication_pt pub = NULL;
 +			pubsub_serializer_service_t *best_serializer = NULL;
 +			if( (status=pubsubAdmin_getBestSerializer(admin, pubEP, &best_serializer)) == CELIX_SUCCESS){
 +				status = pubsub_topicPublicationCreate(admin->sendSocket, pubEP, best_serializer, admin->mcIpAddress, &pub);
 +			}
 +			else{
- 				printf("PSA_UDP_MC: Cannot find a serializer for publishing topic %s. Adding it to pending list.\n", pubEP->topic);
++				printf("PSA_UDP_MC: Cannot find a serializer for publishing topic %s. Adding it to pending list.\n",
++					   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
++
 +				celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +				arrayList_add(admin->noSerializerPublications,pubEP);
 +				celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +			}
 +
 +			if (status == CELIX_SUCCESS) {
 +				status = pubsub_topicPublicationStart(admin->bundle_context, pub, &factory);
 +				if (status == CELIX_SUCCESS && factory != NULL) {
 +					hashMap_put(admin->localPublications, strdup(scope_topic), factory);
 +					connectTopicPubSubToSerializer(admin, best_serializer, pub, true);
 +				}
 +			} else {
- 				printf("PSA_UDP_MC: Cannot create a topicPublication for scope=%s, topic=%s (bundle %ld).\n", pubEP->scope, pubEP->topic, pubEP->serviceID);
++				printf("PSA_UDP_MC: Cannot create a topicPublication for scope=%s, topic=%s (bundle %ld).\n",
++					   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++					   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++					   pubEP->serviceID);
 +			}
 +		} else {
 +			//just add the new EP to the list
 +			topic_publication_pt pub = (topic_publication_pt) factory->handle;
 +			pubsub_topicPublicationAddPublisherEP(pub, pubEP);
 +		}
 +
 +		celixThreadMutex_unlock(&admin->localPublicationsLock);
 +	}
 +	else{
 +
 +		celixThreadMutex_lock(&admin->externalPublicationsLock);
 +		array_list_pt ext_pub_list = (array_list_pt) hashMap_get(admin->externalPublications, scope_topic);
 +		if (ext_pub_list == NULL) {
 +			arrayList_create(&ext_pub_list);
 +			hashMap_put(admin->externalPublications, strdup(scope_topic), ext_pub_list);
 +		}
 +
 +		arrayList_add(ext_pub_list, pubEP);
 +
 +		celixThreadMutex_unlock(&admin->externalPublicationsLock);
 +	}
 +
 +	/* Re-evaluate the pending subscriptions */
 +	celixThreadMutex_lock(&admin->pendingSubscriptionsLock);
 +
 +	hash_map_entry_pt pendingSub = hashMap_getEntry(admin->pendingSubscriptions, scope_topic);
 +	if (pendingSub != NULL) { //There were pending subscription for the just published topic. Let's connect them.
 +		char* topic = (char*) hashMapEntry_getKey(pendingSub);
 +		array_list_pt pendingSubList = (array_list_pt) hashMapEntry_getValue(pendingSub);
 +		int i;
 +		for (i = 0; i < arrayList_size(pendingSubList); i++) {
 +			pubsub_endpoint_pt subEP = (pubsub_endpoint_pt) arrayList_get(pendingSubList, i);
 +			pubsubAdmin_addSubscription(admin, subEP);
 +		}
 +		hashMap_remove(admin->pendingSubscriptions, scope_topic);
 +		arrayList_clear(pendingSubList);
 +		arrayList_destroy(pendingSubList);
 +		free(topic);
 +	}
 +
 +	celixThreadMutex_unlock(&admin->pendingSubscriptionsLock);
 +
 +	/* Connect the new publisher to the subscription for his topic, if there is any */
 +	celixThreadMutex_lock(&admin->subscriptionsLock);
 +
 +	topic_subscription_pt sub = (topic_subscription_pt) hashMap_get(admin->subscriptions, scope_topic);
- 	if (sub != NULL && pubEP->endpoint != NULL) {
- 		pubsub_topicSubscriptionAddConnectPublisherToPendingList(sub, pubEP->endpoint);
++	if (sub != NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) != NULL) {
++		pubsub_topicSubscriptionAddConnectPublisherToPendingList(sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +	}
 +
 +	/* And check also for ANY subscription */
 +	topic_subscription_pt any_sub = (topic_subscription_pt) hashMap_get(admin->subscriptions, PUBSUB_ANY_SUB_TOPIC);
- 	if (any_sub != NULL && pubEP->endpoint != NULL) {
- 		pubsub_topicSubscriptionAddConnectPublisherToPendingList(any_sub, pubEP->endpoint);
++	if (any_sub != NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL) != NULL) {
++		pubsub_topicSubscriptionAddConnectPublisherToPendingList(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +	}
 +
 +	free(scope_topic);
 +
 +	celixThreadMutex_unlock(&admin->subscriptionsLock);
 +
 +	return status;
 +
 +}
 +
 +celix_status_t pubsubAdmin_removePublication(pubsub_admin_pt admin,pubsub_endpoint_pt pubEP){
 +	celix_status_t status = CELIX_SUCCESS;
 +	int count = 0;
 +
- 	printf("PSA_UDP_MC: Removing publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",pubEP->frameworkUUID,pubEP->serviceID,pubEP->scope, pubEP->topic);
++	printf("PSA_UDP_MC: Removing publication [FWUUID=%s bundleID=%ld scope=%s, topic=%s]\n",
++		   properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),
++		   pubEP->serviceID,
++		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++		   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
 +	const char* fwUUID = NULL;
 +
 +	bundleContext_getProperty(admin->bundle_context,OSGI_FRAMEWORK_FRAMEWORK_UUID,&fwUUID);
 +	if(fwUUID==NULL){
 +		printf("PSA_UDP_MC: Cannot retrieve fwUUID.\n");
 +		return CELIX_INVALID_BUNDLE_CONTEXT;
 +	}
- 	char *scope_topic = createScopeTopicKey(pubEP->scope, pubEP->topic);
++	char *scope_topic = createScopeTopicKey(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
- 	if(strcmp(pubEP->frameworkUUID,fwUUID)==0){
++	if(strcmp(properties_get(pubEP->endpoint_props, OSGI_FRAMEWORK_FRAMEWORK_UUID),fwUUID)==0){
 +
 +		celixThreadMutex_lock(&admin->localPublicationsLock);
 +		service_factory_pt factory = (service_factory_pt)hashMap_get(admin->localPublications,scope_topic);
 +		if(factory!=NULL){
 +			topic_publication_pt pub = (topic_publication_pt)factory->handle;
 +			pubsub_topicPublicationRemovePublisherEP(pub,pubEP);
 +		}
 +		celixThreadMutex_unlock(&admin->localPublicationsLock);
 +
 +		if(factory==NULL){
 +			/* Maybe the endpoint was pending */
 +			celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +			if(!arrayList_removeElement(admin->noSerializerPublications, pubEP)){
 +				status = CELIX_ILLEGAL_STATE;
 +			}
 +			celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +		}
 +
 +	}
 +	else{
 +
 +		celixThreadMutex_lock(&admin->externalPublicationsLock);
 +		array_list_pt ext_pub_list = (array_list_pt)hashMap_get(admin->externalPublications,scope_topic);
 +		if(ext_pub_list!=NULL){
 +			int i;
 +			bool found = false;
 +			for(i=0;!found && i<arrayList_size(ext_pub_list);i++){
 +				pubsub_endpoint_pt p  = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
 +				found = pubsubEndpoint_equals(pubEP,p);
 +				if (found){
 +					arrayList_remove(ext_pub_list,i);
 +				}
 +			}
 +			// Check if there are more publishers on the same endpoint (happens when 1 celix-instance with multiple bundles publish in same topic)
 +			for(i=0; i<arrayList_size(ext_pub_list);i++) {
 +				pubsub_endpoint_pt p  = (pubsub_endpoint_pt)arrayList_get(ext_pub_list,i);
- 				if (strcmp(pubEP->endpoint,p->endpoint) == 0) {
++				if (strcmp(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL),properties_get(p->endpoint_props, PUBSUB_ENDPOINT_URL)) == 0) {
 +					count++;
 +				}
 +			}
 +
 +			if(arrayList_size(ext_pub_list)==0){
 +				hash_map_entry_pt entry = hashMap_getEntry(admin->externalPublications,scope_topic);
 +				char* topic = (char*)hashMapEntry_getKey(entry);
 +				array_list_pt list = (array_list_pt)hashMapEntry_getValue(entry);
 +				hashMap_remove(admin->externalPublications,topic);
 +				arrayList_destroy(list);
 +				free(topic);
 +			}
 +		}
 +
 +		celixThreadMutex_unlock(&admin->externalPublicationsLock);
 +	}
 +
 +	/* Check if this publisher was connected to one of our subscribers*/
 +	celixThreadMutex_lock(&admin->subscriptionsLock);
 +
 +	topic_subscription_pt sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,scope_topic);
- 	if(sub!=NULL && pubEP->endpoint!=NULL && count == 0){
- 		pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub,pubEP->endpoint);
++	if(sub!=NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL && count == 0){
++		pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +	}
 +
 +	/* And check also for ANY subscription */
 +	topic_subscription_pt any_sub = (topic_subscription_pt)hashMap_get(admin->subscriptions,PUBSUB_ANY_SUB_TOPIC);
- 	if(any_sub!=NULL && pubEP->endpoint!=NULL && count == 0){
- 		pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(any_sub,pubEP->endpoint);
++	if(any_sub!=NULL && properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL && count == 0){
++		pubsub_topicSubscriptionAddDisconnectPublisherToPendingList(any_sub, (char*) properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL));
 +	}
 +
 +	free(scope_topic);
 +	celixThreadMutex_unlock(&admin->subscriptionsLock);
 +
 +	return status;
 +
 +}
 +
 +celix_status_t pubsubAdmin_closeAllPublications(pubsub_admin_pt admin,char *scope, char* topic){
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	printf("PSA_UDP_MC: Closing all publications for scope=%s,topic=%s\n", scope, topic);
 +
 +	celixThreadMutex_lock(&admin->localPublicationsLock);
 +	char* scope_topic =createScopeTopicKey(scope, topic);
 +	hash_map_entry_pt pubsvc_entry = (hash_map_entry_pt)hashMap_getEntry(admin->localPublications,scope_topic);
 +	if(pubsvc_entry!=NULL){
 +		char* key = (char*)hashMapEntry_getKey(pubsvc_entry);
 +		service_factory_pt factory= (service_factory_pt)hashMapEntry_getValue(pubsvc_entry);
 +		topic_publication_pt pub = (topic_publication_pt)factory->handle;
 +		status += pubsub_topicPublicationStop(pub);
 +		disconnectTopicPubSubFromSerializer(admin, pub, true);
 +		status += pubsub_topicPublicationDestroy(pub);
 +		hashMap_remove(admin->localPublications,scope_topic);
 +		free(key);
 +		free(factory);
 +	}
 +	free(scope_topic);
 +	celixThreadMutex_unlock(&admin->localPublicationsLock);
 +
 +	return status;
 +
 +}
 +
 +celix_status_t pubsubAdmin_closeAllSubscriptions(pubsub_admin_pt admin,char *scope, char* topic){
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	printf("PSA_UDP_MC: Closing all subscriptions\n");
 +
 +	celixThreadMutex_lock(&admin->subscriptionsLock);
 +	char* scope_topic =createScopeTopicKey(scope, topic);
 +	hash_map_entry_pt sub_entry = (hash_map_entry_pt)hashMap_getEntry(admin->subscriptions,scope_topic);
 +	if(sub_entry!=NULL){
 +		char* topic = (char*)hashMapEntry_getKey(sub_entry);
 +
 +		topic_subscription_pt ts = (topic_subscription_pt)hashMapEntry_getValue(sub_entry);
 +		status += pubsub_topicSubscriptionStop(ts);
 +		disconnectTopicPubSubFromSerializer(admin, ts, false);
 +		status += pubsub_topicSubscriptionDestroy(ts);
 +		hashMap_remove(admin->subscriptions,topic);
 +		free(topic);
 +
 +	}
 +	free(scope_topic);
 +	celixThreadMutex_unlock(&admin->subscriptionsLock);
 +
 +	return status;
 +
 +}
 +
 +
 +#ifndef ANDROID
 +static celix_status_t pubsubAdmin_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
 +
 +static celix_status_t pubsubAdmin_addSubscriptionToPendingList(pubsub_admin_pt admin,pubsub_endpoint_pt subEP){
 +	celix_status_t status = CELIX_SUCCESS;
 +
- 	char* scope_topic =createScopeTopicKey(subEP->scope, subEP->topic);
++	char* scope_topic =createScopeTopicKey(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE), properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +	array_list_pt pendingListPerTopic = hashMap_get(admin->pendingSubscriptions,scope_topic);
 +	if(pendingListPerTopic==NULL){
 +		arrayList_create(&pendingListPerTopic);
 +		hashMap_put(admin->pendingSubscriptions,strdup(scope_topic),pendingListPerTopic);
 +	}
 +	arrayList_add(pendingListPerTopic,subEP);
 +	free(scope_topic);
 +
 +	return status;
 +}
 +
 +
 +celix_status_t pubsubAdmin_serializerAdded(void * handle, service_reference_pt reference, void * service){
 +	/* Assumption: serializers are all available at startup.
 +	 * If a new (possibly better) serializer is installed and started, already created topic_publications/subscriptions will not be destroyed and recreated */
 +
 +	celix_status_t status = CELIX_SUCCESS;
 +	int i=0;
 +
 +	const char *serType = NULL;
 +	serviceReference_getProperty(reference, PUBSUB_SERIALIZER_TYPE_KEY,&serType);
 +	if(serType == NULL){
 +		printf("Serializer serviceReference %p has no pubsub_serializer.type property specified\n",reference);
 +		return CELIX_SERVICE_EXCEPTION;
 +	}
 +
 +	pubsub_admin_pt admin = (pubsub_admin_pt)handle;
 +	celixThreadMutex_lock(&admin->serializerListLock);
 +	arrayList_add(admin->serializerList, reference);
 +	celixThreadMutex_unlock(&admin->serializerListLock);
 +
 +	/* Now let's re-evaluate the pending */
 +	celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +
 +	for(i=0;i<arrayList_size(admin->noSerializerSubscriptions);i++){
 +		pubsub_endpoint_pt ep = (pubsub_endpoint_pt)arrayList_get(admin->noSerializerSubscriptions,i);
 +		pubsub_serializer_service_t *best_serializer = NULL;
 +		pubsubAdmin_getBestSerializer(admin, ep, &best_serializer);
 +		if(best_serializer != NULL){ /* Finally we have a valid serializer! */
 +			pubsubAdmin_addSubscription(admin, ep);
 +		}
 +	}
 +
 +	for(i=0;i<arrayList_size(admin->noSerializerPublications);i++){
 +		pubsub_endpoint_pt ep = (pubsub_endpoint_pt)arrayList_get(admin->noSerializerPublications,i);
 +		pubsub_serializer_service_t *best_serializer = NULL;
 +		pubsubAdmin_getBestSerializer(admin, ep, &best_serializer);
 +		if(best_serializer != NULL){ /* Finally we have a valid serializer! */
 +			pubsubAdmin_addPublication(admin, ep);
 +		}
 +	}
 +
 +	celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +
 +	printf("PSA_UDP_MC: %s serializer added\n",serType);
 +
 +	return status;
 +}
 +
 +celix_status_t pubsubAdmin_serializerRemoved(void * handle, service_reference_pt reference, void * service){
 +
 +	pubsub_admin_pt admin = (pubsub_admin_pt)handle;
 +	int i=0, j=0;
 +	const char *serType = NULL;
 +
 +	serviceReference_getProperty(reference, PUBSUB_SERIALIZER_TYPE_KEY,&serType);
 +	if(serType == NULL){
 +		printf("Serializer serviceReference %p has no pubsub_serializer.type property specified\n",reference);
 +		return CELIX_SERVICE_EXCEPTION;
 +	}
 +
 +	celixThreadMutex_lock(&admin->serializerListLock);
 +	/* Remove the serializer from the list */
 +	arrayList_removeElement(admin->serializerList, reference);
 +	celixThreadMutex_unlock(&admin->serializerListLock);
 +
 +	celixThreadMutex_lock(&admin->usedSerializersLock);
 +	array_list_pt topicPubList = (array_list_pt)hashMap_remove(admin->topicPublicationsPerSerializer, service);
 +	array_list_pt topicSubList = (array_list_pt)hashMap_remove(admin->topicSubscriptionsPerSerializer, service);
 +	celixThreadMutex_unlock(&admin->usedSerializersLock);
 +
 +	/* Now destroy the topicPublications, but first put back the pubsub_endpoints back to the noSerializer pending list */
 +	if(topicPubList!=NULL){
 +		for(i=0;i<arrayList_size(topicPubList);i++){
 +			topic_publication_pt topicPub = (topic_publication_pt)arrayList_get(topicPubList,i);
 +			/* Stop the topic publication */
 +			pubsub_topicPublicationStop(topicPub);
 +			/* Get the endpoints that are going to be orphan */
 +			array_list_pt pubList = pubsub_topicPublicationGetPublisherList(topicPub);
 +			for(j=0;j<arrayList_size(pubList);j++){
 +				pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pubList,j);
 +				/* Remove the publication */
 +				pubsubAdmin_removePublication(admin, pubEP);
 +				/* Reset the endpoint field, so that will be recreated from scratch when a new serializer will be found */
- 				if(pubEP->endpoint!=NULL){
- 					free(pubEP->endpoint);
- 					pubEP->endpoint = NULL;
++				if(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL){
++					properties_unset(pubEP->endpoint_props, PUBSUB_ENDPOINT_URL);
 +				}
 +				/* Add the orphan endpoint to the noSerializer pending list */
 +				celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +				arrayList_add(admin->noSerializerPublications,pubEP);
 +				celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +			}
 +			arrayList_destroy(pubList);
 +
 +			/* Cleanup also the localPublications hashmap*/
 +			celixThreadMutex_lock(&admin->localPublicationsLock);
 +			hash_map_iterator_pt iter = hashMapIterator_create(admin->localPublications);
 +			char *key = NULL;
 +			service_factory_pt factory = NULL;
 +			while(hashMapIterator_hasNext(iter)){
 +				hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
 +				factory = (service_factory_pt)hashMapEntry_getValue(entry);
 +				topic_publication_pt pub = (topic_publication_pt)factory->handle;
 +				if(pub==topicPub){
 +					key = (char*)hashMapEntry_getKey(entry);
 +					break;
 +				}
 +			}
 +			hashMapIterator_destroy(iter);
 +			if(key!=NULL){
 +				hashMap_remove(admin->localPublications, key);
 +				free(factory);
 +				free(key);
 +			}
 +			celixThreadMutex_unlock(&admin->localPublicationsLock);
 +
 +			/* Finally destroy the topicPublication */
 +			pubsub_topicPublicationDestroy(topicPub);
 +		}
 +		arrayList_destroy(topicPubList);
 +	}
 +
 +	/* Now destroy the topicSubscriptions, but first put back the pubsub_endpoints back to the noSerializer pending list */
 +	if(topicSubList!=NULL){
 +		for(i=0;i<arrayList_size(topicSubList);i++){
 +			topic_subscription_pt topicSub = (topic_subscription_pt)arrayList_get(topicSubList,i);
 +			/* Stop the topic subscription */
 +			pubsub_topicSubscriptionStop(topicSub);
 +			/* Get the endpoints that are going to be orphan */
 +			array_list_pt subList = pubsub_topicSubscriptionGetSubscribersList(topicSub);
 +			for(j=0;j<arrayList_size(subList);j++){
 +				pubsub_endpoint_pt subEP = (pubsub_endpoint_pt)arrayList_get(subList,j);
 +				/* Remove the subscription */
 +				pubsubAdmin_removeSubscription(admin, subEP);
 +				/* Reset the endpoint field, so that will be recreated from scratch when a new serializer will be found */
- 				if(subEP->endpoint!=NULL){
- 					free(subEP->endpoint);
- 					subEP->endpoint = NULL;
++				if(properties_get(subEP->endpoint_props, PUBSUB_ENDPOINT_URL)!=NULL){
++					properties_unset(subEP->endpoint_props, PUBSUB_ENDPOINT_URL);
 +				}
 +				/* Add the orphan endpoint to the noSerializer pending list */
 +				celixThreadMutex_lock(&admin->noSerializerPendingsLock);
 +				arrayList_add(admin->noSerializerSubscriptions,subEP);
 +				celixThreadMutex_unlock(&admin->noSerializerPendingsLock);
 +			}
 +
 +			/* Cleanup also the subscriptions hashmap*/
 +			celixThreadMutex_lock(&admin->subscriptionsLock);
 +			hash_map_iterator_pt iter = hashMapIterator_create(admin->subscriptions);
 +			char *key = NULL;
 +			while(hashMapIterator_hasNext(iter)){
 +				hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
 +				topic_subscription_pt sub = (topic_subscription_pt)hashMapEntry_getValue(entry);
 +				if(sub==topicSub){
 +					key = (char*)hashMapEntry_getKey(entry);
 +					break;
 +				}
 +			}
 +			hashMapIterator_destroy(iter);
 +			if(key!=NULL){
 +				hashMap_remove(admin->subscriptions, key);
 +				free(key);
 +			}
 +			celixThreadMutex_unlock(&admin->subscriptionsLock);
 +
 +			/* Finally destroy the topicSubscription */
 +			pubsub_topicSubscriptionDestroy(topicSub);
 +		}
 +		arrayList_destroy(topicSubList);
 +	}
 +
 +	printf("PSA_UDP_MC: %s serializer removed\n",serType);
 +
 +
 +	return CELIX_SUCCESS;
 +}
 +
 +celix_status_t pubsubAdmin_matchEndpoint(pubsub_admin_pt admin, pubsub_endpoint_pt endpoint, double* score){
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	celixThreadMutex_lock(&admin->serializerListLock);
 +	status = pubsub_admin_match(endpoint->topic_props,PUBSUB_ADMIN_TYPE,admin->serializerList,score);
 +	celixThreadMutex_unlock(&admin->serializerListLock);
 +
 +	return status;
 +}
 +
 +/* This one recall the same logic as in the match function */
 +static celix_status_t pubsubAdmin_getBestSerializer(pubsub_admin_pt admin,pubsub_endpoint_pt ep, pubsub_serializer_service_t **serSvc){
 +
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	celixThreadMutex_lock(&admin->serializerListLock);
 +	status = pubsub_admin_get_best_serializer(ep->topic_props, admin->serializerList, serSvc);
 +	celixThreadMutex_unlock(&admin->serializerListLock);
 +
 +	return status;
 +
 +}
 +
 +static void connectTopicPubSubToSerializer(pubsub_admin_pt admin,pubsub_serializer_service_t *serializer,void *topicPubSub,bool isPublication){
 +
 +	celixThreadMutex_lock(&admin->usedSerializersLock);
 +
 +	hash_map_pt map = isPublication?admin->topicPublicationsPerSerializer:admin->topicSubscriptionsPerSerializer;
 +	array_list_pt list = (array_list_pt)hashMap_get(map,serializer);
 +	if(list==NULL){
 +		arrayList_create(&list);
 +		hashMap_put(map,serializer,list);
 +	}
 +	arrayList_add(list,topicPubSub);
 +
 +	celixThreadMutex_unlock(&admin->usedSerializersLock);
 +
 +}
 +
 +static void disconnectTopicPubSubFromSerializer(pubsub_admin_pt admin,void *topicPubSub,bool isPublication){
 +
 +	celixThreadMutex_lock(&admin->usedSerializersLock);
 +
 +	hash_map_pt map = isPublication?admin->topicPublicationsPerSerializer:admin->topicSubscriptionsPerSerializer;
 +	hash_map_iterator_pt iter = hashMapIterator_create(map);
 +	while(hashMapIterator_hasNext(iter)){
 +		array_list_pt list = (array_list_pt)hashMapIterator_nextValue(iter);
 +		if(arrayList_removeElement(list, topicPubSub)){ //Found it!
 +			break;
 +		}
 +	}
 +	hashMapIterator_destroy(iter);
 +
 +	celixThreadMutex_unlock(&admin->usedSerializersLock);
 +
 +}

http://git-wip-us.apache.org/repos/asf/celix/blob/0a5ef69a/pubsub/pubsub_admin_udp_mc/src/topic_publication.c
----------------------------------------------------------------------
diff --cc pubsub/pubsub_admin_udp_mc/src/topic_publication.c
index 15af108,0000000..79a2698
mode 100644,000000..100644
--- a/pubsub/pubsub_admin_udp_mc/src/topic_publication.c
+++ b/pubsub/pubsub_admin_udp_mc/src/topic_publication.c
@@@ -1,437 -1,0 +1,440 @@@
 +/**
 + *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 <string.h>
 +#include <unistd.h>
 +#include <errno.h>
 +
 +#include <sys/types.h>
 +#include <sys/socket.h>
 +#include <netinet/in.h>
 +#include <arpa/inet.h>
 +
 +#include "array_list.h"
 +#include "celixbool.h"
 +#include "service_registration.h"
 +#include "utils.h"
 +#include "service_factory.h"
 +#include "version.h"
 +
 +#include "topic_publication.h"
 +#include "pubsub_common.h"
 +#include "pubsub/publisher.h"
 +#include "large_udp.h"
 +
 +#include "pubsub_serializer.h"
 +
 +#define EP_ADDRESS_LEN		32
 +
 +#define FIRST_SEND_DELAY	2
 +
 +struct topic_publication {
 +	int sendSocket;
 +	char* endpoint;
 +	service_registration_pt svcFactoryReg;
 +	array_list_pt pub_ep_list; //List<pubsub_endpoint>
 +	hash_map_pt boundServices; //<bundle_pt,bound_service>
 +	celix_thread_mutex_t tp_lock;
 +	pubsub_serializer_service_t *serializer;
 +	struct sockaddr_in destAddr;
 +};
 +
 +typedef struct publish_bundle_bound_service {
 +	topic_publication_pt parent;
 +	pubsub_publisher_t service;
 +	bundle_pt bundle;
 +	char *scope;
 +	char *topic;
 +	hash_map_pt msgTypes;
 +	unsigned short getCount;
 +	celix_thread_mutex_t mp_lock;
 +	largeUdp_pt largeUdpHandle;
 +}* publish_bundle_bound_service_pt;
 +
 +
 +typedef struct pubsub_msg{
 +	pubsub_msg_header_pt header;
 +	char* payload;
 +	unsigned int payloadSize;
 +} pubsub_msg_t;
 +
 +
 +static unsigned int rand_range(unsigned int min, unsigned int max);
 +
 +static celix_status_t pubsub_topicPublicationGetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service);
 +static celix_status_t pubsub_topicPublicationUngetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service);
 +
 +static publish_bundle_bound_service_pt pubsub_createPublishBundleBoundService(topic_publication_pt tp,bundle_pt bundle);
 +static void pubsub_destroyPublishBundleBoundService(publish_bundle_bound_service_pt boundSvc);
 +
 +static int pubsub_topicPublicationSend(void* handle,unsigned int msgTypeId, const void *msg);
 +
 +static int pubsub_localMsgTypeIdForUUID(void* handle, const char* msgType, unsigned int* msgTypeId);
 +
 +
 +static void delay_first_send_for_late_joiners(void);
 +
 +
 +celix_status_t pubsub_topicPublicationCreate(int sendSocket, pubsub_endpoint_pt pubEP, pubsub_serializer_service_t *best_serializer, char* bindIP, topic_publication_pt *out){
 +
 +	char* ep = malloc(EP_ADDRESS_LEN);
 +	memset(ep,0,EP_ADDRESS_LEN);
 +	unsigned int port = pubEP->serviceID + rand_range(UDP_BASE_PORT+pubEP->serviceID+3, UDP_MAX_PORT);
 +	snprintf(ep,EP_ADDRESS_LEN,"udp://%s:%u",bindIP,port);
 +
 +
 +	topic_publication_pt pub = calloc(1,sizeof(*pub));
 +
 +	arrayList_create(&(pub->pub_ep_list));
 +	pub->boundServices = hashMap_create(NULL,NULL,NULL,NULL);
 +	celixThreadMutex_create(&(pub->tp_lock),NULL);
 +
 +	pub->endpoint = ep;
 +	pub->sendSocket = sendSocket;
 +	pub->destAddr.sin_family = AF_INET;
 +	pub->destAddr.sin_addr.s_addr = inet_addr(bindIP);
 +	pub->destAddr.sin_port = htons(port);
 +
 +	pub->serializer = best_serializer;
 +
 +	pubsub_topicPublicationAddPublisherEP(pub,pubEP);
 +
 +	*out = pub;
 +
 +	return CELIX_SUCCESS;
 +}
 +
 +celix_status_t pubsub_topicPublicationDestroy(topic_publication_pt pub){
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	celixThreadMutex_lock(&(pub->tp_lock));
 +
 +	free(pub->endpoint);
 +	arrayList_destroy(pub->pub_ep_list);
 +
 +	hash_map_iterator_pt iter = hashMapIterator_create(pub->boundServices);
 +	while(hashMapIterator_hasNext(iter)){
 +		publish_bundle_bound_service_pt bound = hashMapIterator_nextValue(iter);
 +		pubsub_destroyPublishBundleBoundService(bound);
 +	}
 +	hashMapIterator_destroy(iter);
 +	hashMap_destroy(pub->boundServices,false,false);
 +
 +	pub->svcFactoryReg = NULL;
 +	pub->serializer = NULL;
 +
 +	if(close(pub->sendSocket) != 0){
 +		status = CELIX_FILE_IO_EXCEPTION;
 +	}
 +
 +	celixThreadMutex_unlock(&(pub->tp_lock));
 +
 +	celixThreadMutex_destroy(&(pub->tp_lock));
 +
 +	free(pub);
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_topicPublicationStart(bundle_context_pt bundle_context,topic_publication_pt pub,service_factory_pt* svcFactory){
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	/* Let's register the new service */
 +
 +	pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(pub->pub_ep_list,0);
 +
 +	if(pubEP!=NULL){
 +		service_factory_pt factory = calloc(1, sizeof(*factory));
 +		factory->handle = pub;
 +		factory->getService = pubsub_topicPublicationGetService;
 +		factory->ungetService = pubsub_topicPublicationUngetService;
 +
 +		properties_pt props = properties_create();
- 		properties_set(props,PUBSUB_PUBLISHER_SCOPE,pubEP->scope);
- 		properties_set(props,PUBSUB_PUBLISHER_TOPIC,pubEP->topic);
++		properties_set(props,PUBSUB_PUBLISHER_SCOPE,properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE));
++		properties_set(props,PUBSUB_PUBLISHER_TOPIC,properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +
 +		status = bundleContext_registerServiceFactory(bundle_context,PUBSUB_PUBLISHER_SERVICE_NAME,factory,props,&(pub->svcFactoryReg));
 +
 +		if(status != CELIX_SUCCESS){
 +			properties_destroy(props);
- 			printf("PSA_UDP_MC_PSA_UDP_MC_TP: Cannot register ServiceFactory for topic %s, topic %s (bundle %ld).\n",pubEP->scope, pubEP->topic,pubEP->serviceID);
++			printf("PSA_UDP_MC_PSA_UDP_MC_TP: Cannot register ServiceFactory for topic %s, topic %s (bundle %ld).\n",
++				   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE),
++				   properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC),
++				   pubEP->serviceID);
 +		}
 +		else{
 +			*svcFactory = factory;
 +		}
 +	}
 +	else{
 +		printf("PSA_UDP_MC_PSA_UDP_MC_TP: Cannot find pubsub_endpoint after adding it...Should never happen!\n");
 +		status = CELIX_SERVICE_EXCEPTION;
 +	}
 +
 +	return status;
 +}
 +
 +celix_status_t pubsub_topicPublicationStop(topic_publication_pt pub){
 +	return serviceRegistration_unregister(pub->svcFactoryReg);
 +}
 +
 +celix_status_t pubsub_topicPublicationAddPublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep){
 +
 +	celixThreadMutex_lock(&(pub->tp_lock));
- 	ep->endpoint = strdup(pub->endpoint);
++	pubsubEndpoint_setField(ep, PUBSUB_ENDPOINT_URL, pub->endpoint);
 +	arrayList_add(pub->pub_ep_list,ep);
 +	celixThreadMutex_unlock(&(pub->tp_lock));
 +
 +	return CELIX_SUCCESS;
 +}
 +
 +celix_status_t pubsub_topicPublicationRemovePublisherEP(topic_publication_pt pub,pubsub_endpoint_pt ep){
 +
 +	celixThreadMutex_lock(&(pub->tp_lock));
 +	arrayList_removeElement(pub->pub_ep_list,ep);
 +	celixThreadMutex_unlock(&(pub->tp_lock));
 +
 +	return CELIX_SUCCESS;
 +}
 +
 +array_list_pt pubsub_topicPublicationGetPublisherList(topic_publication_pt pub){
 +	array_list_pt list = NULL;
 +	celixThreadMutex_lock(&(pub->tp_lock));
 +	list = arrayList_clone(pub->pub_ep_list);
 +	celixThreadMutex_unlock(&(pub->tp_lock));
 +	return list;
 +}
 +
 +
 +static celix_status_t pubsub_topicPublicationGetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service) {
 +	celix_status_t  status = CELIX_SUCCESS;
 +
 +	topic_publication_pt publish = (topic_publication_pt)handle;
 +
 +	celixThreadMutex_lock(&(publish->tp_lock));
 +
 +	publish_bundle_bound_service_pt bound = (publish_bundle_bound_service_pt)hashMap_get(publish->boundServices,bundle);
 +	if(bound==NULL){
 +		bound = pubsub_createPublishBundleBoundService(publish,bundle);
 +		if(bound!=NULL){
 +			hashMap_put(publish->boundServices,bundle,bound);
 +		}
 +	}
 +	else{
 +		bound->getCount++;
 +	}
 +
 +	if (bound != NULL) {
 +		*service = &bound->service;
 +	}
 +
 +	celixThreadMutex_unlock(&(publish->tp_lock));
 +
 +	return status;
 +}
 +
 +static celix_status_t pubsub_topicPublicationUngetService(void* handle, bundle_pt bundle, service_registration_pt registration, void **service)  {
 +
 +	topic_publication_pt publish = (topic_publication_pt)handle;
 +
 +	celixThreadMutex_lock(&(publish->tp_lock));
 +
 +	publish_bundle_bound_service_pt bound = (publish_bundle_bound_service_pt)hashMap_get(publish->boundServices,bundle);
 +	if(bound!=NULL){
 +
 +		bound->getCount--;
 +		if(bound->getCount==0){
 +			pubsub_destroyPublishBundleBoundService(bound);
 +			hashMap_remove(publish->boundServices,bundle);
 +		}
 +
 +	}
 +	else{
 +		long bundleId = -1;
 +		bundle_getBundleId(bundle,&bundleId);
 +		printf("PSA_UDP_MC_TP: Unexpected ungetService call for bundle %ld.\n", bundleId);
 +	}
 +
 +	/* service should be never used for unget, so let's set the pointer to NULL */
 +	*service = NULL;
 +
 +	celixThreadMutex_unlock(&(publish->tp_lock));
 +
 +	return CELIX_SUCCESS;
 +}
 +
 +static bool send_pubsub_msg(publish_bundle_bound_service_pt bound, pubsub_msg_t* msg, bool last, pubsub_release_callback_t *releaseCallback){
 +	const int iovec_len = 3; // header + size + payload
 +	bool ret = true;
 +
 +	struct iovec msg_iovec[iovec_len];
 +	msg_iovec[0].iov_base = msg->header;
 +	msg_iovec[0].iov_len = sizeof(*msg->header);
 +	msg_iovec[1].iov_base = &msg->payloadSize;
 +	msg_iovec[1].iov_len = sizeof(msg->payloadSize);
 +	msg_iovec[2].iov_base = msg->payload;
 +	msg_iovec[2].iov_len = msg->payloadSize;
 +
 +	delay_first_send_for_late_joiners();
 +
 +	if(largeUdp_sendmsg(bound->largeUdpHandle, bound->parent->sendSocket, msg_iovec, iovec_len, 0, &bound->parent->destAddr, sizeof(bound->parent->destAddr)) == -1) {
 +		perror("send_pubsub_msg:sendSocket");
 +		ret = false;
 +	}
 +
 +	if(releaseCallback) {
 +		releaseCallback->release(msg->payload, bound);
 +	}
 +	return ret;
 +
 +}
 +
 +
 +static int pubsub_topicPublicationSend(void* handle, unsigned int msgTypeId, const void *inMsg) {
 +	int status = 0;
 +	publish_bundle_bound_service_pt bound = (publish_bundle_bound_service_pt) handle;
 +
 +	celixThreadMutex_lock(&(bound->parent->tp_lock));
 +	celixThreadMutex_lock(&(bound->mp_lock));
 +
 +	pubsub_msg_serializer_t* msgSer = (pubsub_msg_serializer_t*)hashMap_get(bound->msgTypes, (void*)(intptr_t)msgTypeId);
 +
 +	if (msgSer != NULL) {
 +		int major=0, minor=0;
 +
 +		pubsub_msg_header_pt msg_hdr = calloc(1,sizeof(struct pubsub_msg_header));
 +		strncpy(msg_hdr->topic,bound->topic,MAX_TOPIC_LEN-1);
 +		msg_hdr->type = msgTypeId;
 +
 +
 +		if (msgSer->msgVersion != NULL){
 +			version_getMajor(msgSer->msgVersion, &major);
 +			version_getMinor(msgSer->msgVersion, &minor);
 +			msg_hdr->major = major;
 +			msg_hdr->minor = minor;
 +		}
 +
 +		void* serializedOutput = NULL;
 +		size_t serializedOutputLen = 0;
 +		msgSer->serialize(msgSer,inMsg,&serializedOutput, &serializedOutputLen);
 +
 +		pubsub_msg_t *msg = calloc(1,sizeof(pubsub_msg_t));
 +		msg->header = msg_hdr;
 +		msg->payload = (char*)serializedOutput;
 +		msg->payloadSize = serializedOutputLen;
 +
 +
 +		if(send_pubsub_msg(bound, msg,true, NULL) == false) {
 +			status = -1;
 +		}
 +		free(msg_hdr);
 +		free(msg);
 +		free(serializedOutput);
 +
 +
 +	} else {
 +		printf("PSA_UDP_MC_TP: No msg serializer available for msg type id %d\n", msgTypeId);
 +		status=-1;
 +	}
 +
 +	celixThreadMutex_unlock(&(bound->mp_lock));
 +	celixThreadMutex_unlock(&(bound->parent->tp_lock));
 +
 +	return status;
 +}
 +
 +static int pubsub_localMsgTypeIdForUUID(void* handle, const char* msgType, unsigned int* msgTypeId){
 +	*msgTypeId = utils_stringHash(msgType);
 +	return 0;
 +}
 +
 +
 +static unsigned int rand_range(unsigned int min, unsigned int max){
 +
 +	double scaled = (double)(((double)random())/((double)RAND_MAX));
 +	return (max-min+1)*scaled + min;
 +
 +}
 +
 +static publish_bundle_bound_service_pt pubsub_createPublishBundleBoundService(topic_publication_pt tp,bundle_pt bundle){
 +
 +	publish_bundle_bound_service_pt bound = calloc(1, sizeof(*bound));
 +
 +	if (bound != NULL) {
 +
 +		bound->parent = tp;
 +		bound->bundle = bundle;
 +		bound->getCount = 1;
 +		celixThreadMutex_create(&bound->mp_lock,NULL);
 +
 +		if(tp->serializer != NULL){
 +			tp->serializer->createSerializerMap(tp->serializer->handle,bundle,&bound->msgTypes);
 +		}
 +
 +		pubsub_endpoint_pt pubEP = (pubsub_endpoint_pt)arrayList_get(bound->parent->pub_ep_list,0);
- 		bound->scope=strdup(pubEP->scope);
- 		bound->topic=strdup(pubEP->topic);
++		bound->scope=strdup(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_SCOPE));
++		bound->topic=strdup(properties_get(pubEP->endpoint_props, PUBSUB_ENDPOINT_TOPIC));
 +		bound->largeUdpHandle = largeUdp_create(1);
 +
 +		bound->service.handle = bound;
 +		bound->service.localMsgTypeIdForMsgType = pubsub_localMsgTypeIdForUUID;
 +		bound->service.send = pubsub_topicPublicationSend;
 +		bound->service.sendMultipart = NULL;  //Multipart not supported for UDP
 +
 +	}
 +
 +	return bound;
 +}
 +
 +static void pubsub_destroyPublishBundleBoundService(publish_bundle_bound_service_pt boundSvc){
 +
 +	celixThreadMutex_lock(&boundSvc->mp_lock);
 +
 +	if(boundSvc->parent->serializer != NULL && boundSvc->msgTypes != NULL){
 +		boundSvc->parent->serializer->destroySerializerMap(boundSvc->parent->serializer->handle, boundSvc->msgTypes);
 +	}
 +
 +	if(boundSvc->scope!=NULL){
 +		free(boundSvc->scope);
 +	}
 +
 +	if(boundSvc->topic!=NULL){
 +		free(boundSvc->topic);
 +	}
 +
 +	largeUdp_destroy(boundSvc->largeUdpHandle);
 +
 +	celixThreadMutex_unlock(&boundSvc->mp_lock);
 +	celixThreadMutex_destroy(&boundSvc->mp_lock);
 +
 +	free(boundSvc);
 +
 +}
 +
 +static void delay_first_send_for_late_joiners(){
 +
 +	static bool firstSend = true;
 +
 +	if(firstSend){
 +		printf("PSA_UDP_MC_TP: Delaying first send for late joiners...\n");
 +		sleep(FIRST_SEND_DELAY);
 +		firstSend = false;
 +	}
 +}