--- a/minissdpd/minissdpd.c
+++ b/minissdpd/minissdpd.c
@@ -32,6 +32,8 @@
 #include <pwd.h>
 #include <grp.h>
 #endif
+/* for uloop thread */
+#include <pthread.h>
 
 /* LOG_PERROR does not exist on Solaris */
 #ifndef LOG_PERROR
@@ -52,6 +54,10 @@
 #define MIN(x,y) (((x)<(y))?(x):(y))
 #endif
 
+extern char *ssdp_sockpath;
+void upnp_thread_discover_devices(void);
+void ssdpd_ubus_stop(void);
+
 /* current request management structure */
 struct reqelem {
 	int socket;
@@ -1220,6 +1226,12 @@ static void ssdpDiscover(int s, int ipv6
 	}
 }
 
+static void *thread_discover_devices(void *args __attribute__((unused)))
+{
+	upnp_thread_discover_devices();
+	return NULL;
+}
+
 /* main(): program entry point */
 int main(int argc, char * * argv)
 {
@@ -1264,6 +1276,7 @@ int main(int argc, char * * argv)
 	unsigned char ttl = 2;	/* UDA says it should default to 2 */
 	const char * searched_device = NULL;	/* if not NULL, search/filter a specific device type */
 	int opt;
+	pthread_t upnp_thread;
 
 	LIST_INIT(&reqlisthead);
 	LIST_INIT(&servicelisthead);
@@ -1309,6 +1322,7 @@ int main(int argc, char * * argv)
 			break;
 		case 's':
 			sockpath = optarg;
+			ssdp_sockpath = optarg;
 			break;
 #ifndef NO_BACKGROUND_NO_PIDFILE
 		case 'p':
@@ -1496,6 +1510,11 @@ int main(int argc, char * * argv)
 	if(s_ssdp6 >= 0)
 		ssdpDiscover(s_ssdp6, 1, searched_device);
 
+	int err = pthread_create(&upnp_thread, NULL, &thread_discover_devices, NULL);
+	if (err < 0) {
+		syslog(LOG_ERR, "Error when creating upnp thread");
+	}
+
 	/* Main loop */
 	while(!quitting) {
 		/* fill readfds fd_set */
@@ -1704,6 +1723,8 @@ quit:
 	if(unlink(pidfilename) < 0)
 		syslog(LOG_ERR, "unlink(%s): %m", pidfilename);
 #endif
+	ssdpd_ubus_stop();
+	pthread_join(upnp_thread, NULL);
 	closelog();
 	return ret;
 }
--- a/minissdpd/ssdpd.c
+++ b/minissdpd/ssdpd.c
@@ -39,10 +39,9 @@ struct desc_list_elt {
 	struct list_head list;
 	char *url;
 	char *desc_path;
-	bool is_device_desc;
 };
 
-#define UPNP_DESC_PATH "/etc/upnp/description"
+#define UPNP_DESC_PATH "/tmp/ssdp/description"
 #define UPNP_DISCOVER_TIMEOUT (30 * 1000)
 
 #ifndef MIN
@@ -93,17 +92,41 @@ static void add_dev_to_dev_list(char *de
 	dev->usn = usn;
 }
 
-void free_all_dev_list(void)
+static void free_all_dev_list(void)
 {
 	struct UPNPDev *dev = NULL;
+	struct UPNPDev *dev_tmp = NULL;
 
-	while (dev_list.next != &dev_list) {
-		dev = list_entry(dev_list.next, struct UPNPDev, list);
+	list_for_each_entry_safe(dev, dev_tmp, &dev_list, list) {
+		list_del(&dev->list);
 		free(dev->descURL);
 		free(dev->st);
 		free(dev->usn);
 		free(dev);
-		list_del(&dev->list);
+	}
+}
+
+static void add_desc_to_desc_list(const char *desc_path, const char *url)
+{
+	struct desc_list_elt *desc_elt;
+
+	desc_elt = calloc(1, sizeof(struct desc_list_elt));
+	list_add_tail(&desc_elt->list, &desc_list);
+
+	desc_elt->desc_path = strdup(desc_path);
+	desc_elt->url = strdup(url);
+}
+
+static void free_all_desc_list(void)
+{
+	struct desc_list_elt *desc_elt = NULL;
+	struct desc_list_elt *desc_elt_tmp = NULL;
+
+	list_for_each_entry_safe(desc_elt, desc_elt_tmp, &desc_list, list) {
+		list_del(&desc_elt->list);
+		free(desc_elt->desc_path);
+		free(desc_elt->url);
+		free(desc_elt);
 	}
 }
 
@@ -167,8 +190,8 @@ static int receiveDevicesFromMiniSSDPD(i
 	ssize_t n;
 	unsigned char *p;
 	unsigned int bufferindex;
-	unsigned int i, ndev;
-	unsigned int urlsize, stsize, usnsize, l;
+	unsigned int i = 0, ndev = 0;
+	unsigned int urlsize = 0, stsize = 0, usnsize = 0, l = 0;
 	char *url, *st, *usn;
 
 	n = read(s, buffer, sizeof(buffer));
@@ -182,11 +205,12 @@ static int receiveDevicesFromMiniSSDPD(i
 		if (n <= 0)
 			return -1;
 
-		url = (char *)malloc(urlsize);
+		url = (char *)calloc(urlsize + 1, sizeof(char));
 		if (url == NULL)
 			return -1;
 
 		READ_COPY_BUFFER(url, urlsize);
+		url[urlsize] = 0;
 		if (n <= 0)
 			return -1;
 
@@ -194,11 +218,12 @@ static int receiveDevicesFromMiniSSDPD(i
 		if (n <= 0)
 			goto free_url_and_return;
 
-		st = (char *)malloc(stsize);
+		st = (char *)calloc(stsize + 1, sizeof(char));
 		if (st == NULL)
 			goto free_url_and_return;
 
 		READ_COPY_BUFFER(st, stsize);
+		st[stsize] = 0;
 		if (n <= 0)
 			goto free_url_and_st_and_return;
 
@@ -206,11 +231,12 @@ static int receiveDevicesFromMiniSSDPD(i
 		if (n <= 0)
 			goto free_url_and_st_and_return;
 
-		usn = (char *)malloc(usnsize);
+		usn = (char *)calloc(usnsize + 1, sizeof(char));
 		if (usn == NULL)
 			goto free_url_and_st_and_return;
 
 		READ_COPY_BUFFER(usn, usnsize);
+		usn[usnsize] = 0;
 		if (n <= 0)
 			goto free_url_and_st_and_usn_and_return;
 
@@ -282,6 +308,21 @@ static bool is_desc_exist(const char *de
 	return false;
 }
 
+static bool is_device_exist(const char *dev_url)
+{
+	struct UPNPDev *dev = NULL;
+
+	if (!dev_url)
+		return false;
+
+	list_for_each_entry(dev, &dev_list, list) {
+		if (strcmp(dev->descURL, dev_url) == 0)
+			return true;
+	}
+
+	return false;
+}
+
 static void get_desc_name(const char *desc_url, char *str, size_t len)
 {
 	if (!desc_url || !str || len == 0)
@@ -297,37 +338,14 @@ static void get_desc_name(const char *de
 	}
 }
 
-static void add_desc_to_desc_list(const char *desc_path, const char *url, int is_device_desc)
-{
-	struct desc_list_elt *desc_elt;
-
-	desc_elt = calloc(1, sizeof(struct desc_list_elt));
-	list_add_tail(&desc_elt->list, &desc_list);
-
-	desc_elt->desc_path = strdup(desc_path);
-	desc_elt->url = strdup(url);
-	desc_elt->is_device_desc = is_device_desc;
-}
-
-static void free_all_desc_list(void)
-{
-	struct desc_list_elt *desc_elt = NULL;
-
-	while (desc_list.next != &desc_list) {
-		desc_elt = list_entry(desc_list.next, struct desc_list_elt, list);
-		free(desc_elt->desc_path);
-		free(desc_elt->url);
-		free(desc_elt);
-		list_del(&desc_elt->list);
-	}
-}
-
 static void __upnp_discover_devices(void)
 {
+	struct desc_list_elt *desc_elt = NULL;
+	struct desc_list_elt *desc_elt_tmp = NULL;
 	struct UPNPDev *dev = NULL;
 	char desc_name[128] = {0};
 	char file_path[256] = {0};
-	int res = 0, is_device_desc = 0;
+	int res = 0;
 
 	/*
 	 * Discover devices
@@ -349,13 +367,26 @@ static void __upnp_discover_devices(void
 
 		get_desc_name(dev->descURL, desc_name, sizeof(desc_name));
 		snprintf(file_path, sizeof(file_path), "%s/%s", UPNP_DESC_PATH, desc_name);
-		is_device_desc = (dev->usn && strstr(dev->usn, ":service:")) ? 0 : 1;
 
 		// Download Description
 		download_file(file_path, dev->descURL);
 
 		// Add description to descriptions list
-		add_desc_to_desc_list(file_path, dev->descURL, is_device_desc);
+		add_desc_to_desc_list(file_path, dev->descURL);
+	}
+
+	/*
+	 * Remove unused descriptions
+	 */
+	list_for_each_entry_safe(desc_elt, desc_elt_tmp, &desc_list, list) {
+
+		if (is_device_exist(desc_elt->url))
+			continue;
+
+		list_del(&desc_elt->list);
+		free(desc_elt->desc_path);
+		free(desc_elt->url);
+		free(desc_elt);
 	}
 
 end:
@@ -371,15 +402,27 @@ static int upnp_discovery_res(struct ubu
 	memset(&bb,0,sizeof(struct blob_buf));
 	blob_buf_init(&bb, 0);
 
+	void *root_devices_array = blobmsg_open_array(&bb, "root_devices");
+	list_for_each_entry_reverse(dev, &dev_list, list) {
+		// Parse root device
+		if (dev->st && strstr(dev->st, ":rootdevice") != NULL) {
+			void *device_obj = blobmsg_open_table(&bb, NULL);
+			blobmsg_add_string(&bb, "descurl", dev->descURL);
+			blobmsg_add_string(&bb, "st", dev->st);
+			blobmsg_add_string(&bb, "usn", dev->usn);
+			blobmsg_close_table(&bb, device_obj);
+		}
+	}
+	blobmsg_close_array(&bb, root_devices_array);
+
 	void *devices_array = blobmsg_open_array(&bb, "devices");
 	list_for_each_entry_reverse(dev, &dev_list, list) {
-		// Parse Root device and devices
-		if ((dev->st && strstr(dev->st, ":rootdevice") != NULL) || (dev->usn && strstr(dev->usn, ":device:") != NULL)) {
+		// Parse devices
+		if (dev->usn && strstr(dev->usn, ":device:") != NULL) {
 			void *device_obj = blobmsg_open_table(&bb, NULL);
 			blobmsg_add_string(&bb, "descurl", dev->descURL);
 			blobmsg_add_string(&bb, "st", dev->st);
 			blobmsg_add_string(&bb, "usn", dev->usn);
-			blobmsg_add_string(&bb, "is_root_device", dev->st && strstr(dev->st, ":rootdevice") ? "1" : "0");
 			blobmsg_close_table(&bb, device_obj);
 		}
 	}
@@ -472,7 +515,7 @@ static void fill_device_instances(struct
 		blobmsg_close_table(bb, device_obj);
 }
 
-static void fill_service_element(struct blob_buf *bb, mxml_node_t *service)
+static void fill_service_instances(struct blob_buf *bb, mxml_node_t *service)
 {
 	mxml_node_t *b = service;
 	void *service_obj = NULL;
@@ -525,6 +568,32 @@ static void fill_service_element(struct
 		blobmsg_close_table(bb, service_obj);
 }
 
+static void fill_device_service_instances(struct blob_buf *bb, bool is_device)
+{
+	struct desc_list_elt *desc_elt = NULL;
+
+	list_for_each_entry(desc_elt, &desc_list, list) {
+
+		FILE *fp = fopen(desc_elt->desc_path, "r");
+		if (!fp)
+			continue;
+
+		mxml_node_t *tree = mxmlLoadFile(NULL, fp, MXML_OPAQUE_CALLBACK);
+		fclose(fp);
+
+		if (tree) {
+	 		mxml_node_t *node = mxmlFindElement(tree, tree, "device", NULL, NULL, MXML_DESCEND);
+			
+			if (is_device)
+				fill_device_instances(bb, node);
+			else
+				fill_service_instances(bb, node);
+
+			mxmlDelete(tree);
+		}
+	}
+}
+
 static int upnp_description_res(struct ubus_context *ctx, struct ubus_object *obj __attribute__((unused)),
 		struct ubus_request_data *req, const char *method __attribute__((unused)), struct blob_attr *msg __attribute__((unused)))
 {
@@ -534,39 +603,25 @@ static int upnp_description_res(struct u
 	memset(&bb,0,sizeof(struct blob_buf));
 	blob_buf_init(&bb, 0);
 
+	// Descriptions Array
 	void *desc_array = blobmsg_open_array(&bb, "descriptions");
 	list_for_each_entry(desc_elt, &desc_list, list) {
 		void *device_obj = blobmsg_open_table(&bb, NULL);
 		blobmsg_add_string(&bb, "desc_url", desc_elt->url);
-		blobmsg_add_u32(&bb, "is_device_desc", desc_elt->is_device_desc);
 		blobmsg_close_table(&bb, device_obj);
 
 	}
 	blobmsg_close_array(&bb, desc_array);
 
-	list_for_each_entry(desc_elt, &desc_list, list) {
-
-		FILE *fp = fopen(desc_elt->desc_path, "r");
-		if (!fp)
-			continue;
-
-		mxml_node_t *tree = mxmlLoadFile(NULL, fp, MXML_OPAQUE_CALLBACK);
-		fclose(fp);
-
-		if (tree) {
-			void *devices_array = blobmsg_open_array(&bb, "devices");
-	 		mxml_node_t *device = mxmlFindElement(tree, tree, "device", NULL, NULL, MXML_DESCEND);
-			fill_device_instances(&bb, device);
-			blobmsg_close_array(&bb, devices_array);
-
-			void *services_array = blobmsg_open_array(&bb, "services");
-	 		mxml_node_t *service = mxmlFindElement(tree, tree, "device", NULL, NULL, MXML_DESCEND);
-			fill_service_element(&bb, service);
-			blobmsg_close_array(&bb, services_array);
+	// Devices Array
+	void *devices_array = blobmsg_open_array(&bb, "devices");
+	fill_device_service_instances(&bb, true);
+	blobmsg_close_array(&bb, devices_array);
 
-			mxmlDelete(tree);
-		}
-	}
+	// Services Array
+	void *services_array = blobmsg_open_array(&bb, "services");
+	fill_device_service_instances(&bb, false);
+	blobmsg_close_array(&bb, services_array);
 
 	ubus_send_reply(ctx, req, bb.head);
 	blob_buf_free(&bb);
@@ -624,3 +679,9 @@ end:
 	uloop_done();
 	ubus_free(ctx);
 }
+
+void ssdpd_ubus_stop(void)
+{
+	uloop_end();
+}
+
--- a/minissdpd/config.h
+++ b/minissdpd/config.h
@@ -32,7 +32,7 @@
 
 /* When NO_BACKGROUND_NO_PIDFILE is defined, minissdpd does not go to
  * background and does not create any pidfile */
-/*#define NO_BACKGROUND_NO_PIDFILE*/
+#define NO_BACKGROUND_NO_PIDFILE
 
 /* define HAVE_IP_MREQN to use struct ip_mreqn instead of struct ip_mreq
  * for setsockopt(IP_MULTICAST_IF). Available with Linux 2.4+,
