mdnssvc icon indicating copy to clipboard operation
mdnssvc copied to clipboard

airplay service cannot be discovered

Open CoolBoy119 opened this issue 1 year ago • 12 comments

I use this library to register the airplay service, but it cannot be discovered using a Mac computer. Are there any restrictions?

CoolBoy119 avatar Jan 31 '24 14:01 CoolBoy119

I found that a crash occurs when adding a txt record

CoolBoy119 avatar Jan 31 '24 15:01 CoolBoy119

Can you share your code?

philippe44 avatar Jan 31 '24 16:01 philippe44

I just do some update in climdnssvc.c,this is my code: `int main(int argc, char argv[]) { // const char* txt = NULL; struct in_addr host; char hostname[256],* arg, * identity = NULL, * type = NULL, * addr = NULL; int port = 0; bool verbose = false;

// if (argc <= 2) {
// 	print_usage();
// 	exit(0);
// }

#ifdef _WIN32 winsock_init(); #endif

signal(SIGINT, sighandler);
signal(SIGTERM, sighandler);

#if defined(SIGPIPE) signal(SIGPIPE, SIG_IGN); #endif #if defined(SIGQUIT) signal(SIGQUIT, sighandler); #endif #if defined(SIGHUP) signal(SIGHUP, sighandler); #endif

// while ((arg = *++argv) != NULL) {
// 	if (!strcasecmp(arg, "-o") || !strcasecmp(arg, "host")) {
// 		addr = *++argv;
// 		argc -= 2;
// 	} else if (!strcasecmp(arg, "-p")) {
// 		port = atoi(*++argv);
// 	} else if (!strcasecmp(arg, "-v")) {
// 		verbose = true;
// 	} else if (!strcasecmp(arg, "-t")) {
// 		(void)! asprintf(&type, "%s.local", *++argv);
// 	} else if (!strcasecmp(arg, "-i")) {
// 		identity = *++argv;
// 	} else {
// 		// nothing let's try to be smart and handle legacy crap		
// 		if (!identity) identity = *argv;
// 		else if (!type) (void) !asprintf(&type, "%s.local", *argv);
// 		else if (!port) port = atoi(*argv);
// 		else {
// 			txt = (const char**) malloc((argc + 1) * sizeof(char**));
// 			memcpy(txt, argv, argc * sizeof(char**));
// 			txt[argc] = NULL;
// 			break;
// 		}
// 		argc--;
// 	}
// }

char* identity_raop="cc3d825f7ed1@mdnslib";
char* type_raop="_raop._tcp.local";
short port_raop=6012;
const char* txt_raop[]= {NULL, "tp=UDP", "sm=false", "sv=false", "ek=1",
				"et=0,1", "md=0,1,2", "cn=0,1", "ch=2",
				"ss=16", "sr=44100", "vn=3", "txtvers=1",
				NULL 
				 };			

gethostname(hostname, sizeof(hostname));
strcat(hostname, ".local");
host = get_interface(addr);

svr = mdnsd_start(host, verbose);
if (svr) {
	printf("host: %s\nidentity: %s\ntype: %s\nip: %s\nport: %u\n", hostname, identity, type, inet_ntoa(host), port);

	mdnsd_set_hostname(svr, hostname, host);
	svc_raop = mdnsd_register_svc(svr, identity_raop, type_raop, port_raop, NULL, txt_raop);
	// mdns_service_destroy(svc);

#ifdef _WIN32 Sleep(INFINITE); #else pause(); #endif mdns_service_remove(svr, svc_raop); mdnsd_stop(svr); } else { printf("Can't start server"); print_usage(); }

free(type);
if (txt_raop) free(txt_raop);

#ifdef _WIN32 winsock_close(); #endif

return 0;

} `

CoolBoy119 avatar Feb 01 '24 02:02 CoolBoy119

I found it could not create a TXT record in mdnsd_register_svc,it may not enter this branch. image

CoolBoy119 avatar Feb 01 '24 02:02 CoolBoy119

when I use it with removing the first NULL element in txt, it can enter the branch,but a segfault occurred during runtime. const char* txt_raop[]= { "tp=UDP", "sm=false", "sv=false", "ek=1", "et=0,1", "md=0,1,2", "cn=0,1", "ch=2", "ss=16", "sr=44100", "vn=3", "txtvers=1" };

CoolBoy119 avatar Feb 01 '24 02:02 CoolBoy119

I think you misunderstood the syntax of TXT. It's an array of pointers and a NULL indicates the last item. If you put NULL first, nothing will be taken into account. If you forget the NULL at the end, the parser will runaway everywhere and crash

philippe44 avatar Feb 01 '24 09:02 philippe44

But it also crashed if I only placed NULL at the end.

CoolBoy119 avatar Feb 01 '24 12:02 CoolBoy119

You either don't set a TXT at all (the txt parameter in the function call is NULL) or it includes at least one element and then finishes by NULL. You can't obviously send an array with just NULL inside, you send a NULL array instead.

philippe44 avatar Feb 01 '24 16:02 philippe44

yes,I just update with this,it also crash. const char* txt_raop[]= {"tp=UDP", "sm=false", "sv=false", "ek=1", "et=0,1", "md=0,1,2", "cn=0,1", "ch=2", "ss=16", "sr=44100", "vn=3", "txtvers=1", NULL }; if I don't set TXT record,the service may not discover.Can you give me some example?

CoolBoy119 avatar Feb 02 '24 01:02 CoolBoy119

You can look at my AirConnect project and see how I'm using it

philippe44 avatar Feb 02 '24 07:02 philippe44

I look the libraop project in AirConnect,it show txt code like this:https://github.com/philippe44/libraop/blob/master/src/raop_server.c I think it register service without txt record. image

CoolBoy119 avatar Feb 03 '24 03:02 CoolBoy119

No, I do use services w/ TXT, it would not work otherwise, AirPlay would not work. What you probably missed is that the leading NULL is replaced a few lines below by a dynamically generated string.

// set model
(void)!asprintf(&(txt[0]), "am=%s", model);

philippe44 avatar Feb 03 '24 04:02 philippe44