#include <time.h>
#include <libubus.h>
-#include <libubox/vlist.h>
#include <libubox/uloop.h>
-#include <libubox/avl-cmp.h>
#include <libubox/blobmsg_json.h>
#include "ubus.h"
__SERVICE_MAX,
};
-struct service {
- struct vlist_node node;
-
- time_t t;
-
- const char *id;
- const char *instance;
- const char *service;
- const uint8_t *txt;
- int txt_len;
- int port;
- int active;
-};
-
static const struct blobmsg_policy service_policy[__SERVICE_MAX] = {
[SERVICE_INSTANCE] = { .name = "instance", .type = BLOBMSG_TYPE_STRING },
[SERVICE_SERVICE] = { .name = "service", .type = BLOBMSG_TYPE_STRING },
[SERVICE_HOSTNAME] = { .name = "hostname", .type = BLOBMSG_TYPE_STRING },
};
-static void
-service_update(struct vlist_tree *tree, struct vlist_node *node_new,
- struct vlist_node *node_old);
-
static void
hostname_update(struct vlist_tree *tree, struct vlist_node *node_new,
struct vlist_node *node_old);
static struct blob_buf b;
-static VLIST_TREE(services, avl_strcmp, service_update, false, false);
+VLIST_TREE(announced_services, avl_strcmp, service_update, false, false);
VLIST_TREE(hostnames, avl_strcmp, hostname_update, false, false);
static int service_init_announce;
{
struct service *s;
- vlist_for_each_element(&services, s, node) {
+ vlist_for_each_element(&announced_services, s, node) {
if (instance && strcmp(s->instance, instance))
continue;
if (service_domain && strcmp(s->service, service_domain))
{
struct service *s;
- vlist_for_each_element(&services, s, node) {
+ vlist_for_each_element(&announced_services, s, node) {
s->t = 0;
if (ttl) {
dns_init_answer();
}
}
-static void
+void
service_update(struct vlist_tree *tree, struct vlist_node *node_new,
struct vlist_node *node_old)
{
d_txt += len;
}
- vlist_add(&services, &s->node, s->id);
+ vlist_add(&announced_services, &s->node, s->id);
}
static void
get_hostname();
- vlist_update(&services);
+ vlist_update(&announced_services);
vlist_update(&hostnames);
service_load("/etc/umdns/*");
}
}
}
- vlist_flush(&services);
+ vlist_flush(&announced_services);
vlist_flush(&hostnames);
}
void
service_cleanup(void)
{
- vlist_flush(&services);
+ vlist_flush(&announced_services);
blob_buf_free(&b);
}
#ifndef _SERVICE_H__
#define _SERVICE_H__
+#include <libubox/vlist.h>
+#include <libubox/avl-cmp.h>
+
+struct service {
+ struct vlist_node node;
+
+ time_t t;
+
+ const char *id;
+ const char *instance;
+ const char *service;
+ const uint8_t *txt;
+ int txt_len;
+ int port;
+ int active;
+};
+
struct hostname {
struct vlist_node node;
const char *hostname;
};
extern struct vlist_tree hostnames;
+extern struct vlist_tree announced_services;
extern void service_init(int announce);
extern void service_cleanup(void);
extern void service_reply(struct interface *iface, struct sockaddr *to, const char *instance, const char *service_domain, int ttl);
extern void service_announce_services(struct interface *iface, struct sockaddr *to, int ttl);
+extern void service_update(struct vlist_tree *tree, struct vlist_node *node_new, struct vlist_node *node_old);
#endif
#include <arpa/inet.h>
#include <stdio.h>
+#include <ctype.h>
#include <libubus.h>
#include <libubox/vlist.h>
return 0;
}
+static int
+umdns_announcements(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct service *s;
+ void *c1 = NULL, *c2 = NULL;
+
+ blob_buf_init(&b, 0);
+ vlist_for_each_element(&announced_services, s, node) {
+ // is something there?
+ if (!s->id || !strlen(s->id))
+ continue;
+
+ if (!s->service || !strlen(s->service))
+ continue;
+
+ if (!s->port)
+ continue;
+
+ if (!c1) {
+ c1 = blobmsg_open_table(&b, (const char *) s->service);
+ }
+
+ c2 = blobmsg_open_table(&b, s->id);
+
+ blobmsg_add_u32(&b, "port", s->port);
+
+ // check if there are any text entries
+ if (s->txt_len) {
+ void *c_txt = NULL;
+ int i;
+
+ // this string will hold text records
+ char *txt_str = (char *) calloc(s->txt_len, sizeof(char));
+
+ // we get some weird characters like \u000b, so get don't copy them
+ for (i=0; i<s->txt_len; i++) {
+ if ((ispunct(s->txt[i])) || (isalnum(s->txt[i])))
+ txt_str[i] = (char) s->txt[i];
+ else
+ txt_str[i] = ' ';
+ }
+
+ txt_str[s->txt_len] = '\0';
+
+ // a table of txt json objects
+ c_txt = blobmsg_open_array(&b, "txt");
+
+ // split based on space and add each token to output
+ char *pch = NULL, *pchr = NULL;
+
+ for (pch = strtok_r(txt_str, " ", &pchr); pch != NULL; pch = strtok_r(NULL, " ", &pchr)) {
+ // add it to array
+ blobmsg_add_string(&b, "txt", pch);
+ }
+
+ // close the array
+ blobmsg_close_array(&b, c_txt);
+
+ // free the calloced memory
+ free(txt_str);
+ }
+
+ blobmsg_close_table(&b, c2);
+ blobmsg_close_table(&b, c1);
+ c1 = NULL;
+ }
+
+ ubus_send_reply(ctx, req, b.head);
+
+ return UBUS_STATUS_OK;
+}
+
enum {
BROWSE_SERVICE,
BROWSE_ARRAY,
address = blobmsg_get_bool(data[BROWSE_ADDRESS]);
blob_buf_init(&b, 0);
+
avl_for_each_element(&services, s, avl) {
const char *hostname = buffer;
char *local;
c1 = NULL;
}
}
+
ubus_send_reply(ctx, req, b.head);
return UBUS_STATUS_OK;
UBUS_METHOD("query", umdns_query, query_policy),
UBUS_METHOD("fetch", umdns_query, query_policy),
UBUS_METHOD("browse", umdns_browse, browse_policy),
+ UBUS_METHOD_NOARG("announcements", umdns_announcements),
UBUS_METHOD_NOARG("update", umdns_update),
UBUS_METHOD("hosts", umdns_hosts, hosts_policy),
UBUS_METHOD_NOARG("reload", umdns_reload),