celix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pnol...@apache.org
Subject [33/60] [abbrv] [partial] celix git commit: CELIX-424: Cleans up the directory structure. Moves all libraries to the libs subdir and all bundles to the bundles subdir
Date Sun, 27 May 2018 18:52:41 GMT
http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/civetweb/src/md5.inl
----------------------------------------------------------------------
diff --git a/bundles/remote_services/civetweb/src/md5.inl b/bundles/remote_services/civetweb/src/md5.inl
new file mode 100644
index 0000000..4da933d
--- /dev/null
+++ b/bundles/remote_services/civetweb/src/md5.inl
@@ -0,0 +1,461 @@
+/*
+ * This an amalgamation of md5.c and md5.h into a single file
+ * with all static declaration to reduce linker conflicts
+ * in Civetweb.
+ *
+ * The MD5_STATIC declaration was added to facilitate static
+ * inclusion.
+ * No Face Press, LLC
+ */
+
+/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321, whose
+  text is available at
+	http://www.ietf.org/rfc/rfc1321.txt
+  The code is derived from the text of the RFC, including the test suite
+  (section A.5) but excluding the rest of Appendix A.  It does not include
+  any code or documentation that is identified in the RFC as being
+  copyrighted.
+
+  The original and principal author of md5.h is L. Peter Deutsch
+  <ghost@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2002-04-13 lpd Removed support for non-ANSI compilers; removed
+	references to Ghostscript; clarified derivation from RFC 1321;
+	now handles byte order either statically or dynamically.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+	added conditionalization for C++ compilation from Martin
+	Purschke <purschke@bnl.gov>.
+  1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+#  define md5_INCLUDED
+
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order.  If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+    md5_word_t count[2];	/* message length in bits, lsw first */
+    md5_word_t abcd[4];		/* digest buffer */
+    md5_byte_t buf[64];		/* accumulate block */
+} md5_state_t;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Initialize the algorithm. */
+MD5_STATIC void md5_init(md5_state_t *pms);
+
+/* Append a string to the message. */
+MD5_STATIC void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+/* Finish the message and return the digest. */
+MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+#ifdef __cplusplus
+}  /* end extern "C" */
+#endif
+
+#endif /* md5_INCLUDED */
+
+/*
+  Copyright (C) 1999, 2000, 2002 Aladdin Enterprises.  All rights reserved.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost@aladdin.com
+
+ */
+/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321, whose
+  text is available at
+	http://www.ietf.org/rfc/rfc1321.txt
+  The code is derived from the text of the RFC, including the test suite
+  (section A.5) but excluding the rest of Appendix A.  It does not include
+  any code or documentation that is identified in the RFC as being
+  copyrighted.
+
+  The original and principal author of md5.c is L. Peter Deutsch
+  <ghost@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+	either statically or dynamically; added missing #include <string.h>
+	in library.
+  2002-03-11 lpd Corrected argument list for main(), and added int return
+	type, in test program and T value program.
+  2002-02-21 lpd Added missing #include <stdio.h> in test program.
+  2000-07-03 lpd Patched to eliminate warnings about "constant is
+	unsigned in ANSI C, signed in traditional"; made test program
+	self-checking.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+  1999-05-03 lpd Original version.
+ */
+
+#ifndef MD5_STATIC
+#include <string.h>
+#endif
+
+#undef BYTE_ORDER	/* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#ifdef ARCH_IS_BIG_ENDIAN
+#  define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+#else
+#  define BYTE_ORDER 0
+#endif
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3    0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6    0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9    0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13    0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16    0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19    0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22    0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25    0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28    0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31    0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35    0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38    0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41    0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44    0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47    0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50    0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53    0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57    0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60    0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63    0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+    md5_word_t
+    a = pms->abcd[0], b = pms->abcd[1],
+    c = pms->abcd[2], d = pms->abcd[3];
+    md5_word_t t;
+#if BYTE_ORDER > 0
+    /* Define storage only for big-endian CPUs. */
+    md5_word_t X[16];
+#else
+    /* Define storage for little-endian or both types of CPUs. */
+    md5_word_t xbuf[16];
+    const md5_word_t *X;
+#endif
+
+    {
+#if BYTE_ORDER == 0
+        /*
+         * Determine dynamically whether this is a big-endian or
+         * little-endian machine, since we can use a more efficient
+         * algorithm on the latter.
+         */
+        static const int w = 1;
+
+        if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+#endif
+#if BYTE_ORDER <= 0		/* little-endian */
+        {
+            /*
+             * On little-endian machines, we can process properly aligned
+             * data without copying it.
+             */
+            if (!((data - (const md5_byte_t *)0) & 3)) {
+                /* data are properly aligned */
+                X = (const md5_word_t *)data;
+            } else {
+                /* not aligned */
+                memcpy(xbuf, data, 64);
+                X = xbuf;
+            }
+        }
+#endif
+#if BYTE_ORDER == 0
+        else			/* dynamic big-endian */
+#endif
+#if BYTE_ORDER >= 0		/* big-endian */
+        {
+            /*
+             * On big-endian machines, we must arrange the bytes in the
+             * right order.
+             */
+            const md5_byte_t *xp = data;
+            int i;
+
+#  if BYTE_ORDER == 0
+            X = xbuf;		/* (dynamic only) */
+#  else
+#    define xbuf X		/* (static only) */
+#  endif
+            for (i = 0; i < 16; ++i, xp += 4)
+                xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+        }
+#endif
+    }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+    /* Round 1. */
+    /* Let [abcd k s i] denote the operation
+       a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + F(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+    /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  7,  T1);
+    SET(d, a, b, c,  1, 12,  T2);
+    SET(c, d, a, b,  2, 17,  T3);
+    SET(b, c, d, a,  3, 22,  T4);
+    SET(a, b, c, d,  4,  7,  T5);
+    SET(d, a, b, c,  5, 12,  T6);
+    SET(c, d, a, b,  6, 17,  T7);
+    SET(b, c, d, a,  7, 22,  T8);
+    SET(a, b, c, d,  8,  7,  T9);
+    SET(d, a, b, c,  9, 12, T10);
+    SET(c, d, a, b, 10, 17, T11);
+    SET(b, c, d, a, 11, 22, T12);
+    SET(a, b, c, d, 12,  7, T13);
+    SET(d, a, b, c, 13, 12, T14);
+    SET(c, d, a, b, 14, 17, T15);
+    SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+    /* Round 2. */
+    /* Let [abcd k s i] denote the operation
+         a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + G(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+    /* Do the following 16 operations. */
+    SET(a, b, c, d,  1,  5, T17);
+    SET(d, a, b, c,  6,  9, T18);
+    SET(c, d, a, b, 11, 14, T19);
+    SET(b, c, d, a,  0, 20, T20);
+    SET(a, b, c, d,  5,  5, T21);
+    SET(d, a, b, c, 10,  9, T22);
+    SET(c, d, a, b, 15, 14, T23);
+    SET(b, c, d, a,  4, 20, T24);
+    SET(a, b, c, d,  9,  5, T25);
+    SET(d, a, b, c, 14,  9, T26);
+    SET(c, d, a, b,  3, 14, T27);
+    SET(b, c, d, a,  8, 20, T28);
+    SET(a, b, c, d, 13,  5, T29);
+    SET(d, a, b, c,  2,  9, T30);
+    SET(c, d, a, b,  7, 14, T31);
+    SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+    /* Round 3. */
+    /* Let [abcd k s t] denote the operation
+         a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + H(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+    /* Do the following 16 operations. */
+    SET(a, b, c, d,  5,  4, T33);
+    SET(d, a, b, c,  8, 11, T34);
+    SET(c, d, a, b, 11, 16, T35);
+    SET(b, c, d, a, 14, 23, T36);
+    SET(a, b, c, d,  1,  4, T37);
+    SET(d, a, b, c,  4, 11, T38);
+    SET(c, d, a, b,  7, 16, T39);
+    SET(b, c, d, a, 10, 23, T40);
+    SET(a, b, c, d, 13,  4, T41);
+    SET(d, a, b, c,  0, 11, T42);
+    SET(c, d, a, b,  3, 16, T43);
+    SET(b, c, d, a,  6, 23, T44);
+    SET(a, b, c, d,  9,  4, T45);
+    SET(d, a, b, c, 12, 11, T46);
+    SET(c, d, a, b, 15, 16, T47);
+    SET(b, c, d, a,  2, 23, T48);
+#undef SET
+
+    /* Round 4. */
+    /* Let [abcd k s t] denote the operation
+         a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + I(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+    /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  6, T49);
+    SET(d, a, b, c,  7, 10, T50);
+    SET(c, d, a, b, 14, 15, T51);
+    SET(b, c, d, a,  5, 21, T52);
+    SET(a, b, c, d, 12,  6, T53);
+    SET(d, a, b, c,  3, 10, T54);
+    SET(c, d, a, b, 10, 15, T55);
+    SET(b, c, d, a,  1, 21, T56);
+    SET(a, b, c, d,  8,  6, T57);
+    SET(d, a, b, c, 15, 10, T58);
+    SET(c, d, a, b,  6, 15, T59);
+    SET(b, c, d, a, 13, 21, T60);
+    SET(a, b, c, d,  4,  6, T61);
+    SET(d, a, b, c, 11, 10, T62);
+    SET(c, d, a, b,  2, 15, T63);
+    SET(b, c, d, a,  9, 21, T64);
+#undef SET
+
+    /* Then perform the following additions. (That is increment each
+       of the four registers by the value it had before this block
+       was started.) */
+    pms->abcd[0] += a;
+    pms->abcd[1] += b;
+    pms->abcd[2] += c;
+    pms->abcd[3] += d;
+}
+
+MD5_STATIC void
+md5_init(md5_state_t *pms)
+{
+    pms->count[0] = pms->count[1] = 0;
+    pms->abcd[0] = 0x67452301;
+    pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+    pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+    pms->abcd[3] = 0x10325476;
+}
+
+MD5_STATIC void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+    const md5_byte_t *p = data;
+    int left = nbytes;
+    int offset = (pms->count[0] >> 3) & 63;
+    md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+    if (nbytes <= 0)
+        return;
+
+    /* Update the message length. */
+    pms->count[1] += nbytes >> 29;
+    pms->count[0] += nbits;
+    if (pms->count[0] < nbits)
+        pms->count[1]++;
+
+    /* Process an initial partial block. */
+    if (offset) {
+        int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+        memcpy(pms->buf + offset, p, copy);
+        if (offset + copy < 64)
+            return;
+        p += copy;
+        left -= copy;
+        md5_process(pms, pms->buf);
+    }
+
+    /* Process full blocks. */
+    for (; left >= 64; p += 64, left -= 64)
+        md5_process(pms, p);
+
+    /* Process a final partial block. */
+    if (left)
+        memcpy(pms->buf, p, left);
+}
+
+MD5_STATIC void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+    static const md5_byte_t pad[64] = {
+        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+    };
+    md5_byte_t data[8];
+    int i;
+
+    /* Save the length before padding. */
+    for (i = 0; i < 8; ++i)
+        data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+    /* Pad to 56 bytes mod 64. */
+    md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+    /* Append the length. */
+    md5_append(pms, data, 8);
+    for (i = 0; i < 16; ++i)
+        digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/discovery_common/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/bundles/remote_services/discovery_common/CMakeLists.txt b/bundles/remote_services/discovery_common/CMakeLists.txt
new file mode 100644
index 0000000..f035e8e
--- /dev/null
+++ b/bundles/remote_services/discovery_common/CMakeLists.txt
@@ -0,0 +1,41 @@
+# 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.
+
+
+find_package(CURL REQUIRED)
+find_package(LibXml2 REQUIRED)
+
+add_library(rsa_discovery_common OBJECT
+		src/discovery.c
+		src/discovery_activator.c
+		src/endpoint_descriptor_reader.c
+		src/endpoint_descriptor_writer.c
+		src/endpoint_discovery_poller.c
+		src/endpoint_discovery_server.c
+)
+target_include_directories(rsa_discovery_common PUBLIC
+		include src
+		$<TARGET_PROPERTY:Celix::framework,INTERFACE_INCLUDE_DIRECTORIES>
+		$<TARGET_PROPERTY:Celix::utils,INTERFACE_INCLUDE_DIRECTORIES>
+		$<TARGET_PROPERTY:Celix::log_helper,INTERFACE_INCLUDE_DIRECTORIES>
+		$<TARGET_PROPERTY:Celix::rsa_spi,INTERFACE_INCLUDE_DIRECTORIES>
+		$<TARGET_PROPERTY:civetweb,INCLUDE_DIRECTORIES>
+		${CURL_INCLUDE_DIRS}
+		${LIBXML2_INCLUDE_DIR})
+
+#Setup target aliases to match external usage
+add_library(Celix::rsa_discovery_common ALIAS rsa_discovery_common)

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/discovery_common/include/discovery.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/discovery_common/include/discovery.h b/bundles/remote_services/discovery_common/include/discovery.h
new file mode 100644
index 0000000..ede3d5e
--- /dev/null
+++ b/bundles/remote_services/discovery_common/include/discovery.h
@@ -0,0 +1,88 @@
+/**
+ *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.
+ */
+/*
+ * discovery.h
+ *
+ *  \date       Sep 29, 2011
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef DISCOVERY_H_
+#define DISCOVERY_H_
+
+#include "discovery_type.h"
+#include "bundle_context.h"
+#include "service_reference.h"
+
+#include "endpoint_description.h"
+#include "endpoint_listener.h"
+
+#include "endpoint_discovery_server.h"
+#include "endpoint_discovery_poller.h"
+
+#include "log_helper.h"
+
+#define DISCOVERY_SERVER_INTERFACE	"DISCOVERY_CFG_SERVER_INTERFACE"
+#define DISCOVERY_SERVER_IP 		"DISCOVERY_CFG_SERVER_IP"
+#define DISCOVERY_SERVER_PORT 		"DISCOVERY_CFG_SERVER_PORT"
+#define DISCOVERY_SERVER_PATH 		"DISCOVERY_CFG_SERVER_PATH"
+#define DISCOVERY_POLL_ENDPOINTS 	"DISCOVERY_CFG_POLL_ENDPOINTS"
+#define DISCOVERY_SERVER_MAX_EP	"DISCOVERY_CFG_SERVER_MAX_EP"
+
+struct discovery {
+    bundle_context_t* context;
+
+    celix_thread_mutex_t listenerReferencesMutex;
+    celix_thread_mutex_t discoveredServicesMutex;
+
+    hash_map_t* listenerReferences; //key=serviceReference, value=nop
+    hash_map_t* discoveredServices; //key=endpointId (string), value=endpoint_description_pt
+
+    endpoint_discovery_poller_t* poller;
+    endpoint_discovery_server_t* server;
+
+    log_helper_t* loghelper;
+
+    discovery_impl_t* pImpl;
+};
+
+
+/* those one could be put into a general discovery.h - file */
+celix_status_t discovery_create(bundle_context_pt context, discovery_pt *discovery);
+celix_status_t discovery_destroy(discovery_pt discovery);
+
+celix_status_t discovery_start(discovery_pt discovery);
+celix_status_t discovery_stop(discovery_pt discovery);
+
+celix_status_t discovery_endpointAdded(void *handle, endpoint_description_pt endpoint, char *machtedFilter);
+celix_status_t discovery_endpointRemoved(void *handle, endpoint_description_pt endpoint, char *machtedFilter);
+
+celix_status_t discovery_endpointListenerAdding(void * handle, service_reference_pt reference, void **service);
+celix_status_t discovery_endpointListenerAdded(void * handle, service_reference_pt reference, void * service);
+celix_status_t discovery_endpointListenerModified(void * handle, service_reference_pt reference, void * service);
+celix_status_t discovery_endpointListenerRemoved(void * handle, service_reference_pt reference, void * service);
+
+celix_status_t discovery_informEndpointListeners(discovery_pt discovery, endpoint_description_pt endpoint, bool endpointAdded);
+celix_status_t discovery_updateEndpointListener(discovery_pt discovery, service_reference_pt reference, endpoint_listener_pt service);
+
+celix_status_t discovery_addDiscoveredEndpoint(discovery_pt discovery, endpoint_description_pt endpoint);
+celix_status_t discovery_removeDiscoveredEndpoint(discovery_pt discovery, endpoint_description_pt endpoint);
+
+#endif /* DISCOVERY_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/discovery_common/include/discovery_type.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/discovery_common/include/discovery_type.h b/bundles/remote_services/discovery_common/include/discovery_type.h
new file mode 100644
index 0000000..222a495
--- /dev/null
+++ b/bundles/remote_services/discovery_common/include/discovery_type.h
@@ -0,0 +1,27 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef DISCOVERY_TYPE_H_
+#define DISCOVERY_TYPE_H_
+
+typedef struct discovery  discovery_t;
+typedef struct discovery* discovery_pt;
+typedef struct discovery_impl discovery_impl_t;
+
+#endif //DISCOVERY_TYPE_H_
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/discovery_common/include/endpoint_descriptor_common.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/discovery_common/include/endpoint_descriptor_common.h b/bundles/remote_services/discovery_common/include/endpoint_descriptor_common.h
new file mode 100644
index 0000000..a186a18
--- /dev/null
+++ b/bundles/remote_services/discovery_common/include/endpoint_descriptor_common.h
@@ -0,0 +1,61 @@
+/**
+ * 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_descriptor_common.h
+ *
+ * \date		Aug 8, 2014
+ * \author		<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright	Apache License, Version 2.0
+ */
+
+#ifndef ENDPOINT_DESCRIPTOR_COMMON_H_
+#define ENDPOINT_DESCRIPTOR_COMMON_H_
+
+/*
+ * Private constant & enum definitions for endpoint descriptor reader and writer, not needed for normal usage of the reader and writer.
+ */
+
+typedef enum {
+    VALUE_TYPE_STRING,
+    VALUE_TYPE_LONG,
+    VALUE_TYPE_DOUBLE,
+    VALUE_TYPE_FLOAT,
+    VALUE_TYPE_INTEGER,
+    VALUE_TYPE_BYTE,
+    VALUE_TYPE_CHAR,
+    VALUE_TYPE_BOOLEAN,
+    VALUE_TYPE_SHORT,
+} valueType;
+
+static const __attribute__((unused)) xmlChar* XML = (const xmlChar*) "xml";
+static const __attribute__((unused)) xmlChar* XMLNS = (const xmlChar*) "http://www.osgi.org/xmlns/rsa/v1.0.0";
+
+static const __attribute__((unused)) xmlChar* ENDPOINT_DESCRIPTIONS = (const xmlChar*) "endpoint-descriptions";
+static const xmlChar* ENDPOINT_DESCRIPTION = (const xmlChar*) "endpoint-description";
+
+static const xmlChar* ARRAY = (const xmlChar*) "array";
+static const __attribute__((unused)) xmlChar* LIST = (const xmlChar*) "list";
+static const __attribute__((unused)) xmlChar* SET = (const xmlChar*) "set";
+
+static const xmlChar* PROPERTY = (const xmlChar*) "property";
+static const xmlChar* NAME = (const xmlChar*) "name";
+static const xmlChar* VALUE = (const xmlChar*) "value";
+static const xmlChar* VALUE_TYPE = (const xmlChar*) "value-type";
+
+#endif /* ENDPOINT_DESCRIPTOR_COMMON_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/discovery_common/include/endpoint_descriptor_reader.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/discovery_common/include/endpoint_descriptor_reader.h b/bundles/remote_services/discovery_common/include/endpoint_descriptor_reader.h
new file mode 100644
index 0000000..7a05d9e
--- /dev/null
+++ b/bundles/remote_services/discovery_common/include/endpoint_descriptor_reader.h
@@ -0,0 +1,42 @@
+/**
+ *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_descriptor_reader.h
+ *
+ *  \date       26 Jul 2014
+ *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright  Apache License, Version 2.0
+ */
+
+#ifndef ENDPOINT_DESCRIPTOR_READER_H_
+#define ENDPOINT_DESCRIPTOR_READER_H_
+
+#include "endpoint_discovery_poller.h"
+#include "celix_errno.h"
+#include "array_list.h"
+
+typedef struct endpoint_descriptor_reader *endpoint_descriptor_reader_pt;
+
+celix_status_t endpointDescriptorReader_create(endpoint_discovery_poller_pt poller, endpoint_descriptor_reader_pt *reader);
+celix_status_t endpointDescriptorReader_destroy(endpoint_descriptor_reader_pt reader);
+
+celix_status_t endpointDescriptorReader_parseDocument(endpoint_descriptor_reader_pt reader, char *document, array_list_pt *endpoints);
+
+
+#endif /* ENDPOINT_DESCRIPTOR_READER_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/discovery_common/include/endpoint_descriptor_writer.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/discovery_common/include/endpoint_descriptor_writer.h b/bundles/remote_services/discovery_common/include/endpoint_descriptor_writer.h
new file mode 100644
index 0000000..3c5a9be
--- /dev/null
+++ b/bundles/remote_services/discovery_common/include/endpoint_descriptor_writer.h
@@ -0,0 +1,39 @@
+/**
+ *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_descriptor_writer.h
+ *
+ *  \date       26 Jul 2014
+ *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright  Apache License, Version 2.0
+ */
+
+#ifndef ENDPOINT_DESCRIPTOR_WRITER_H_
+#define ENDPOINT_DESCRIPTOR_WRITER_H_
+
+#include "celix_errno.h"
+#include "array_list.h"
+
+typedef struct endpoint_descriptor_writer *endpoint_descriptor_writer_pt;
+
+celix_status_t endpointDescriptorWriter_create(endpoint_descriptor_writer_pt *writer);
+celix_status_t endpointDescriptorWriter_destroy(endpoint_descriptor_writer_pt writer);
+celix_status_t endpointDescriptorWriter_writeDocument(endpoint_descriptor_writer_pt writer, array_list_pt endpoints, char **document);
+
+#endif /* ENDPOINT_DESCRIPTOR_WRITER_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/discovery_common/include/endpoint_discovery_poller.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/discovery_common/include/endpoint_discovery_poller.h b/bundles/remote_services/discovery_common/include/endpoint_discovery_poller.h
new file mode 100644
index 0000000..3c537f1
--- /dev/null
+++ b/bundles/remote_services/discovery_common/include/endpoint_discovery_poller.h
@@ -0,0 +1,57 @@
+/**
+ * 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_discovery_poller.h
+ *
+ * \date       3 Jul 2014
+ * \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright  Apache License, Version 2.0
+ */
+
+#ifndef ENDPOINT_DISCOVERY_POLLER_H_
+#define ENDPOINT_DISCOVERY_POLLER_H_
+
+#include "celix_errno.h"
+#include "discovery_type.h"
+#include "log_helper.h"
+
+typedef struct endpoint_discovery_poller endpoint_discovery_poller_t;
+typedef struct endpoint_discovery_poller *endpoint_discovery_poller_pt;
+
+struct endpoint_discovery_poller {
+    discovery_pt discovery;
+    hash_map_pt entries;
+    log_helper_pt* loghelper;
+
+    celix_thread_mutex_t pollerLock;
+    celix_thread_t pollerThread;
+
+    unsigned int poll_interval;
+    volatile bool running;
+};
+
+celix_status_t endpointDiscoveryPoller_create(discovery_pt discovery, bundle_context_pt context, const char* defaultPollEndpoints, endpoint_discovery_poller_pt *poller);
+celix_status_t endpointDiscoveryPoller_destroy(endpoint_discovery_poller_pt poller);
+
+celix_status_t endpointDiscoveryPoller_addDiscoveryEndpoint(endpoint_discovery_poller_pt poller, char *url);
+celix_status_t endpointDiscoveryPoller_removeDiscoveryEndpoint(endpoint_discovery_poller_pt poller, char *url);
+
+celix_status_t endpointDiscoveryPoller_getDiscoveryEndpoints(endpoint_discovery_poller_pt poller, array_list_pt urls);
+
+#endif /* ENDPOINT_DISCOVERY_POLLER_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/discovery_common/include/endpoint_discovery_server.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/discovery_common/include/endpoint_discovery_server.h b/bundles/remote_services/discovery_common/include/endpoint_discovery_server.h
new file mode 100644
index 0000000..d70c145
--- /dev/null
+++ b/bundles/remote_services/discovery_common/include/endpoint_discovery_server.h
@@ -0,0 +1,88 @@
+/**
+ * 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_discovery_server.h
+ *
+ * \date		Aug 12, 2014
+ * \author		<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright	Apache License, Version 2.0
+ */
+
+#ifndef ENDPOINT_DISCOVERY_SERVER_H_
+#define ENDPOINT_DISCOVERY_SERVER_H_
+
+#include "celix_errno.h"
+#include "discovery_type.h"
+
+typedef struct endpoint_discovery_server endpoint_discovery_server_t;
+typedef struct endpoint_discovery_server *endpoint_discovery_server_pt;
+
+/**
+ * Creates and starts a new instance of an endpoint discovery server.
+ *
+ * @param discovery [in] the discovery service itself;
+ * @param context [in] the bundle context;
+ * @param server [out] the pointer to the created instance.
+ * @return CELIX_SUCCESS when successful.
+ */
+celix_status_t endpointDiscoveryServer_create(
+        discovery_pt discovery,
+        bundle_context_pt context,
+        const char* defaultServerPath,
+        const char* defaultServerPort,
+        const char* defaultServerIp,
+        endpoint_discovery_server_pt *server);
+
+/**
+ * Stops and destroys a given instance of an endpoint discovery server.
+ *
+ * @param server [in] the pointer to the instance to destroy.
+ * @return CELIX_SUCCESS when successful.
+ */
+celix_status_t endpointDiscoveryServer_destroy(endpoint_discovery_server_pt server);
+
+/**
+ * Adds a given endpoint description to expose through the given discovery server.
+ *
+ * @param server [in] the endpoint discovery server to expose the endpoint through;
+ * @param endpoint [in] the endpoint description to expose.
+ * @return CELIX_SUCCESS when successful.
+ */
+celix_status_t endpointDiscoveryServer_addEndpoint(endpoint_discovery_server_pt server, endpoint_description_pt endpoint);
+
+/**
+ * Removes a given endpoint description from exposure through the given discovery server.
+ *
+ * @param server [in] the endpoint discovery server to remove the endpoint from;
+ * @param endpoint [in] the endpoint description to remove.
+ * @return CELIX_SUCCESS when successful.
+ */
+celix_status_t endpointDiscoveryServer_removeEndpoint( endpoint_discovery_server_pt server, endpoint_description_pt endpoint);
+
+/**
+ * Returns the url, which is used by the discovery server to announce the endpoints
+ *
+ * @param server [in] the endpoint discovery server to retrieve the url from
+ * @param url [out] url which is used to announce the endpoints.
+ * @return CELIX_SUCCESS when successful.
+ */
+celix_status_t endpointDiscoveryServer_getUrl(endpoint_discovery_server_pt server, char* url);
+
+
+#endif /* ENDPOINT_DISCOVERY_SERVER_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/discovery_common/src/desc.xml
----------------------------------------------------------------------
diff --git a/bundles/remote_services/discovery_common/src/desc.xml b/bundles/remote_services/discovery_common/src/desc.xml
new file mode 100644
index 0000000..5998992
--- /dev/null
+++ b/bundles/remote_services/discovery_common/src/desc.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ *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-descriptions xmlns="http://www.osgi.org/xmlns/rsa/v1.0.0">
+	<endpoint-description>
+		<property name="service.intents">
+			<list>
+				<value>SOAP</value>
+				<value>HTTP</value>
+			</list>
+		</property>
+		<property name="endpoint.id" value="http://ws.acme.com:9000/hello" />
+		<property name="objectClass" value="com.acme.Foo" />
+		<property name="endpoint.package.version.com.acme" value="4.2" />
+		<property name="service.imported.configs" value="com.acme" />
+		<property name="com.acme.ws.xml">
+			<xml>
+				<config xmlns="http://acme.com/defs">
+					<port>1029</port>
+					<host>www.acme.com</host>
+				</config>
+			</xml>
+		</property>
+	</endpoint-description>
+</endpoint-descriptions>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/discovery_common/src/discovery.c
----------------------------------------------------------------------
diff --git a/bundles/remote_services/discovery_common/src/discovery.c b/bundles/remote_services/discovery_common/src/discovery.c
new file mode 100644
index 0000000..d016c09
--- /dev/null
+++ b/bundles/remote_services/discovery_common/src/discovery.c
@@ -0,0 +1,233 @@
+/**
+ * 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.
+ */
+/*
+ * discovery.c
+ *
+ * \date        Aug 8, 2014
+ * \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright	Apache License, Version 2.0
+ */
+#include <stdio.h>
+#include <stdbool.h>
+#include <netdb.h>
+#include <string.h>
+
+#include "celix_threads.h"
+#include "bundle_context.h"
+#include "log_helper.h"
+#include "discovery.h"
+#include "endpoint_discovery_server.h"
+
+
+celix_status_t discovery_endpointAdded(void *handle, endpoint_description_pt endpoint, char *matchedFilter) {
+	celix_status_t status;
+	discovery_pt discovery = handle;
+
+	logHelper_log(discovery->loghelper, OSGI_LOGSERVICE_INFO, "Endpoint for %s, with filter \"%s\" added...", endpoint->service, matchedFilter);
+
+	status = endpointDiscoveryServer_addEndpoint(discovery->server, endpoint);
+
+	return status;
+}
+
+celix_status_t discovery_endpointRemoved(void *handle, endpoint_description_pt endpoint, char *matchedFilter) {
+	celix_status_t status;
+	discovery_pt discovery = handle;
+
+	logHelper_log(discovery->loghelper, OSGI_LOGSERVICE_INFO, "Endpoint for %s, with filter \"%s\" removed...", endpoint->service, matchedFilter);
+
+	status = endpointDiscoveryServer_removeEndpoint(discovery->server, endpoint);
+
+	return status;
+}
+
+celix_status_t discovery_endpointListenerAdding(void* handle, service_reference_pt reference, void** service) {
+	celix_status_t status = CELIX_SUCCESS;
+	discovery_pt discovery = handle;
+
+	bundleContext_getService(discovery->context, reference, service);
+
+	return status;
+}
+
+celix_status_t discovery_endpointListenerAdded(void* handle, service_reference_pt reference, void* service) {
+	celix_status_t status = CELIX_SUCCESS;
+	discovery_pt discovery = handle;
+
+	const char *discoveryListener = NULL;
+	serviceReference_getProperty(reference, "DISCOVERY", &discoveryListener);
+	const char *scope = NULL;
+	serviceReference_getProperty(reference, OSGI_ENDPOINT_LISTENER_SCOPE, &scope);
+
+	filter_pt filter = filter_create(scope);
+
+	if (discoveryListener != NULL && strcmp(discoveryListener, "true") == 0) {
+		logHelper_log(discovery->loghelper, OSGI_LOGSERVICE_INFO, "EndpointListener Ignored - Discovery listener");
+	} else {
+		celixThreadMutex_lock(&discovery->discoveredServicesMutex);
+
+		hash_map_iterator_pt iter = hashMapIterator_create(discovery->discoveredServices);
+		while (hashMapIterator_hasNext(iter)) {
+			endpoint_description_pt endpoint = hashMapIterator_nextValue(iter);
+
+			bool matchResult = false;
+			filter_match(filter, endpoint->properties, &matchResult);
+			if (matchResult) {
+				endpoint_listener_pt listener = service;
+
+				logHelper_log(discovery->loghelper, OSGI_LOGSERVICE_INFO, "EndpointListener Added - Add Scope");
+
+				listener->endpointAdded(listener->handle, endpoint, NULL);
+			}
+		}
+		hashMapIterator_destroy(iter);
+
+		celixThreadMutex_unlock(&discovery->discoveredServicesMutex);
+
+		celixThreadMutex_lock(&discovery->listenerReferencesMutex);
+
+		hashMap_put(discovery->listenerReferences, reference, NULL);
+
+		celixThreadMutex_unlock(&discovery->listenerReferencesMutex);
+	}
+
+	filter_destroy(filter);
+
+	return status;
+}
+
+celix_status_t discovery_endpointListenerModified(void * handle, service_reference_pt reference, void * service) {
+	celix_status_t status;
+
+	status = discovery_endpointListenerRemoved(handle, reference, service);
+	if (status == CELIX_SUCCESS) {
+        status = discovery_endpointListenerAdded(handle, reference, service);
+	}
+
+	return status;
+}
+
+celix_status_t discovery_endpointListenerRemoved(void * handle, service_reference_pt reference, void * service) {
+    celix_status_t status;
+    discovery_pt discovery = handle;
+
+    status = celixThreadMutex_lock(&discovery->listenerReferencesMutex);
+
+    if (status == CELIX_SUCCESS) {
+        if (discovery->listenerReferences != NULL) {
+            if (hashMap_remove(discovery->listenerReferences, reference)) {
+                logHelper_log(discovery->loghelper, OSGI_LOGSERVICE_INFO, "EndpointListener Removed");
+            }
+        }
+
+        status = celixThreadMutex_unlock(&discovery->listenerReferencesMutex);
+    }
+
+	return status;
+}
+
+celix_status_t discovery_informEndpointListeners(discovery_pt discovery, endpoint_description_pt endpoint, bool endpointAdded) {
+	celix_status_t status;
+
+	// Inform listeners of new endpoint
+	status = celixThreadMutex_lock(&discovery->listenerReferencesMutex);
+
+    if (status == CELIX_SUCCESS) {
+        if (discovery->listenerReferences != NULL) {
+            hash_map_iterator_pt iter = hashMapIterator_create(discovery->listenerReferences);
+            while (hashMapIterator_hasNext(iter)) {
+                hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+
+                service_reference_pt reference = hashMapEntry_getKey(entry);
+                endpoint_listener_pt listener = NULL;
+
+                const char* scope = NULL;
+                serviceReference_getProperty(reference, OSGI_ENDPOINT_LISTENER_SCOPE, &scope);
+
+                filter_pt filter = filter_create(scope);
+                bool matchResult = false;
+
+                status = filter_match(filter, endpoint->properties, &matchResult);
+                if (status == CELIX_SUCCESS) {
+                    if (matchResult) {
+                        bundleContext_getService(discovery->context, reference, (void **) &listener);
+                        if (endpointAdded) {
+                            logHelper_log(discovery->loghelper, OSGI_LOGSERVICE_INFO, "Adding service (%s)", endpoint->service);
+
+                            listener->endpointAdded(listener->handle, endpoint, (char*)scope);
+                        } else {
+                            logHelper_log(discovery->loghelper, OSGI_LOGSERVICE_INFO, "Removing service (%s)", endpoint->service);
+
+                            listener->endpointRemoved(listener->handle, endpoint, (char*)scope);
+                        }
+                    }
+
+                    filter_destroy(filter);
+                }
+            }
+            hashMapIterator_destroy(iter);
+        }
+
+        status = celixThreadMutex_unlock(&discovery->listenerReferencesMutex);
+    }
+
+	return status;
+}
+
+celix_status_t discovery_addDiscoveredEndpoint(discovery_pt discovery, endpoint_description_pt endpoint) {
+	celix_status_t status;
+
+	status = celixThreadMutex_lock(&discovery->discoveredServicesMutex);
+
+    if (status == CELIX_SUCCESS) {
+        char *endpointId = endpoint->id;
+        bool exists = hashMap_get(discovery->discoveredServices, endpointId) != NULL;
+        if (!exists) {
+            hashMap_put(discovery->discoveredServices, endpointId, endpoint);
+        }
+
+        status = celixThreadMutex_unlock(&discovery->discoveredServicesMutex);
+
+        if (!exists) {
+            // notify our listeners that a new endpoint is available...
+            discovery_informEndpointListeners(discovery, endpoint, true /* addingService */);
+        }
+    }
+
+	return status;
+}
+
+celix_status_t discovery_removeDiscoveredEndpoint(discovery_pt discovery, endpoint_description_pt endpoint) {
+	celix_status_t status;
+
+	status = celixThreadMutex_lock(&discovery->discoveredServicesMutex);
+
+    if (status == CELIX_SUCCESS) {
+        char *endpointId = endpoint->id;
+        void *oldValue = hashMap_remove(discovery->discoveredServices, endpointId);
+
+        status = celixThreadMutex_unlock(&discovery->discoveredServicesMutex);
+
+        if (oldValue) {
+            status = discovery_informEndpointListeners(discovery, endpoint, false /* removeService */);
+        }
+    }
+
+	return status;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/discovery_common/src/discovery_activator.c
----------------------------------------------------------------------
diff --git a/bundles/remote_services/discovery_common/src/discovery_activator.c b/bundles/remote_services/discovery_common/src/discovery_activator.c
new file mode 100644
index 0000000..3267d25
--- /dev/null
+++ b/bundles/remote_services/discovery_common/src/discovery_activator.c
@@ -0,0 +1,186 @@
+/**
+ * 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.
+ */
+/*
+ * discovery_activator.c
+ *
+ * \date        Aug 8, 2014
+ * \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 "bundle_activator.h"
+#include "service_tracker.h"
+#include "constants.h"
+
+#include "log_helper.h"
+#include "discovery.h"
+#include "remote_constants.h"
+
+struct activator {
+	bundle_context_pt context;
+	discovery_pt discovery;
+	log_helper_pt loghelper;
+
+	service_tracker_pt endpointListenerTracker;
+	endpoint_listener_pt endpointListener;
+	service_registration_pt endpointListenerService;
+};
+
+celix_status_t bundleActivator_createEPLTracker(struct activator *activator, service_tracker_pt *tracker) {
+	celix_status_t status;
+
+	service_tracker_customizer_pt customizer = NULL;
+
+	status = serviceTrackerCustomizer_create(activator->discovery, discovery_endpointListenerAdding, discovery_endpointListenerAdded, discovery_endpointListenerModified,
+			discovery_endpointListenerRemoved, &customizer);
+
+	if (status == CELIX_SUCCESS) {
+		status = serviceTracker_create(activator->context, (char *) OSGI_ENDPOINT_LISTENER_SERVICE, customizer, tracker);
+	}
+
+	return status;
+}
+
+celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) {
+	celix_status_t status;
+
+	struct activator* activator = calloc(1,sizeof(struct activator));
+	if (!activator) {
+		return CELIX_ENOMEM;
+	}
+
+	status = discovery_create(context, &activator->discovery);
+	if (status == CELIX_SUCCESS) {
+		activator->context = context;
+
+		logHelper_create(context, &activator->loghelper);
+
+		status = bundleActivator_createEPLTracker(activator, &activator->endpointListenerTracker);
+		if(status==CELIX_SUCCESS){
+			*userData = activator;
+		}
+		else{
+			bundleActivator_destroy(activator,context);
+		}
+	}
+	else{
+		free(activator);
+	}
+
+	return status;
+}
+
+celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
+	celix_status_t status;
+	struct activator *activator = userData;
+	const char *uuid = NULL;
+
+	logHelper_start(activator->loghelper);
+
+	status = bundleContext_getProperty(context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &uuid);
+	if (!uuid) {
+		logHelper_log(activator->loghelper, OSGI_LOGSERVICE_DEBUG, "no framework UUID defined?!");
+		return CELIX_ILLEGAL_STATE;
+	}
+
+	size_t len = 11 + strlen(OSGI_FRAMEWORK_OBJECTCLASS) + strlen(OSGI_RSA_ENDPOINT_FRAMEWORK_UUID) + strlen(uuid);
+	char *scope = malloc(len + 1);
+	if (!scope) {
+		return CELIX_ENOMEM;
+	}
+
+	sprintf(scope, "(&(%s=*)(%s=%s))", OSGI_FRAMEWORK_OBJECTCLASS, OSGI_RSA_ENDPOINT_FRAMEWORK_UUID, uuid);
+	scope[len] = 0;
+
+	logHelper_log(activator->loghelper, OSGI_LOGSERVICE_DEBUG, "using scope %s.", scope);
+
+	properties_pt props = properties_create();
+	properties_set(props, "DISCOVERY", "true");
+	properties_set(props, (char *) OSGI_ENDPOINT_LISTENER_SCOPE, scope);
+
+	if (status == CELIX_SUCCESS) {
+		status = serviceTracker_open(activator->endpointListenerTracker);
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = discovery_start(activator->discovery);
+	}
+
+	if (status == CELIX_SUCCESS) {
+		endpoint_listener_pt endpointListener = calloc(1, sizeof(struct endpoint_listener));
+
+		if (endpointListener) {
+			endpointListener->handle = activator->discovery;
+			endpointListener->endpointAdded = discovery_endpointAdded;
+			endpointListener->endpointRemoved = discovery_endpointRemoved;
+
+			status = bundleContext_registerService(context, (char *) OSGI_ENDPOINT_LISTENER_SERVICE, endpointListener, props, &activator->endpointListenerService);
+
+			if (status == CELIX_SUCCESS) {
+				activator->endpointListener = endpointListener;
+			}
+		}
+	}
+	// We can release the scope, as properties_set makes a copy of the key & value...
+	free(scope);
+
+	return status;
+}
+
+celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) {
+	celix_status_t status;
+	struct activator *activator = userData;
+
+	status = discovery_stop(activator->discovery);
+
+	status = serviceTracker_close(activator->endpointListenerTracker);
+
+	status = serviceRegistration_unregister(activator->endpointListenerService);
+	free(activator->endpointListener);
+
+	logHelper_stop(activator->loghelper);
+
+	return status;
+}
+
+celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) {
+	celix_status_t status;
+	struct activator *activator = userData;
+
+	status = serviceTracker_destroy(activator->endpointListenerTracker);
+
+	status = discovery_destroy(activator->discovery);
+
+	logHelper_destroy(&activator->loghelper);
+
+	activator->loghelper = NULL;
+	activator->endpointListenerTracker = NULL;
+	activator->endpointListenerService = NULL;
+	activator->discovery = NULL;
+	activator->context = NULL;
+
+	free(activator);
+
+	return status;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/discovery_common/src/endpoint_descriptor_reader.c
----------------------------------------------------------------------
diff --git a/bundles/remote_services/discovery_common/src/endpoint_descriptor_reader.c b/bundles/remote_services/discovery_common/src/endpoint_descriptor_reader.c
new file mode 100644
index 0000000..887bc29
--- /dev/null
+++ b/bundles/remote_services/discovery_common/src/endpoint_descriptor_reader.c
@@ -0,0 +1,293 @@
+/**
+ *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_descriptor_reader.c
+ *
+ *  \date       24 Jul 2014
+ *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright  Apache License, Version 2.0
+ */
+
+#include <stdbool.h>
+#include <string.h>
+#include <libxml/xmlreader.h>
+
+#include "log_helper.h"
+#include "remote_constants.h"
+
+#include "endpoint_description.h"
+#include "endpoint_descriptor_common.h"
+#include "endpoint_descriptor_reader.h"
+
+struct endpoint_descriptor_reader {
+    xmlTextReaderPtr reader;
+    log_helper_pt* loghelper;
+};
+
+static valueType valueTypeFromString(char *name);
+
+celix_status_t endpointDescriptorReader_create(endpoint_discovery_poller_pt poller, endpoint_descriptor_reader_pt *reader) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    *reader = malloc(sizeof(**reader));
+    if (!*reader) {
+        status = CELIX_ENOMEM;
+    } else {
+        (*reader)->reader = NULL;
+        (*reader)->loghelper = poller->loghelper;
+    }
+
+    return status;
+}
+
+celix_status_t endpointDescriptorReader_destroy(endpoint_descriptor_reader_pt reader) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    reader->loghelper = NULL;
+
+    free(reader);
+
+    return status;
+}
+
+void endpointDescriptorReader_addSingleValuedProperty(properties_pt properties, const xmlChar* name, const xmlChar* value) {
+	properties_set(properties, (char *) name, (char*) value);
+}
+
+void endpointDescriptorReader_addMultiValuedProperty(properties_pt properties, const xmlChar* name, array_list_pt values) {
+	char *value = calloc(256, sizeof(*value));
+	if (value) {
+		unsigned int size = arrayList_size(values);
+        unsigned int i;
+        for (i = 0; i < size; i++) {
+			char* item = (char*) arrayList_get(values, i);
+			if (i > 0) {
+				value = strcat(value, ",");
+			}
+			value = strcat(value, item);
+		}
+
+		properties_set(properties, (char *) name, value);
+
+		free(value);
+	}
+}
+
+celix_status_t endpointDescriptorReader_parseDocument(endpoint_descriptor_reader_pt reader, char *document, array_list_pt *endpoints) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    reader->reader = xmlReaderForMemory(document, (int) strlen(document), NULL, "UTF-8", 0);
+    if (reader->reader == NULL) {
+        status = CELIX_BUNDLE_EXCEPTION;
+    } else {
+        bool inProperty = false;
+        bool inXml = false;
+        bool inArray = false;
+        bool inList = false;
+        bool inSet = false;
+        bool inValue = false;
+
+        const xmlChar *propertyName = NULL;
+        const xmlChar *propertyValue = NULL;
+        valueType propertyType = VALUE_TYPE_STRING;
+        xmlChar *valueBuffer = xmlMalloc(256);
+        valueBuffer[0] = '\0';
+
+        array_list_pt propertyValues = NULL;
+        arrayList_create(&propertyValues);
+
+        array_list_pt endpointDescriptions = NULL;
+        if (*endpoints) {
+        	// use the given arraylist...
+        	endpointDescriptions = *endpoints;
+        } else {
+			arrayList_create(&endpointDescriptions);
+			// return the read endpoints...
+			*endpoints = endpointDescriptions;
+        }
+
+        properties_pt endpointProperties = NULL;
+
+        int read = xmlTextReaderRead(reader->reader);
+        while (read == XML_TEXTREADER_MODE_INTERACTIVE) {
+            int type = xmlTextReaderNodeType(reader->reader);
+
+            if (type == XML_READER_TYPE_ELEMENT) {
+                const xmlChar *localname = xmlTextReaderConstLocalName(reader->reader);
+
+                if (inXml) {
+                    valueBuffer = xmlStrcat(valueBuffer, BAD_CAST "<");
+                    valueBuffer = xmlStrcat(valueBuffer, localname);
+
+                    int i = xmlTextReaderMoveToFirstAttribute(reader->reader);
+                    while (i == 1) {
+                        const xmlChar *name = xmlTextReaderConstName(reader->reader);
+                        const xmlChar *value = xmlTextReaderConstValue(reader->reader);
+
+                        valueBuffer = xmlStrcat(valueBuffer, BAD_CAST " ");
+                        valueBuffer = xmlStrcat(valueBuffer, name);
+                        valueBuffer = xmlStrcat(valueBuffer, BAD_CAST "=\"");
+                        valueBuffer = xmlStrcat(valueBuffer, BAD_CAST value);
+                        valueBuffer = xmlStrcat(valueBuffer, BAD_CAST "\"");
+
+                        i = xmlTextReaderMoveToNextAttribute(reader->reader);
+                    }
+
+                    valueBuffer = xmlStrcat(valueBuffer, BAD_CAST ">");
+                } else if (xmlStrcmp(localname, ENDPOINT_DESCRIPTION) == 0) {
+
+                	if (endpointProperties != NULL)
+                		properties_destroy(endpointProperties);
+
+                    endpointProperties = properties_create();
+                } else if (xmlStrcmp(localname, PROPERTY) == 0) {
+                    inProperty = true;
+
+                    propertyName = xmlTextReaderGetAttribute(reader->reader, NAME);
+                    propertyValue = xmlTextReaderGetAttribute(reader->reader, VALUE);
+                    xmlChar *vtype = xmlTextReaderGetAttribute(reader->reader, VALUE_TYPE);
+                    propertyType = valueTypeFromString((char*) vtype);
+                    arrayList_clear(propertyValues);
+
+                    if (xmlTextReaderIsEmptyElement(reader->reader)) {
+                        inProperty = false;
+
+                        if (propertyValue != NULL) {
+                        	endpointDescriptorReader_addSingleValuedProperty(endpointProperties, propertyName, propertyValue);
+                        }
+
+                        xmlFree((void *) propertyName);
+                        xmlFree((void *) propertyValue);
+                        xmlFree((void *) vtype);
+                    }
+                } else {
+                    valueBuffer[0] = 0;
+                    inArray |= inProperty && xmlStrcmp(localname, ARRAY) == 0;
+                    inList |= inProperty && xmlStrcmp(localname, LIST) == 0;
+                    inSet |= inProperty && xmlStrcmp(localname, SET) == 0;
+                    inXml |= inProperty && xmlStrcmp(localname, XML) == 0;
+                    inValue |= inProperty && xmlStrcmp(localname, VALUE) == 0;
+				}
+			} else if (type == XML_READER_TYPE_END_ELEMENT) {
+				const xmlChar *localname = xmlTextReaderConstLocalName(reader->reader);
+
+                if (inXml) {
+                    if (xmlStrcmp(localname, XML) != 0)  {
+                    	valueBuffer = xmlStrcat(valueBuffer, BAD_CAST "</");
+                    	valueBuffer = xmlStrcat(valueBuffer, localname);
+                    	valueBuffer = xmlStrcat(valueBuffer, BAD_CAST ">");
+                    }
+                    else {
+                        inXml = false;
+                    }
+                } else if (xmlStrcmp(localname, ENDPOINT_DESCRIPTION) == 0) {
+                    endpoint_description_pt endpointDescription = NULL;
+                    // Completely parsed endpoint description, add it to our list of results...
+                    if(endpointDescription_create(endpointProperties, &endpointDescription) == CELIX_SUCCESS){
+			arrayList_add(endpointDescriptions, endpointDescription);
+                    }
+
+                    endpointProperties = properties_create();
+                } else if (xmlStrcmp(localname, PROPERTY) == 0) {
+                    inProperty = false;
+
+                    if (inArray || inList || inSet) {
+						endpointDescriptorReader_addMultiValuedProperty(endpointProperties, propertyName, propertyValues);
+                    }
+                    else if (propertyValue != NULL) {
+                    	if (propertyType != VALUE_TYPE_STRING) {
+                    		logHelper_log(*reader->loghelper, OSGI_LOGSERVICE_WARNING, "ENDPOINT_DESCRIPTOR_READER: Only string support for %s\n", propertyName);
+                    	}
+                    	endpointDescriptorReader_addSingleValuedProperty(endpointProperties, propertyName, propertyValue);
+
+                        xmlFree((void *) propertyValue);
+                    }
+                    else {
+                    	endpointDescriptorReader_addSingleValuedProperty(endpointProperties, propertyName, valueBuffer);
+                    }
+
+                    xmlFree((void *) propertyName);
+					unsigned int k=0;
+					for(;k<arrayList_size(propertyValues);k++){
+						free(arrayList_get(propertyValues,k));
+					}
+                    arrayList_clear(propertyValues);
+
+                    propertyType = VALUE_TYPE_STRING;
+                    inArray = false;
+                    inList = false;
+                    inSet = false;
+                    inXml = false;
+                } else if (xmlStrcmp(localname, VALUE) == 0) {
+                    arrayList_add(propertyValues, strdup((char*) valueBuffer));
+                    valueBuffer[0] = 0;
+                    inValue = false;
+                }
+            } else if (type == XML_READER_TYPE_TEXT) {
+                if (inValue || inXml) {
+                    const xmlChar *value = xmlTextReaderValue(reader->reader);
+                    valueBuffer = xmlStrcat(valueBuffer, value);
+                    xmlFree((void *)value);
+                }
+            }
+
+            read = xmlTextReaderRead(reader->reader);
+        }
+
+		if(endpointProperties!=NULL){
+			properties_destroy(endpointProperties);
+		}
+
+		unsigned int k=0;
+		for(;k<arrayList_size(propertyValues);k++){
+			free(arrayList_get(propertyValues,k));
+		}
+        arrayList_destroy(propertyValues);
+        xmlFree(valueBuffer);
+
+        xmlFreeTextReader(reader->reader);
+    }
+
+    return status;
+}
+
+static valueType valueTypeFromString(char *name) {
+    if (name == NULL || strcmp(name, "") == 0 || strcmp(name, "String") == 0) {
+        return VALUE_TYPE_STRING;
+    } else if (strcmp(name, "long") == 0 || strcmp(name, "Long") == 0) {
+        return VALUE_TYPE_LONG;
+    } else if (strcmp(name, "double") == 0 || strcmp(name, "Double") == 0) {
+        return VALUE_TYPE_DOUBLE;
+    } else if (strcmp(name, "float") == 0 || strcmp(name, "Float") == 0) {
+        return VALUE_TYPE_FLOAT;
+    } else if (strcmp(name, "int") == 0 || strcmp(name, "integer") == 0 || strcmp(name, "Integer") == 0) {
+        return VALUE_TYPE_INTEGER;
+    } else if (strcmp(name, "short") == 0 || strcmp(name, "Short") == 0) {
+        return VALUE_TYPE_SHORT;
+    } else if (strcmp(name, "byte") == 0 || strcmp(name, "Byte") == 0) {
+        return VALUE_TYPE_BYTE;
+    } else if (strcmp(name, "char") == 0 || strcmp(name, "Character") == 0) {
+        return VALUE_TYPE_CHAR;
+    } else if (strcmp(name, "boolean") == 0 || strcmp(name, "Boolean") == 0) {
+        return VALUE_TYPE_BOOLEAN;
+    } else {
+        return VALUE_TYPE_STRING;
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/discovery_common/src/endpoint_descriptor_writer.c
----------------------------------------------------------------------
diff --git a/bundles/remote_services/discovery_common/src/endpoint_descriptor_writer.c b/bundles/remote_services/discovery_common/src/endpoint_descriptor_writer.c
new file mode 100644
index 0000000..4a5bcd7
--- /dev/null
+++ b/bundles/remote_services/discovery_common/src/endpoint_descriptor_writer.c
@@ -0,0 +1,196 @@
+/**
+ *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_descriptor_writer.c
+ *
+ *  \date       26 Jul 2014
+ *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright  Apache License, Version 2.0
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <libxml/xmlwriter.h>
+
+#include "constants.h"
+#include "remote_constants.h"
+
+#include "endpoint_description.h"
+#include "endpoint_descriptor_common.h"
+#include "endpoint_descriptor_writer.h"
+
+struct endpoint_descriptor_writer {
+    xmlBufferPtr buffer;
+    xmlTextWriterPtr writer;
+};
+
+static celix_status_t endpointDescriptorWriter_writeEndpoint(endpoint_descriptor_writer_pt writer, endpoint_description_pt endpoint);
+
+static char* valueTypeToString(valueType type);
+
+celix_status_t endpointDescriptorWriter_create(endpoint_descriptor_writer_pt *writer) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    *writer = malloc(sizeof(**writer));
+    if (!*writer) {
+        status = CELIX_ENOMEM;
+    } else {
+        (*writer)->buffer = xmlBufferCreate();
+        if ((*writer)->buffer == NULL) {
+            status = CELIX_BUNDLE_EXCEPTION;
+        } else {
+            (*writer)->writer = xmlNewTextWriterMemory((*writer)->buffer, 0);
+            if ((*writer)->writer == NULL) {
+                status = CELIX_BUNDLE_EXCEPTION;
+            }
+        }
+    }
+
+    return status;
+}
+
+celix_status_t endpointDescriptorWriter_destroy(endpoint_descriptor_writer_pt writer) {
+    xmlFreeTextWriter(writer->writer);
+    xmlBufferFree(writer->buffer);
+    free(writer);
+    return CELIX_SUCCESS;
+}
+
+celix_status_t endpointDescriptorWriter_writeDocument(endpoint_descriptor_writer_pt writer, array_list_pt endpoints, char **document) {
+    celix_status_t status = CELIX_SUCCESS;
+    int rc;
+
+    rc = xmlTextWriterStartDocument(writer->writer, NULL, "UTF-8", NULL);
+    if (rc < 0) {
+        status = CELIX_BUNDLE_EXCEPTION;
+    } else {
+        rc = xmlTextWriterStartElementNS(writer->writer, NULL, ENDPOINT_DESCRIPTIONS, XMLNS);
+        if (rc < 0) {
+            status = CELIX_BUNDLE_EXCEPTION;
+        } else {
+            unsigned int i;
+            for (i = 0; i < arrayList_size(endpoints); i++) {
+                endpoint_description_pt endpoint = arrayList_get(endpoints, i);
+                status = endpointDescriptorWriter_writeEndpoint(writer, endpoint);
+            }
+            if (status == CELIX_SUCCESS) {
+                rc = xmlTextWriterEndElement(writer->writer);
+                if (rc < 0) {
+                    status = CELIX_BUNDLE_EXCEPTION;
+                } else {
+                    rc = xmlTextWriterEndDocument(writer->writer);
+                    if (rc < 0) {
+                        status = CELIX_BUNDLE_EXCEPTION;
+                    } else {
+                        *document = (char *) writer->buffer->content;
+                    }
+                }
+            }
+        }
+    }
+
+    return status;
+}
+
+static celix_status_t endpointDescriptorWriter_writeArrayValue(xmlTextWriterPtr writer, const xmlChar* value) {
+    xmlTextWriterStartElement(writer, ARRAY);
+    xmlTextWriterStartElement(writer, VALUE);
+    xmlTextWriterWriteString(writer, value);
+    xmlTextWriterEndElement(writer); // value
+    xmlTextWriterEndElement(writer); // array
+
+	return CELIX_SUCCESS;
+}
+
+static celix_status_t endpointDescriptorWriter_writeTypedValue(xmlTextWriterPtr writer, valueType type, const xmlChar* value) {
+	xmlTextWriterWriteAttribute(writer, VALUE_TYPE, (const xmlChar*) valueTypeToString(type));
+	xmlTextWriterWriteAttribute(writer, VALUE, value);
+
+	return CELIX_SUCCESS;
+}
+
+static celix_status_t endpointDescriptorWriter_writeUntypedValue(xmlTextWriterPtr writer, const xmlChar* value) {
+	xmlTextWriterWriteAttribute(writer, VALUE, value);
+
+	return CELIX_SUCCESS;
+}
+
+static celix_status_t endpointDescriptorWriter_writeEndpoint(endpoint_descriptor_writer_pt writer, endpoint_description_pt endpoint) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    if (endpoint == NULL || writer == NULL) {
+        status = CELIX_ILLEGAL_ARGUMENT;
+    } else {
+        xmlTextWriterStartElement(writer->writer, ENDPOINT_DESCRIPTION);
+
+        hash_map_iterator_pt iter = hashMapIterator_create(endpoint->properties);
+        while (hashMapIterator_hasNext(iter)) {
+            hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+
+            void* propertyName = hashMapEntry_getKey(entry);
+			const xmlChar* propertyValue = (const xmlChar*) hashMapEntry_getValue(entry);
+
+            xmlTextWriterStartElement(writer->writer, PROPERTY);
+            xmlTextWriterWriteAttribute(writer->writer, NAME, propertyName);
+
+            if (strcmp(OSGI_FRAMEWORK_OBJECTCLASS, (char*) propertyName) == 0) {
+            	// objectClass *must* be represented as array of string values...
+            	endpointDescriptorWriter_writeArrayValue(writer->writer, propertyValue);
+            } else if (strcmp(OSGI_RSA_ENDPOINT_SERVICE_ID, (char*) propertyName) == 0) {
+            	// endpoint.service.id *must* be represented as long value...
+            	endpointDescriptorWriter_writeTypedValue(writer->writer, VALUE_TYPE_LONG, propertyValue);
+            } else {
+            	// represent all other values as plain string values...
+            	endpointDescriptorWriter_writeUntypedValue(writer->writer, propertyValue);
+            }
+
+            xmlTextWriterEndElement(writer->writer);
+        }
+        hashMapIterator_destroy(iter);
+
+        xmlTextWriterEndElement(writer->writer);
+    }
+
+    return status;
+}
+
+
+static char* valueTypeToString(valueType type) {
+	switch (type) {
+		case VALUE_TYPE_BOOLEAN:
+			return "boolean";
+		case VALUE_TYPE_BYTE:
+			return "byte";
+		case VALUE_TYPE_CHAR:
+			return "char";
+		case VALUE_TYPE_DOUBLE:
+			return "double";
+		case VALUE_TYPE_FLOAT:
+			return "float";
+		case VALUE_TYPE_INTEGER:
+			return "int";
+		case VALUE_TYPE_LONG:
+			return "long";
+		case VALUE_TYPE_SHORT:
+			return "short";
+		case VALUE_TYPE_STRING:
+			// FALL-THROUGH!
+		default:
+			return "string";
+	}
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/discovery_common/src/endpoint_discovery_poller.c
----------------------------------------------------------------------
diff --git a/bundles/remote_services/discovery_common/src/endpoint_discovery_poller.c b/bundles/remote_services/discovery_common/src/endpoint_discovery_poller.c
new file mode 100644
index 0000000..e3f9cd4
--- /dev/null
+++ b/bundles/remote_services/discovery_common/src/endpoint_discovery_poller.c
@@ -0,0 +1,402 @@
+/**
+ * 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_discovery_poller.c
+ *
+ * \date       3 Jul 2014
+ * \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright  Apache License, Version 2.0
+ */
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <curl/curl.h>
+
+#include "bundle_context.h"
+#include "log_helper.h"
+#include "utils.h"
+
+#include "endpoint_descriptor_reader.h"
+#include "discovery.h"
+
+
+#define DISCOVERY_POLL_INTERVAL "DISCOVERY_CFG_POLL_INTERVAL"
+#define DEFAULT_POLL_INTERVAL "10"
+
+
+static void *endpointDiscoveryPoller_performPeriodicPoll(void *data);
+celix_status_t endpointDiscoveryPoller_poll(endpoint_discovery_poller_pt poller, char *url, array_list_pt currentEndpoints);
+static celix_status_t endpointDiscoveryPoller_getEndpoints(endpoint_discovery_poller_pt poller, char *url, array_list_pt *updatedEndpoints);
+static celix_status_t endpointDiscoveryPoller_endpointDescriptionEquals(const void *endpointPtr, const void *comparePtr, bool *equals);
+
+/**
+ * Allocates memory and initializes a new endpoint_discovery_poller instance.
+ */
+celix_status_t endpointDiscoveryPoller_create(discovery_pt discovery, bundle_context_pt context, const char* defaultPollEndpoints, endpoint_discovery_poller_pt *poller) {
+	celix_status_t status;
+
+	*poller = malloc(sizeof(struct endpoint_discovery_poller));
+	if (!*poller) {
+		return CELIX_ENOMEM;
+	}
+
+	(*poller)->loghelper = &discovery->loghelper;
+
+	status = celixThreadMutex_create(&(*poller)->pollerLock, NULL);
+	if (status != CELIX_SUCCESS) {
+		return status;
+	}
+
+	const char* interval = NULL;
+	status = bundleContext_getProperty(context, DISCOVERY_POLL_INTERVAL, &interval);
+	if (!interval) {
+		interval = DEFAULT_POLL_INTERVAL;
+	}
+
+	const char* endpointsProp = NULL;
+	status = bundleContext_getProperty(context, DISCOVERY_POLL_ENDPOINTS, &endpointsProp);
+	if (!endpointsProp) {
+		endpointsProp = defaultPollEndpoints;
+	}
+	// we're going to mutate the string with strtok, so create a copy...
+	char* endpoints = strdup(endpointsProp);
+
+	(*poller)->poll_interval = atoi(interval);
+	(*poller)->discovery = discovery;
+	(*poller)->running = false;
+	(*poller)->entries = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
+
+	const char* sep = ",";
+	char *save_ptr = NULL;
+	char* tok = strtok_r(endpoints, sep, &save_ptr);
+	while (tok) {
+		endpointDiscoveryPoller_addDiscoveryEndpoint(*poller, utils_stringTrim(tok));
+		tok = strtok_r(NULL, sep, &save_ptr);
+	}
+	// Clean up after ourselves...
+	free(endpoints);
+
+	status = celixThreadMutex_lock(&(*poller)->pollerLock);
+	if (status != CELIX_SUCCESS) {
+		return CELIX_BUNDLE_EXCEPTION;
+	}
+
+	(*poller)->running = true;
+
+	status += celixThread_create(&(*poller)->pollerThread, NULL, endpointDiscoveryPoller_performPeriodicPoll, *poller);
+	status += celixThreadMutex_unlock(&(*poller)->pollerLock);
+
+	if(status != CELIX_SUCCESS){
+		status = CELIX_BUNDLE_EXCEPTION;
+	}
+
+	return status;
+}
+
+/**
+ * Destroys and frees up memory for a given endpoint_discovery_poller struct.
+ */
+celix_status_t endpointDiscoveryPoller_destroy(endpoint_discovery_poller_pt poller) {
+	celix_status_t status;
+
+	poller->running = false;
+
+	celixThread_join(poller->pollerThread, NULL);
+
+	hash_map_iterator_pt iterator = hashMapIterator_create(poller->entries);
+	while (hashMapIterator_hasNext(iterator)) {
+		hash_map_entry_pt entry = hashMapIterator_nextEntry(iterator);
+
+		if ( endpointDiscoveryPoller_removeDiscoveryEndpoint(poller, (char*) hashMapEntry_getKey(entry)) == CELIX_SUCCESS) {
+			hashMapIterator_destroy(iterator);
+			iterator = hashMapIterator_create(poller->entries);
+		}
+	}
+	hashMapIterator_destroy(iterator);
+
+	status = celixThreadMutex_lock(&poller->pollerLock);
+
+	if (status != CELIX_SUCCESS) {
+		return CELIX_BUNDLE_EXCEPTION;
+	}
+
+	hashMap_destroy(poller->entries, true, false);
+
+	status = celixThreadMutex_unlock(&poller->pollerLock);
+
+	poller->loghelper = NULL;
+
+	free(poller);
+
+	return status;
+}
+
+
+celix_status_t endpointDiscoveryPoller_getDiscoveryEndpoints(endpoint_discovery_poller_pt poller, array_list_pt urls) {
+	celixThreadMutex_lock(&(poller)->pollerLock);
+
+	hash_map_iterator_pt iterator = hashMapIterator_create(poller->entries);
+
+	while(hashMapIterator_hasNext(iterator))  {
+		hash_map_entry_pt entry = hashMapIterator_nextEntry(iterator);
+		char* toAdd = strdup((char*) hashMapEntry_getKey(entry));
+		arrayList_add(urls, toAdd);
+	}
+
+	hashMapIterator_destroy(iterator);
+
+	celixThreadMutex_unlock(&(poller)->pollerLock);
+
+	return CELIX_SUCCESS;
+}
+
+/**
+ * Adds a new endpoint URL to the list of polled endpoints.
+ */
+celix_status_t endpointDiscoveryPoller_addDiscoveryEndpoint(endpoint_discovery_poller_pt poller, char *url) {
+	celix_status_t status;
+
+	status = celixThreadMutex_lock(&(poller)->pollerLock);
+	if (status != CELIX_SUCCESS) {
+		return CELIX_BUNDLE_EXCEPTION;
+	}
+
+	// Avoid memory leaks when adding an already existing URL...
+	array_list_pt endpoints = hashMap_get(poller->entries, url);
+	if (endpoints == NULL) {
+		status = arrayList_createWithEquals(endpointDiscoveryPoller_endpointDescriptionEquals, &endpoints);
+
+		if (status == CELIX_SUCCESS) {
+			logHelper_log(*poller->loghelper, OSGI_LOGSERVICE_DEBUG, "ENDPOINT_POLLER: add new discovery endpoint with url %s", url);
+			hashMap_put(poller->entries, strdup(url), endpoints);
+			endpointDiscoveryPoller_poll(poller, url, endpoints);
+		}
+	}
+
+	status = celixThreadMutex_unlock(&poller->pollerLock);
+
+	return status;
+}
+
+/**
+ * Removes an endpoint URL from the list of polled endpoints.
+ */
+celix_status_t endpointDiscoveryPoller_removeDiscoveryEndpoint(endpoint_discovery_poller_pt poller, char *url) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (celixThreadMutex_lock(&poller->pollerLock) != CELIX_SUCCESS) {
+		status = CELIX_BUNDLE_EXCEPTION;
+	} else {
+		hash_map_entry_pt entry = hashMap_getEntry(poller->entries, url);
+
+		if (entry == NULL) {
+			logHelper_log(*poller->loghelper, OSGI_LOGSERVICE_DEBUG, "ENDPOINT_POLLER: There was no entry found belonging to url %s - maybe already removed?", url);
+		} else {
+			char* origKey = hashMapEntry_getKey(entry);
+
+			logHelper_log(*poller->loghelper, OSGI_LOGSERVICE_DEBUG, "ENDPOINT_POLLER: remove discovery endpoint with url %s", url);
+
+			array_list_pt entries = hashMap_remove(poller->entries, url);
+
+			if (entries != NULL) {
+				for (unsigned int i = arrayList_size(entries); i > 0; i--) {
+					endpoint_description_pt endpoint = arrayList_get(entries, i - 1);
+					discovery_removeDiscoveredEndpoint(poller->discovery, endpoint);
+					arrayList_remove(entries, i - 1);
+					endpointDescription_destroy(endpoint);
+				}
+				arrayList_destroy(entries);
+			}
+
+			free(origKey);
+		}
+		status = celixThreadMutex_unlock(&poller->pollerLock);
+	}
+
+	return status;
+}
+
+
+
+
+celix_status_t endpointDiscoveryPoller_poll(endpoint_discovery_poller_pt poller, char *url, array_list_pt currentEndpoints) {
+	celix_status_t status;
+	array_list_pt updatedEndpoints = NULL;
+
+	// create an arraylist with a custom equality test to ensure we can find endpoints properly...
+	arrayList_createWithEquals(endpointDiscoveryPoller_endpointDescriptionEquals, &updatedEndpoints);
+	status = endpointDiscoveryPoller_getEndpoints(poller, url, &updatedEndpoints);
+
+	if (status == CELIX_SUCCESS) {
+		if (updatedEndpoints!=NULL) {
+			for (unsigned int i = arrayList_size(currentEndpoints); i > 0; i--) {
+				endpoint_description_pt endpoint = arrayList_get(currentEndpoints, i - 1);
+
+				if (!arrayList_contains(updatedEndpoints, endpoint)) {
+					status = discovery_removeDiscoveredEndpoint(poller->discovery, endpoint);
+					arrayList_remove(currentEndpoints, i - 1);
+					endpointDescription_destroy(endpoint);
+				}
+			}
+
+			for (int i = arrayList_size(updatedEndpoints); i > 0; i--) {
+				endpoint_description_pt endpoint = arrayList_remove(updatedEndpoints, 0);
+
+				if (!arrayList_contains(currentEndpoints, endpoint)) {
+					arrayList_add(currentEndpoints, endpoint);
+					status = discovery_addDiscoveredEndpoint(poller->discovery, endpoint);
+				} else {
+					endpointDescription_destroy(endpoint);
+
+				}
+			}
+		}
+	}
+
+	if(updatedEndpoints!=NULL){
+		arrayList_destroy(updatedEndpoints);
+	}
+
+	return status;
+}
+
+static void *endpointDiscoveryPoller_performPeriodicPoll(void *data) {
+	endpoint_discovery_poller_pt poller = (endpoint_discovery_poller_pt) data;
+
+	useconds_t interval = (useconds_t) (poller->poll_interval * 1000000L);
+
+	while (poller->running) {
+		usleep(interval);
+		celix_status_t status = celixThreadMutex_lock(&poller->pollerLock);
+
+		if (status != CELIX_SUCCESS) {
+			logHelper_log(*poller->loghelper, OSGI_LOGSERVICE_WARNING, "ENDPOINT_POLLER: failed to obtain lock; retrying...");
+		} else {
+			hash_map_iterator_pt iterator = hashMapIterator_create(poller->entries);
+
+			while (hashMapIterator_hasNext(iterator)) {
+				hash_map_entry_pt entry = hashMapIterator_nextEntry(iterator);
+
+				char *url = hashMapEntry_getKey(entry);
+				array_list_pt currentEndpoints = hashMapEntry_getValue(entry);
+
+				endpointDiscoveryPoller_poll(poller, url, currentEndpoints);
+			}
+
+			hashMapIterator_destroy(iterator);
+		}
+
+		status = celixThreadMutex_unlock(&poller->pollerLock);
+		if (status != CELIX_SUCCESS) {
+			logHelper_log(*poller->loghelper, OSGI_LOGSERVICE_WARNING, "ENDPOINT_POLLER: failed to release lock; retrying...");
+		}
+	}
+
+	return NULL;
+}
+
+
+
+struct MemoryStruct {
+	char *memory;
+	size_t size;
+};
+
+static size_t endpointDiscoveryPoller_writeMemory(void *contents, size_t size, size_t nmemb, void *memoryPtr) {
+	size_t realsize = size * nmemb;
+	struct MemoryStruct *mem = (struct MemoryStruct *)memoryPtr;
+
+	mem->memory = realloc(mem->memory, mem->size + realsize + 1);
+	if(mem->memory == NULL) {
+		printf("ENDPOINT_POLLER: not enough memory (realloc returned NULL)!");
+		return 0;
+	}
+
+	memcpy(&(mem->memory[mem->size]), contents, realsize);
+	mem->size += realsize;
+	mem->memory[mem->size] = 0;
+
+	return realsize;
+}
+
+static celix_status_t endpointDiscoveryPoller_getEndpoints(endpoint_discovery_poller_pt poller, char *url, array_list_pt *updatedEndpoints) {
+	celix_status_t status = CELIX_SUCCESS;
+
+
+	CURL *curl = NULL;
+	CURLcode res = CURLE_OK;
+
+	struct MemoryStruct chunk;
+	chunk.memory = malloc(1);
+	chunk.size = 0;
+
+	curl = curl_easy_init();
+	if (!curl) {
+		status = CELIX_ILLEGAL_STATE;
+	} else {
+		curl_easy_setopt(curl, CURLOPT_URL, url);
+		curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, endpointDiscoveryPoller_writeMemory);
+		curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
+		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L);
+		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
+		res = curl_easy_perform(curl);
+
+		curl_easy_cleanup(curl);
+	}
+
+	// process endpoints file
+	if (res == CURLE_OK) {
+		endpoint_descriptor_reader_pt reader = NULL;
+
+		status = endpointDescriptorReader_create(poller, &reader);
+		if (status == CELIX_SUCCESS) {
+			status = endpointDescriptorReader_parseDocument(reader, chunk.memory, updatedEndpoints);
+		}
+
+		if (reader) {
+			endpointDescriptorReader_destroy(reader);
+		}
+	} else {
+		logHelper_log(*poller->loghelper, OSGI_LOGSERVICE_ERROR, "ENDPOINT_POLLER: unable to read endpoints from %s, reason: %s", url, curl_easy_strerror(res));
+	}
+
+	// clean up endpoints file
+	if (chunk.memory) {
+		free(chunk.memory);
+	}
+
+	return status;
+}
+
+static celix_status_t endpointDiscoveryPoller_endpointDescriptionEquals(const void *endpointPtr, const void *comparePtr, bool *equals) {
+	endpoint_description_pt endpoint = (endpoint_description_pt) endpointPtr;
+	endpoint_description_pt compare = (endpoint_description_pt) comparePtr;
+
+	if (strcmp(endpoint->id, compare->id) == 0) {
+		*equals = true;
+	} else {
+		*equals = false;
+	}
+
+	return CELIX_SUCCESS;
+}


Mime
View raw message