From 8bb44d97e49251dbf4c8d6b66956b91c7d2144cf Mon Sep 17 00:00:00 2001 From: Niklas Hofmann Date: Thu, 31 Jul 2014 01:44:43 +0200 Subject: [PATCH] avahi mdns integration --- src/discovery.c | 95 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 83 insertions(+), 12 deletions(-) diff --git a/src/discovery.c b/src/discovery.c index a57cfb83..834822aa 100644 --- a/src/discovery.c +++ b/src/discovery.c @@ -13,8 +13,79 @@ #include #define MESHLINK_MDNS_SERVICE_TYPE "_meshlink._tcp" -#define MESHLINK_MDNS_SERVICE_NAME "Meshlink" +//#define MESHLINK_MDNS_SERVICE_NAME "Meshlink" +#define MESHLINK_MDNS_FINGERPRINT_KEY "fingerprint" + +static void discovery_resolve_callback( + AvahiSServiceResolver *resolver, + AVAHI_GCC_UNUSED AvahiIfIndex interface, + AVAHI_GCC_UNUSED AvahiProtocol protocol, + AvahiResolverEvent event, + const char *name, + const char *type, + const char *domain, + const char *host_name, + const AvahiAddress *address, + uint16_t port, + AvahiStringList *txt, + AvahiLookupResultFlags flags, + AVAHI_GCC_UNUSED void* userdata) +{ + meshlink_handle_t *mesh = userdata; + + /* Called whenever a service has been resolved successfully or timed out */ + + switch (event) + { + case AVAHI_RESOLVER_FAILURE: + fprintf(stderr, "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror(avahi_server_errno(mesh->avahi_server))); + break; + + case AVAHI_RESOLVER_FOUND: + { + char straddr[AVAHI_ADDRESS_STR_MAX], *strtxt; + + fprintf(stderr, "(Resolver) Service '%s' of type '%s' in domain '%s':\n", name, type, domain); + + avahi_address_snprint(straddr, sizeof(straddr), address); + strtxt = avahi_string_list_to_string(txt); + fprintf(stderr, + "\t%s:%u (%s)\n" + "\tTXT=%s\n" + "\tcookie is %u\n" + "\tis_local: %i\n" + "\twide_area: %i\n" + "\tmulticast: %i\n" + "\tcached: %i\n", + host_name, port, straddr, + strtxt, + avahi_string_list_get_service_cookie(txt), + !!(flags & AVAHI_LOOKUP_RESULT_LOCAL), + !!(flags & AVAHI_LOOKUP_RESULT_WIDE_AREA), + !!(flags & AVAHI_LOOKUP_RESULT_MULTICAST), + !!(flags & AVAHI_LOOKUP_RESULT_CACHED)); + avahi_free(strtxt); + + // retrieve fingerprint + AvahiStringList *fgli = avahi_string_list_find(txt, MESHLINK_MDNS_FINGERPRINT_KEY); + meshlink_node_t *node = meshlink_get_node(mesh, name); + + fprintf(stderr, "%p, %p, %s, %s\n", fgli, node, avahi_string_list_get_text(fgli), meshlink_get_fingerprint(mesh, node)); + + if( node && fgli && strcmp(avahi_string_list_get_text(fgli)+strlen(MESHLINK_MDNS_FINGERPRINT_KEY)+1, meshlink_get_fingerprint(mesh, node)) == 0 ) + { + fprintf(stderr, "Node %s is part of the mesh network - updating ip address.\n", node->name); + } + else + { + fprintf(stderr, "Node %s is not part of the mesh network - ignoring ip address.\n", node->name); + } + } + } + + avahi_s_service_resolver_free(resolver); +} static void discovery_entry_group_callback(AvahiServer *server, AvahiSEntryGroup *group, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata) { @@ -25,11 +96,11 @@ static void discovery_entry_group_callback(AvahiServer *server, AvahiSEntryGroup { case AVAHI_ENTRY_GROUP_ESTABLISHED: /* The entry group has been established successfully */ - fprintf(stderr, "Service '%s' successfully established.\n", MESHLINK_MDNS_SERVICE_NAME); + fprintf(stderr, "Service '%s' successfully established.\n", /*MESHLINK_MDNS_SERVICE_NAME*/ mesh->name); break; case AVAHI_ENTRY_GROUP_COLLISION: - fprintf(stderr, "Service name collision '%s'\n", MESHLINK_MDNS_SERVICE_NAME); + fprintf(stderr, "Service name collision '%s'\n", /*MESHLINK_MDNS_SERVICE_NAME*/ mesh->name); break; case AVAHI_ENTRY_GROUP_FAILURE : @@ -48,22 +119,22 @@ static void discovery_entry_group_callback(AvahiServer *server, AvahiSEntryGroup static void discovery_create_services(meshlink_handle_t *mesh) { + fprintf(stderr, "Adding service '%s'\n", /*MESHLINK_MDNS_SERVICE_NAME*/ mesh->name); + /* If this is the first time we're called, let's create a new entry group */ if (!mesh->avahi_group) - if (!(mesh->avahi_group = avahi_s_entry_group_new(mesh->avahi_server, discovery_entry_group_callback, NULL))) { + if (!(mesh->avahi_group = avahi_s_entry_group_new(mesh->avahi_server, discovery_entry_group_callback, mesh))) { fprintf(stderr, "avahi_entry_group_new() failed: %s\n", avahi_strerror(avahi_server_errno(mesh->avahi_server))); goto fail; } - fprintf(stderr, "Adding service '%s'\n", MESHLINK_MDNS_SERVICE_NAME); - /* Create some random TXT data */ - char fingerprint[1024]; - snprintf(fingerprint, sizeof(fingerprint), "fingerprint=%s", /*meshlink_get_fingerprint(mesh, mesh->self)*/ ""); + char fingerprint[1024] = ""; + snprintf(fingerprint, sizeof(fingerprint), "%s=%s", MESHLINK_MDNS_FINGERPRINT_KEY, meshlink_get_fingerprint(mesh, meshlink_get_node(mesh, mesh->name))); /* Add the service for IPP */ int ret = 0; - if ((ret = avahi_server_add_service(mesh->avahi_server, mesh->avahi_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, MESHLINK_MDNS_SERVICE_NAME, MESHLINK_MDNS_SERVICE_TYPE, NULL, NULL, mesh->myport ? atoi(mesh->myport) : 655, fingerprint, NULL)) < 0) { + if ((ret = avahi_server_add_service(mesh->avahi_server, mesh->avahi_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, /*MESHLINK_MDNS_SERVICE_NAME*/ mesh->name, MESHLINK_MDNS_SERVICE_TYPE, NULL, NULL, mesh->myport ? atoi(mesh->myport) : 655, fingerprint, NULL)) < 0) { fprintf(stderr, "Failed to add _ipp._tcp service: %s\n", avahi_strerror(ret)); goto fail; } @@ -144,8 +215,8 @@ static void discovery_browse_callback( function we free it. If the server is terminated before the callback function is called the server will free the resolver for us. */ - //if (!(avahi_s_service_resolver_new(s, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, server))) - // fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_server_errno(server))); + if (!(avahi_s_service_resolver_new(mesh->avahi_server, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, discovery_resolve_callback, mesh))) + fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_server_errno(mesh->avahi_server))); break; case AVAHI_BROWSER_REMOVE: @@ -184,7 +255,7 @@ bool discovery_start(meshlink_handle_t *mesh) /* Allocate a new server */ int error; - mesh->avahi_server = avahi_server_new(avahi_simple_poll_get(mesh->avahi_poll), &config, discovery_server_callback, NULL, &error); + mesh->avahi_server = avahi_server_new(avahi_simple_poll_get(mesh->avahi_poll), &config, discovery_server_callback, mesh, &error); /* Free the configuration data */ avahi_server_config_free(&config); -- 2.39.5