mirror of
https://dev.iopsys.eu/feed/iopsys.git
synced 2025-12-10 07:44:50 +01:00
420 lines
11 KiB
Text
420 lines
11 KiB
Text
--- 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+,
|