From b2f9c6458bacc03d726d942ad7b1f62b4ec0183a Mon Sep 17 00:00:00 2001 From: Dan Staples Date: Thu, 27 Mar 2014 11:46:08 -0400 Subject: [PATCH 1/4] create new avahi server periodically to query remote services --- main.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index 66b36ca..1e95bd9 100644 --- a/main.c +++ b/main.c @@ -14,11 +14,14 @@ #include "commotion-service-manager.h" #include "debug.h" +#define UPDATE_INTERVAL 30 + extern struct arguments arguments; static int pid_filehandle; extern AvahiSimplePoll *simple_poll; extern AvahiServer *server; +AvahiServerConfig config; /** Parse commandline options */ static error_t parse_opt (int key, char *arg, struct argp_state *state) { @@ -139,8 +142,50 @@ static void daemon_start(char *pidfile) { } +static void query_server_callback(AvahiServer *s, AvahiServerState state, void* userdata) { + AvahiServer **query_server = (AvahiServer**)userdata; + assert(s && s == *query_server); + + switch (state) { + case AVAHI_SERVER_RUNNING: + DEBUG("Query_server created and running"); + avahi_server_free(s); + *query_server = NULL; + break; + case AVAHI_SERVER_COLLISION: + ERROR("AVAHI_SERVER_COLLISION"); + case AVAHI_SERVER_REGISTERING: + ERROR("AVAHI_SERVER_REGISTERING"); + case AVAHI_SERVER_INVALID: + ERROR("AVAHI_SERVER_INVALID"); + case AVAHI_SERVER_FAILURE: + ERROR("Query_server failure: %s\n", avahi_strerror(avahi_server_errno(s))); + avahi_simple_poll_quit(simple_poll); + } +} + +static void query_services(AvahiTimeout *t, void *userdata) { + AvahiServer **query_server = (AvahiServer**)userdata; + assert(query_server); + assert(t); + + if (*query_server) { + ERROR("query_server already exists"); + return; + } + + int error; + *query_server = avahi_server_new(avahi_simple_poll_get(simple_poll), &config, query_server_callback, query_server, &error); + if (!*query_server) + ERROR("Failed to create server: %s", avahi_strerror(error)); + + struct timeval tv = {0}; + avahi_elapse_time(&tv, 1000*UPDATE_INTERVAL, 0); + timeout_update(t, &tv); +} + int main(int argc, char*argv[]) { - AvahiServerConfig config; + AvahiServer *query_server = NULL; AvahiSServiceTypeBrowser *stb = NULL; int error; int ret = 1; @@ -215,6 +260,10 @@ int main(int argc, char*argv[]) { CHECK((stb = avahi_s_service_type_browser_new(server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "mesh.local", 0, browse_type_callback, server)), "Failed to create service browser: %s", avahi_strerror(avahi_server_errno(server))); + struct timeval tv = {0}; + avahi_elapse_time(&tv, 1000*UPDATE_INTERVAL, 0); + avahi_simple_poll_get(simple_poll)->timeout_new(avahi_simple_poll_get(simple_poll), &tv, query_services, &query_server); // create expiration event for service + /* Run the main loop */ avahi_simple_poll_loop(simple_poll); @@ -230,6 +279,9 @@ int main(int argc, char*argv[]) { if (server) avahi_server_free(server); + + if (query_server) + avahi_server_free(query_server); if (simple_poll) avahi_simple_poll_free(simple_poll); From af013cd96bea3964a6b24dfac428b0fc394db5d1 Mon Sep 17 00:00:00 2001 From: Dan Staples Date: Thu, 27 Mar 2014 11:47:35 -0400 Subject: [PATCH 2/4] tiny fix --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.c b/main.c index 1e95bd9..955bc76 100644 --- a/main.c +++ b/main.c @@ -181,7 +181,7 @@ static void query_services(AvahiTimeout *t, void *userdata) { struct timeval tv = {0}; avahi_elapse_time(&tv, 1000*UPDATE_INTERVAL, 0); - timeout_update(t, &tv); + avahi_simple_poll_get(simple_poll)->timeout_update(t, &tv); } int main(int argc, char*argv[]) { From 5b8c053ca470d8703841b5caa5b0cad224d8f3a8 Mon Sep 17 00:00:00 2001 From: Dan Staples Date: Wed, 2 Apr 2014 12:38:53 -0400 Subject: [PATCH 3/4] shut down and re-create main server, instead of using a new server instance --- main.c | 87 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 45 insertions(+), 42 deletions(-) diff --git a/main.c b/main.c index 955bc76..ca6f308 100644 --- a/main.c +++ b/main.c @@ -14,7 +14,7 @@ #include "commotion-service-manager.h" #include "debug.h" -#define UPDATE_INTERVAL 30 +#define UPDATE_INTERVAL 64 extern struct arguments arguments; static int pid_filehandle; @@ -22,6 +22,7 @@ static int pid_filehandle; extern AvahiSimplePoll *simple_poll; extern AvahiServer *server; AvahiServerConfig config; +AvahiSServiceTypeBrowser *stb = NULL; /** Parse commandline options */ static error_t parse_opt (int key, char *arg, struct argp_state *state) { @@ -142,52 +143,66 @@ static void daemon_start(char *pidfile) { } -static void query_server_callback(AvahiServer *s, AvahiServerState state, void* userdata) { - AvahiServer **query_server = (AvahiServer**)userdata; - assert(s && s == *query_server); +static void server_callback(AvahiServer *s, AvahiServerState state, void* userdata) { + assert(s); switch (state) { case AVAHI_SERVER_RUNNING: - DEBUG("Query_server created and running"); - avahi_server_free(s); - *query_server = NULL; + DEBUG("Server created and running"); + /* Create the service browser */ + stb = avahi_s_service_type_browser_new(s, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "mesh.local", 0, browse_type_callback, s); + if (!stb) + ERROR("Failed to create service type browser: %s", avahi_strerror(avahi_server_errno(s))); break; case AVAHI_SERVER_COLLISION: - ERROR("AVAHI_SERVER_COLLISION"); + WARN("AVAHI_SERVER_COLLISION"); case AVAHI_SERVER_REGISTERING: - ERROR("AVAHI_SERVER_REGISTERING"); + WARN("AVAHI_SERVER_REGISTERING"); case AVAHI_SERVER_INVALID: - ERROR("AVAHI_SERVER_INVALID"); + WARN("AVAHI_SERVER_INVALID"); case AVAHI_SERVER_FAILURE: - ERROR("Query_server failure: %s\n", avahi_strerror(avahi_server_errno(s))); - avahi_simple_poll_quit(simple_poll); + WARN("Server failure: %s", avahi_strerror(avahi_server_errno(s))); } } -static void query_services(AvahiTimeout *t, void *userdata) { - AvahiServer **query_server = (AvahiServer**)userdata; - assert(query_server); +static void start_server(AvahiTimeout *t, void *userdata) { + int error; + assert(t); - if (*query_server) { - ERROR("query_server already exists"); - return; + if (stb) { + DEBUG("Service type browser already exists"); + avahi_s_service_type_browser_free(stb); + stb = NULL; } - int error; - *query_server = avahi_server_new(avahi_simple_poll_get(simple_poll), &config, query_server_callback, query_server, &error); - if (!*query_server) + if (server) { + DEBUG("Server already exists"); + avahi_server_free(server); + server = NULL; + } + + /* Allocate a new server */ + server = avahi_server_new(avahi_simple_poll_get(simple_poll), &config, server_callback, NULL, &error); + + /* Check whether creating the server object succeeded */ + if (!server) { ERROR("Failed to create server: %s", avahi_strerror(error)); + avahi_simple_poll_quit(simple_poll); + return; + } + /* every UPDATE_INTERVAL seconds, shut down and re-create server. This + * has the benefit of causing CSM to send queries to other nodes, prompting + * them to re-multicast their services. This is done because mDNS seems to + * be very unreliable on mesh, and often nodes don't get service announcements + * or can't resolve them. */ struct timeval tv = {0}; avahi_elapse_time(&tv, 1000*UPDATE_INTERVAL, 0); avahi_simple_poll_get(simple_poll)->timeout_update(t, &tv); } int main(int argc, char*argv[]) { - AvahiServer *query_server = NULL; - AvahiSServiceTypeBrowser *stb = NULL; - int error; int ret = 1; argp_program_version = "1.0"; @@ -247,22 +262,10 @@ int main(int argc, char*argv[]) { config.n_wide_area_servers = 1; config.enable_wide_area = 1; - /* Allocate a new server */ - server = avahi_server_new(avahi_simple_poll_get(simple_poll), &config, NULL, NULL, &error); - - /* Free the configuration data */ - avahi_server_config_free(&config); - - /* Check wether creating the server object succeeded */ - CHECK(server,"Failed to create server: %s", avahi_strerror(error)); - - /* Create the service browser */ - CHECK((stb = avahi_s_service_type_browser_new(server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "mesh.local", 0, browse_type_callback, server)), - "Failed to create service browser: %s", avahi_strerror(avahi_server_errno(server))); - + // Start timer to create server struct timeval tv = {0}; - avahi_elapse_time(&tv, 1000*UPDATE_INTERVAL, 0); - avahi_simple_poll_get(simple_poll)->timeout_new(avahi_simple_poll_get(simple_poll), &tv, query_services, &query_server); // create expiration event for service + avahi_elapse_time(&tv, 0, 0); + avahi_simple_poll_get(simple_poll)->timeout_new(avahi_simple_poll_get(simple_poll), &tv, start_server, NULL); // create expiration event for service /* Run the main loop */ avahi_simple_poll_loop(simple_poll); @@ -271,6 +274,9 @@ int main(int argc, char*argv[]) { error: + /* Free the configuration data */ + avahi_server_config_free(&config); + co_shutdown(); /* Cleanup things */ @@ -280,9 +286,6 @@ int main(int argc, char*argv[]) { if (server) avahi_server_free(server); - if (query_server) - avahi_server_free(query_server); - if (simple_poll) avahi_simple_poll_free(simple_poll); From 066825d75cfcf50aafca17b35f69c3585d7937c3 Mon Sep 17 00:00:00 2001 From: Dan Staples Date: Wed, 2 Apr 2014 13:10:10 -0400 Subject: [PATCH 4/4] remove service from list if resolution fails --- commotion-service-manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commotion-service-manager.c b/commotion-service-manager.c index fd65e6f..d891cba 100644 --- a/commotion-service-manager.c +++ b/commotion-service-manager.c @@ -491,7 +491,7 @@ void resolve_callback( } avahi_s_service_resolver_free(i->resolver); i->resolver = NULL; - if (event == AVAHI_RESOLVER_FOUND && !i->resolved) { + if (!i->resolved) { remove_service(NULL, i); } }