From 958fceb60a63c965af8cb971eff2148d3508fd7d Mon Sep 17 00:00:00 2001 From: Paul Lietar Date: Thu, 29 Aug 2013 21:56:17 +0200 Subject: [PATCH] Add a command-line option to force the mDNS backend Add this option to the system-v init script. --- common.h | 4 ++- mdns.c | 48 ++++++++++++++++++++++++-------- mdns.h | 2 ++ mdns_avahi.c | 1 + mdns_external.c | 23 +++++++++++---- scripts/debian/default/shairport | 5 ++++ scripts/debian/init.d/shairport | 1 + shairport.c | 19 +++++++++---- 8 files changed, 80 insertions(+), 23 deletions(-) diff --git a/common.h b/common.h index d7f2a21d..451b815a 100644 --- a/common.h +++ b/common.h @@ -5,6 +5,7 @@ #include #include #include "audio.h" +#include "mdns.h" // struct sockaddr_in6 is bigger than struct sockaddr. derp #ifdef AF_INET6 @@ -23,9 +24,10 @@ typedef struct { int port; char *output_name; audio_output *output; + char *mdns_name; + mdns_backend *mdns; int buffer_start_fill; int daemonise; - int mdns_internal; char *cmd_start, *cmd_stop; char *pidfile; char *logfile; diff --git a/mdns.c b/mdns.c index 9720a74b..978568fd 100644 --- a/mdns.c +++ b/mdns.c @@ -47,8 +47,6 @@ static mdns_backend *mdns_backends[] = { NULL }; -static mdns_backend *backend = NULL; - void mdns_register(void) { char *mdns_apname = malloc(strlen(config.apname) + 14); char *p = mdns_apname; @@ -60,26 +58,54 @@ void mdns_register(void) { *p++ = '@'; strcpy(p, config.apname); - backend = NULL; - mdns_backend **s = NULL; - for (s = mdns_backends; *s; s++) + mdns_backend **b = NULL; + + if (config.mdns_name != NULL) { - int error = (*s)->mdns_register(mdns_apname, config.port); - if (error == 0) + for (b = mdns_backends; *b; b++) { - backend = *s; + if (strcmp((*b)->name, config.mdns_name) != 0) // Not the one we are looking for + continue; + int error = (*b)->mdns_register(mdns_apname, config.port); + if (error >= 0) + { + config.mdns = *b; + } break; } + + if (*b == NULL) + warn("%s mDNS backend not found"); + } + else + { + for (b = mdns_backends; *b; b++) + { + int error = (*b)->mdns_register(mdns_apname, config.port); + if (error >= 0) + { + config.mdns = *b; + break; + } + } } - if (backend == NULL) + if (config.mdns == NULL) die("Could not establish mDNS advertisement!"); } void mdns_unregister(void) { - if (backend) { - backend->mdns_unregister(); + if (config.mdns) { + config.mdns->mdns_unregister(); } } +void mdns_ls_backends(void) { + mdns_backend **b = NULL; + printf("Available mDNS backends: \n"); + for (b = mdns_backends; *b; b++) + { + printf(" %s\n", (*b)->name); + } +} diff --git a/mdns.h b/mdns.h index 4b5f839d..b3f00391 100644 --- a/mdns.h +++ b/mdns.h @@ -5,8 +5,10 @@ extern int mdns_pid; void mdns_unregister(void); void mdns_register(void); +void mdns_ls_backends(void); typedef struct { + char *name; int (*mdns_register)(char *apname, int port); void (*mdns_unregister)(void); } mdns_backend; diff --git a/mdns_avahi.c b/mdns_avahi.c index d927d51c..82b2effd 100644 --- a/mdns_avahi.c +++ b/mdns_avahi.c @@ -141,6 +141,7 @@ static void avahi_unregister(void) { mdns_backend mdns_avahi = { + .name = "avahi", .mdns_register = avahi_register, .mdns_unregister = avahi_unregister }; diff --git a/mdns_external.c b/mdns_external.c index e86d2fb7..ac329e7c 100644 --- a/mdns_external.c +++ b/mdns_external.c @@ -93,16 +93,22 @@ static int mdns_external_avahi_register(char *apname, int port) { }; argv[0] = "avahi-publish-service"; - mdns_pid = fork_execvp(argv[0], argv); - if (mdns_pid > 0) + int pid = fork_execvp(argv[0], argv); + if (pid >= 0) + { + mdns_pid = pid; return 0; + } else warn("Calling %s failed !", argv[0]); argv[0] = "mDNSPublish"; - mdns_pid = fork_execvp(argv[0], argv); - if (mdns_pid > 0) + pid = fork_execvp(argv[0], argv); + if (pid >= 0) + { + mdns_pid = pid; return 0; + } else warn("Calling %s failed !", argv[0]); @@ -117,9 +123,12 @@ static int mdns_external_dns_sd_register(char *apname, int port) { char *argv[] = {"dns-sd", "-R", apname, "_raop._tcp", ".", mdns_port, MDNS_RECORD, NULL}; - mdns_pid = fork_execvp(argv[0], argv); - if (mdns_pid > 0) + int pid = fork_execvp(argv[0], argv); + if (pid >= 0) + { + mdns_pid = pid; return 0; + } else warn("Calling %s failed !", argv[0]); @@ -133,11 +142,13 @@ static void kill_mdns_child(void) { } mdns_backend mdns_external_avahi = { + .name = "external-avahi", .mdns_register = mdns_external_avahi_register, .mdns_unregister = kill_mdns_child }; mdns_backend mdns_external_dns_sd = { + .name = "external-dns-sd", .mdns_register = mdns_external_dns_sd_register, .mdns_unregister = kill_mdns_child }; diff --git a/scripts/debian/default/shairport b/scripts/debian/default/shairport index 5ce903c3..a9bc7293 100644 --- a/scripts/debian/default/shairport +++ b/scripts/debian/default/shairport @@ -32,6 +32,11 @@ #OUTPUT=ao #OUTPUT_OPTS= +# Force the mDNS backend +# By default, shairport will try all backends until one works. +# Check 'shairport -h' for details +# MDNS=avahi + # Change how many frames re required to start playing #BUFFER_FILL=220 diff --git a/scripts/debian/init.d/shairport b/scripts/debian/init.d/shairport index cd7bdf90..392f6832 100755 --- a/scripts/debian/init.d/shairport +++ b/scripts/debian/init.d/shairport @@ -35,6 +35,7 @@ DAEMON_ARGS="--daemon --pidfile $PIDFILE --log $LOGFILE" [ -z "$ON_START" ] || DAEMON_ARGS="$DAEMON_ARGS --on-start \"$ON_START\"" [ -z "$ON_STOP" ] || DAEMON_ARGS="$DAEMON_ARGS --on-stop \"$ON_STOP\"" [ -z "$OUTPUT" ] || DAEMON_ARGS="$DAEMON_ARGS --output $OUTPUT" +[ -z "$MDNS" ] || DAEMON_ARGS="$DAEMON_ARGS --mdns $MDNS" [ -z "$OUTPUT_OPTS" ] || DAEMON_ARGS="$DAEMON_ARGS -- $OUTPUT_OPTS" # Exit if the package is not installed diff --git a/shairport.c b/shairport.c index 8140acd4..86ea8482 100644 --- a/shairport.c +++ b/shairport.c @@ -93,15 +93,20 @@ void usage(char *progname) { printf(" written to stdout, unless a pidfile is used.\n"); printf(" -P, --pidfile=FILE write daemon's pid to FILE on startup.\n"); printf(" Has no effect if -d is not specified\n"); - printf(" -l, --log FILE redirect shairport's standard output to FILE\n"); - printf(" If --errror is not specified, it also redirects\n"); + printf(" -l, --log=FILE redirect shairport's standard output to FILE\n"); + printf(" If --error is not specified, it also redirects\n"); printf(" error output to FILE\n"); - printf(" -e, --error FILE redirect shairport's standard error output to FILE\n"); + printf(" -e, --error=FILE redirect shairport's standard error output to FILE\n"); printf(" -B, --on-start=COMMAND run a shell command when playback begins\n"); printf(" -E, --on-stop=COMMAND run a shell command when playback ends\n"); printf(" -o, --output=BACKEND select audio output method\n"); + printf(" -m, --mdns=BACKEND force the use of BACKEND to advertize the service\n"); + printf(" if no mdns provider is specified,\n"); + printf(" shairport tries them all until one works.\n"); + printf("\n"); + mdns_ls_backends(); printf("\n"); audio_ls_outputs(); } @@ -111,7 +116,7 @@ int parse_options(int argc, char **argv) { setenv("POSIXLY_CORRECT", "", 1); static struct option long_options[] = { - {"help", no_argument, NULL, 'h'}, + {"help", no_argument, NULL, 'h'}, {"daemon", no_argument, NULL, 'd'}, {"pidfile", required_argument, NULL, 'P'}, {"log", required_argument, NULL, 'l'}, @@ -121,12 +126,13 @@ int parse_options(int argc, char **argv) { {"output", required_argument, NULL, 'o'}, {"on-start",required_argument, NULL, 'B'}, {"on-stop", required_argument, NULL, 'E'}, + {"mdns", required_argument, NULL, 'm'}, {NULL, 0, NULL, 0} }; int opt; while ((opt = getopt_long(argc, argv, - "+hdvP:l:e:p:a:o:b:B:E:", + "+hdvP:l:e:p:a:o:b:B:E:m:", long_options, NULL)) > 0) { switch (opt) { default: @@ -166,6 +172,9 @@ int parse_options(int argc, char **argv) { case 'e': config.errfile = optarg; break; + case 'm': + config.mdns_name = optarg; + break; } } return optind;