From 04b142dbe3777bfdafa4c482de35e4de0fbae89d Mon Sep 17 00:00:00 2001 From: James Laird Date: Mon, 1 Apr 2013 20:08:05 +1100 Subject: [PATCH] rewrite: add mDNS registration --- Makefile | 2 +- common.h | 1 + mdns.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++ mdns.h | 7 +++++++ rtsp.c | 3 +++ shairport.c | 7 +++++++ 6 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 mdns.c create mode 100644 mdns.h diff --git a/Makefile b/Makefile index 58996c3ca..7f3e39b2f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -SRCS := shairport.c rtsp.c common.c rtp.c player.c alac.c $(wildcard audio_*.c) +SRCS := shairport.c rtsp.c mdns.c common.c rtp.c player.c alac.c $(wildcard audio_*.c) LIBS := -lcrypto -lm -lao -lpthread diff --git a/common.h b/common.h index 94780e5ac..cf64b3e49 100644 --- a/common.h +++ b/common.h @@ -7,6 +7,7 @@ typedef struct { char *password; + char *apname; char hw_addr[6]; int port; audio_ops *output; diff --git a/mdns.c b/mdns.c new file mode 100644 index 000000000..050cd812e --- /dev/null +++ b/mdns.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include "common.h" + +static int mdns_pid = 0; + +void mdns_unregister(void) { + if (mdns_pid) + kill(mdns_pid, SIGTERM); + mdns_pid = 0; +} + +void mdns_register(void) { + if (mdns_pid) + die("attempted to register with mDNS twice"); + + // XXX todo: native avahi support, if available at compile time + + if ((mdns_pid = fork())) + return; + + char *mdns_apname = malloc(strlen(config.apname) + 14); + char *p = mdns_apname; + int i; + for (i=0; i<6; i++) { + sprintf(p, "%02X", config.hw_addr[i]); + p += 2; + } + *p++ = '@'; + strcpy(p, config.apname); + + char mdns_port[6]; + sprintf(mdns_port, "%d", config.port); + +#define RECORD "tp=UDP", "sm=false", "ek=1", "et=0,1", "cn=0,1", "ch=2", \ + "ss=16", "sr=44100", "vn=3", "txtvers=1", \ + config.password ? "pw=true" : "pw=false" + + char *argv[] = { + NULL, mdns_apname, "_raop._tcp", mdns_port, RECORD + }; + + argv[0] = "avahi-publish-service"; + execvp(argv[0], argv); + + argv[0] = "mDNSPublish"; + execvp(argv[0], argv); + + char *mac_argv[] = {"dns-sd", "-R", mdns_apname, "_raop._tcp", ".", + mdns_port, RECORD}; + execvp(mac_argv[0], mac_argv); + + die("Could not establish mDNS advertisement!\n"); +} diff --git a/mdns.h b/mdns.h new file mode 100644 index 000000000..fe83bfe11 --- /dev/null +++ b/mdns.h @@ -0,0 +1,7 @@ +#ifndef _MDNS_H +#define _MDNS_H + +void mdns_unregister(void); +void mdns_register(void); + +#endif // _MDNS_H diff --git a/rtsp.c b/rtsp.c index f4654c6ce..47908f905 100644 --- a/rtsp.c +++ b/rtsp.c @@ -17,6 +17,7 @@ #include "common.h" #include "player.h" #include "rtp.h" +#include "mdns.h" // only one thread is allowed to use the player at once. // it monitors the request variable (at least when interrupted) @@ -699,6 +700,8 @@ void rtsp_listen_loop(void) { if (sockfd[1]) FD_SET(sockfd[1], &fds); + mdns_register(); + printf("Listening for connections.\n"); int acceptfd; diff --git a/shairport.c b/shairport.c index 69a953ba5..6cbe6987a 100644 --- a/shairport.c +++ b/shairport.c @@ -2,10 +2,12 @@ #include #include "common.h" #include "rtsp.h" +#include "mdns.h" static void shutdown(void) { printf("Shutting down...\n"); + mdns_unregister(); rtsp_shutdown_stream(); config.output->deinit(); exit(0); @@ -23,17 +25,21 @@ int main(int argc, char **argv) { // config.password = "hello"; memcpy(config.hw_addr, "\0\x11\x22\x33\x44\x55", 6); config.buffer_start_fill = 220; + config.port = 9000; + config.apname = "hellothere"; config.output = &audio_dummy; //config.output = &audio_ao; // mask off all signals before creating threads. // this way we control which thread gets which signals. + // for now, we don't care which thread gets the following. sigset_t set; sigfillset(&set); sigdelset(&set, SIGINT); sigdelset(&set, SIGTERM); sigdelset(&set, SIGSTOP); + sigdelset(&set, SIGCHLD); pthread_sigmask(SIG_BLOCK, &set, NULL); // setting this to SIG_IGN would prevent signalling any threads. @@ -46,6 +52,7 @@ int main(int argc, char **argv) { sa.sa_sigaction = &sig_shutdown; sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); + sigaction(SIGCHLD, &sa, NULL); config.output->init(0, 0);