X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Flib%2Fraop_rtp.c;h=7ab98dc32ca48937ec696858b0a50cb26c7bde64;hb=e1a8dfe69a0419217bcce0354fa920dc34a0569d;hp=39ac7ab53d2d7c9f13b2ef0b10028e2b868bf275;hpb=23e7e3ae2b2adfa49635495c0950b76e17987c93;p=deb_shairplay.git diff --git a/src/lib/raop_rtp.c b/src/lib/raop_rtp.c index 39ac7ab..7ab98dc 100644 --- a/src/lib/raop_rtp.c +++ b/src/lib/raop_rtp.c @@ -22,6 +22,7 @@ #include "raop.h" #include "raop_buffer.h" #include "netutils.h" +#include "utils.h" #include "compat.h" #include "logger.h" @@ -31,8 +32,13 @@ struct raop_rtp_s { logger_t *logger; raop_callbacks_t callbacks; + /* Buffer to handle all resends */ raop_buffer_t *buffer; + /* Remote address as sockaddr */ + struct sockaddr_storage remote_saddr; + socklen_t remote_saddr_len; + /* These variables only edited mutex locked */ int running; int joined; @@ -53,18 +59,63 @@ struct raop_rtp_s { unsigned short timing_lport; unsigned short data_lport; + /* Initialized after the first control packet */ struct sockaddr_storage control_saddr; socklen_t control_saddr_len; unsigned short control_seqnum; }; +static int +raop_rtp_parse_remote(raop_rtp_t *raop_rtp, const char *remote) +{ + char *original; + char *current; + char *tmpstr; + int family; + int ret; + + assert(raop_rtp); + + current = original = strdup(remote); + if (!original) { + return -1; + } + tmpstr = utils_strsep(¤t, " "); + if (strcmp(tmpstr, "IN")) { + free(original); + return -1; + } + tmpstr = utils_strsep(¤t, " "); + if (!strcmp(tmpstr, "IP4") && current) { + family = AF_INET; + } else if (!strcmp(tmpstr, "IP6") && current) { + family = AF_INET6; + } else { + free(original); + return -1; + } + ret = netutils_parse_address(family, current, + &raop_rtp->remote_saddr, + sizeof(raop_rtp->remote_saddr)); + if (ret < 0) { + free(original); + return -1; + } + raop_rtp->remote_saddr_len = ret; + free(original); + return 0; +} + raop_rtp_t * -raop_rtp_init(logger_t *logger, raop_callbacks_t *callbacks, const char *fmtp, - const unsigned char *aeskey, const unsigned char *aesiv) +raop_rtp_init(logger_t *logger, raop_callbacks_t *callbacks, const char *remote, + const char *fmtp, const unsigned char *aeskey, const unsigned char *aesiv) { raop_rtp_t *raop_rtp; assert(logger); + assert(callbacks); + assert(remote); + assert(fmtp); raop_rtp = calloc(1, sizeof(raop_rtp_t)); if (!raop_rtp) { @@ -77,6 +128,10 @@ raop_rtp_init(logger_t *logger, raop_callbacks_t *callbacks, const char *fmtp, free(raop_rtp); return NULL; } + if (raop_rtp_parse_remote(raop_rtp, remote) < 0) { + free(raop_rtp); + return NULL; + } raop_rtp->running = 0; raop_rtp->joined = 1; @@ -150,6 +205,7 @@ raop_rtp_resend_callback(void *opaque, unsigned short seqnum, unsigned short cou unsigned short ourseqnum; struct sockaddr *addr; socklen_t addrlen; + int ret; addr = (struct sockaddr *)&raop_rtp->control_saddr; addrlen = raop_rtp->control_saddr_len; @@ -167,7 +223,11 @@ raop_rtp_resend_callback(void *opaque, unsigned short seqnum, unsigned short cou packet[6] = (count >> 8); packet[7] = count; - sendto(raop_rtp->csock, (const char *)packet, sizeof(packet), 0, addr, addrlen); + ret = sendto(raop_rtp->csock, (const char *)packet, sizeof(packet), 0, addr, addrlen); + if (ret == -1) { + logger_log(raop_rtp->logger, LOGGER_WARNING, "Resend failed: %d\n", SOCKET_GET_ERROR()); + } + return 0; } @@ -179,6 +239,7 @@ raop_rtp_thread_udp(void *arg) unsigned int packetlen; struct sockaddr_storage saddr; socklen_t saddrlen; + float volume = 0.0; const ALACSpecificConfig *config; void *cb_data = NULL; @@ -186,14 +247,13 @@ raop_rtp_thread_udp(void *arg) assert(raop_rtp); config = raop_buffer_get_config(raop_rtp->buffer); - raop_rtp->callbacks.audio_init(raop_rtp->callbacks.cls, &cb_data, + cb_data = raop_rtp->callbacks.audio_init(raop_rtp->callbacks.cls, config->bitDepth, config->numChannels, config->sampleRate); while(1) { int volume_changed; - float volume = 0.0; int flush; fd_set rfds; @@ -253,7 +313,7 @@ raop_rtp_thread_udp(void *arg) packetlen = recvfrom(raop_rtp->csock, (char *)packet, sizeof(packet), 0, (struct sockaddr *)&saddr, &saddrlen); - /* FIXME: Get destination address here */ + /* Get the destination address here, because we need the sin6_scope_id */ memcpy(&raop_rtp->control_saddr, &saddr, saddrlen); raop_rtp->control_saddr_len = saddrlen; @@ -295,7 +355,7 @@ raop_rtp_thread_udp(void *arg) } } } - logger_log(raop_rtp->logger, LOGGER_INFO, "Exiting thread\n"); + logger_log(raop_rtp->logger, LOGGER_INFO, "Exiting UDP RAOP thread\n"); raop_rtp->callbacks.audio_destroy(raop_rtp->callbacks.cls, cb_data); return 0; @@ -308,6 +368,7 @@ raop_rtp_thread_tcp(void *arg) int stream_fd = -1; unsigned char packet[RAOP_PACKET_LEN]; unsigned int packetlen = 0; + float volume = 0.0; const ALACSpecificConfig *config; void *cb_data = NULL; @@ -315,14 +376,13 @@ raop_rtp_thread_tcp(void *arg) assert(raop_rtp); config = raop_buffer_get_config(raop_rtp->buffer); - raop_rtp->callbacks.audio_init(raop_rtp->callbacks.cls, &cb_data, + cb_data = raop_rtp->callbacks.audio_init(raop_rtp->callbacks.cls, config->bitDepth, config->numChannels, config->sampleRate); while (1) { int volume_changed; - float volume = 0.0; fd_set rfds; struct timeval tv; @@ -379,7 +439,6 @@ raop_rtp_thread_tcp(void *arg) } if (stream_fd != -1 && FD_ISSET(stream_fd, &rfds)) { unsigned int rtplen=0; - char type; const void *audiobuf; int audiobuflen; @@ -415,7 +474,6 @@ raop_rtp_thread_tcp(void *arg) } /* Packet is valid, process it */ - type = packet[4+1] & ~0x80; ret = raop_buffer_queue(raop_rtp->buffer, packet+4, rtplen, 0); assert(ret >= 0); @@ -435,7 +493,7 @@ raop_rtp_thread_tcp(void *arg) closesocket(stream_fd); } - logger_log(raop_rtp->logger, LOGGER_INFO, "Exiting thread\n"); + logger_log(raop_rtp->logger, LOGGER_INFO, "Exiting TCP RAOP thread\n"); raop_rtp->callbacks.audio_destroy(raop_rtp->callbacks.cls, cb_data); return 0; @@ -445,6 +503,8 @@ void raop_rtp_start(raop_rtp_t *raop_rtp, int use_udp, unsigned short control_rport, unsigned short timing_rport, unsigned short *control_lport, unsigned short *timing_lport, unsigned short *data_lport) { + int use_ipv6 = 0; + assert(raop_rtp); MUTEX_LOCK(raop_rtp->run_mutex); @@ -456,7 +516,10 @@ raop_rtp_start(raop_rtp_t *raop_rtp, int use_udp, unsigned short control_rport, /* Initialize ports and sockets */ raop_rtp->control_rport = control_rport; raop_rtp->timing_rport = timing_rport; - if (raop_rtp_init_sockets(raop_rtp, 1, use_udp) < 0) { + if (raop_rtp->remote_saddr.ss_family == AF_INET6) { + use_ipv6 = 1; + } + if (raop_rtp_init_sockets(raop_rtp, use_ipv6, use_udp) < 0) { logger_log(raop_rtp->logger, LOGGER_INFO, "Initializing sockets failed\n"); MUTEX_UNLOCK(raop_rtp->run_mutex); return;