From: Martin Blanchard <tinram@xxxxxx> --- src/modules/raop/base64.c | 28 ++++-- src/modules/raop/base64.h | 6 +- src/modules/raop/module-raop-discover.c | 169 ++++++++++++++++---------------- src/modules/raop/module-raop-sink.c | 56 +++++------ src/modules/raop/raop_client.c | 91 ++++++++--------- src/modules/raop/raop_client.h | 16 +-- src/modules/rtp/rtsp_client.c | 64 +++++++----- src/modules/rtp/rtsp_client.h | 32 +++--- 8 files changed, 246 insertions(+), 216 deletions(-) diff --git a/src/modules/raop/base64.c b/src/modules/raop/base64.c index cdf52a6..d541745 100644 --- a/src/modules/raop/base64.c +++ b/src/modules/raop/base64.c @@ -17,10 +17,10 @@ along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. ***/ -/* +/*** This file was originally inspired by a file developed by - Kungliga Tekniska H�gskolan -*/ + Kungliga Tekniska Høgskolan. +***/ #ifdef HAVE_CONFIG_H #include <config.h> @@ -37,11 +37,17 @@ static const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static int pos(char c) { - if (c >= 'A' && c <= 'Z') return c - 'A' + 0; - if (c >= 'a' && c <= 'z') return c - 'a' + 26; - if (c >= '0' && c <= '9') return c - '0' + 52; - if (c == '+') return 62; - if (c == '/') return 63; + if (c >= 'A' && c <= 'Z') + return c - 'A' + 0; + if (c >= 'a' && c <= 'z') + return c - 'a' + 26; + if (c >= '0' && c <= '9') + return c - '0' + 52; + if (c == '+') + return 62; + if (c == '/') + return 63; + return -1; } @@ -73,8 +79,10 @@ int pa_base64_encode(const void *data, int size, char **str) { p[2] = '='; p += 4; } + *p = 0; *str = s; + return strlen(s); } @@ -84,6 +92,7 @@ static unsigned int token_decode(const char *token) { int i; unsigned int val = 0; int marker = 0; + if (strlen(token) < 4) return DECODE_ERROR; for (i = 0; i < 4; i++) { @@ -99,8 +108,10 @@ static unsigned int token_decode(const char *token) { val += lpos; } } + if (marker > 2) return DECODE_ERROR; + return (marker << 24) | val; } @@ -120,5 +131,6 @@ int pa_base64_decode(const char *str, void *data) { if (marker < 1) *q++ = val & 0xff; } + return q - (unsigned char *) data; } diff --git a/src/modules/raop/base64.h b/src/modules/raop/base64.h index 352ab96..ce6b9c4 100644 --- a/src/modules/raop/base64.h +++ b/src/modules/raop/base64.h @@ -21,10 +21,10 @@ along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. ***/ -/* +/*** This file was originally inspired by a file developed by - Kungliga Tekniska Høgskolan -*/ + Kungliga Tekniska Høgskolan. +***/ int pa_base64_encode(const void *data, int size, char **str); int pa_base64_decode(const char *str, void *data); diff --git a/src/modules/raop/module-raop-discover.c b/src/modules/raop/module-raop-discover.c index f083044..1ced777 100644 --- a/src/modules/raop/module-raop-discover.c +++ b/src/modules/raop/module-raop-discover.c @@ -52,6 +52,17 @@ PA_MODULE_LOAD_ONCE(true); #define SERVICE_TYPE_SINK "_raop._tcp" +struct userdata { + pa_core *core; + pa_module *module; + + AvahiPoll *avahi_poll; + AvahiClient *client; + AvahiServiceBrowser *sink_browser; + + pa_hashmap *tunnels; +}; + static const char* const valid_modargs[] = { NULL }; @@ -63,16 +74,6 @@ struct tunnel { uint32_t module_index; }; -struct userdata { - pa_core *core; - pa_module *module; - AvahiPoll *avahi_poll; - AvahiClient *client; - AvahiServiceBrowser *sink_browser; - - pa_hashmap *tunnels; -}; - static unsigned tunnel_hash(const void *p) { const struct tunnel *t = p; @@ -102,11 +103,11 @@ static int tunnel_compare(const void *a, const void *b) { return 0; } -static struct tunnel *tunnel_new( +static struct tunnel* tunnel_new( AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain) { - struct tunnel *t; + t = pa_xnew(struct tunnel, 1); t->interface = interface; t->protocol = protocol; @@ -114,6 +115,7 @@ static struct tunnel *tunnel_new( t->type = pa_xstrdup(type); t->domain = pa_xstrdup(domain); t->module_index = PA_IDXSET_INVALID; + return t; } @@ -134,88 +136,87 @@ static void resolver_cb( AvahiStringList *txt, AvahiLookupResultFlags flags, void *userdata) { - struct userdata *u = userdata; struct tunnel *tnl; + char *device = NULL, *nicename, *dname, *vname, *args; + char at[AVAHI_ADDRESS_STR_MAX]; + AvahiStringList *l; + pa_module *m; pa_assert(u); tnl = tunnel_new(interface, protocol, name, type, domain); - if (event != AVAHI_RESOLVER_FOUND) + if (event != AVAHI_RESOLVER_FOUND) { pa_log("Resolving of '%s' failed: %s", name, avahi_strerror(avahi_client_errno(u->client))); - else { - char *device = NULL, *nicename, *dname, *vname, *args; - char at[AVAHI_ADDRESS_STR_MAX]; - AvahiStringList *l; - pa_module *m; - - if ((nicename = strstr(name, "@"))) { - ++nicename; - if (strlen(nicename) > 0) { - pa_log_debug("Found RAOP: %s", nicename); - nicename = pa_escape(nicename, "\"'"); - } else - nicename = NULL; - } + goto finish; + } - for (l = txt; l; l = l->next) { - char *key, *value; - pa_assert_se(avahi_string_list_get_pair(l, &key, &value, NULL) == 0); + if ((nicename = strstr(name, "@"))) { + ++nicename; + if (strlen(nicename) > 0) { + pa_log_debug("Found RAOP: %s", nicename); + nicename = pa_escape(nicename, "\"'"); + } else + nicename = NULL; + } - pa_log_debug("Found key: '%s' with value: '%s'", key, value); - if (pa_streq(key, "device")) { - pa_xfree(device); - device = value; - value = NULL; - } - avahi_free(key); - avahi_free(value); + for (l = txt; l; l = l->next) { + char *key, *value; + pa_assert_se(avahi_string_list_get_pair(l, &key, &value, NULL) == 0); + + pa_log_debug("Found key: '%s' with value: '%s'", key, value); + if (pa_streq(key, "device")) { + device = value; + value = NULL; } - if (device) - dname = pa_sprintf_malloc("raop.%s.%s", host_name, device); - else - dname = pa_sprintf_malloc("raop.%s", host_name); + avahi_free(key); + avahi_free(value); + } - if (!(vname = pa_namereg_make_valid_name(dname))) { - pa_log("Cannot construct valid device name from '%s'.", dname); - avahi_free(device); - pa_xfree(dname); - goto finish; - } + if (device) + dname = pa_sprintf_malloc("raop.%s.%s", host_name, device); + else + dname = pa_sprintf_malloc("raop.%s", host_name); + + if (!(vname = pa_namereg_make_valid_name(dname))) { + pa_log("Cannot construct valid device name from '%s'.", dname); + avahi_free(device); pa_xfree(dname); + goto finish; + } - if (nicename) { - args = pa_sprintf_malloc("server=[%s]:%u " - "sink_name=%s " - "sink_properties='device.description=\"%s\"'", - avahi_address_snprint(at, sizeof(at), a), port, - vname, - nicename); - pa_xfree(nicename); - } else { - args = pa_sprintf_malloc("server=[%s]:%u " - "sink_name=%s", - avahi_address_snprint(at, sizeof(at), a), port, - vname); - } + avahi_free(device); + pa_xfree(dname); + + if (nicename) { + args = pa_sprintf_malloc("server=[%s]:%u " + "sink_name=%s " + "sink_properties='device.description=\"%s\"'", + avahi_address_snprint(at, sizeof(at), a), port, + vname, + nicename); + pa_xfree(nicename); + } else { + args = pa_sprintf_malloc("server=[%s]:%u " + "sink_name=%s", + avahi_address_snprint(at, sizeof(at), a), port, + vname); + } - pa_log_debug("Loading module-raop-sink with arguments '%s'", args); + pa_log_debug("Loading module-raop-sink with arguments '%s'", args); - if ((m = pa_module_load(u->core, "module-raop-sink", args))) { - tnl->module_index = m->index; - pa_hashmap_put(u->tunnels, tnl, tnl); - tnl = NULL; - } - - pa_xfree(vname); - pa_xfree(args); - avahi_free(device); + if ((m = pa_module_load(u->core, "module-raop-sink", args))) { + tnl->module_index = m->index; + pa_hashmap_put(u->tunnels, tnl, tnl); + tnl = NULL; } -finish: + pa_xfree(vname); + pa_xfree(args); +finish: avahi_service_resolver_free(r); if (tnl) @@ -229,7 +230,6 @@ static void browser_cb( const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata) { - struct userdata *u = userdata; struct tunnel *t; @@ -248,7 +248,7 @@ static void browser_cb( /* We ignore the returned resolver object here, since the we don't * need to attach any special data to it, and we can still destroy - * it from the callback */ + * it from the callback. */ } else if (event == AVAHI_BROWSER_REMOVE) { struct tunnel *t2; @@ -275,9 +275,7 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda case AVAHI_CLIENT_S_REGISTERING: case AVAHI_CLIENT_S_RUNNING: case AVAHI_CLIENT_S_COLLISION: - if (!u->sink_browser) { - if (!(u->sink_browser = avahi_service_browser_new( c, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, @@ -299,16 +297,16 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda pa_log_debug("Avahi daemon disconnected."); + /* Try to reconnect. */ if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) { pa_log("avahi_client_new() failed: %s", avahi_strerror(error)); pa_module_unload_request(u->module, true); } } - /* Fall through */ + /* Fall through. */ case AVAHI_CLIENT_CONNECTING: - if (u->sink_browser) { avahi_service_browser_free(u->sink_browser); u->sink_browser = NULL; @@ -316,12 +314,12 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda break; - default: ; + default: + break; } } -int pa__init(pa_module*m) { - +int pa__init(pa_module *m) { struct userdata *u; pa_modargs *ma = NULL; int error; @@ -358,8 +356,9 @@ fail: return -1; } -void pa__done(pa_module*m) { - struct userdata*u; +void pa__done(pa_module *m) { + struct userdata *u; + pa_assert(m); if (!(u = m->userdata)) diff --git a/src/modules/raop/module-raop-sink.c b/src/modules/raop/module-raop-sink.c index 6037038..6fc3d94 100644 --- a/src/modules/raop/module-raop-sink.c +++ b/src/modules/raop/module-raop-sink.c @@ -124,10 +124,10 @@ enum { SINK_MESSAGE_RIP_SOCKET }; -/* Forward declaration */ +/* Forward declarations: */ static void sink_set_volume_cb(pa_sink *); -static void on_connection(int fd, void*userdata) { +static void on_connection(int fd, void *userdata) { int so_sndbuf = 0; socklen_t sl = sizeof(int); struct userdata *u = userdata; @@ -143,7 +143,7 @@ static void on_connection(int fd, void*userdata) { pa_sink_set_max_request(u->sink, PA_MAX((size_t) so_sndbuf, u->block_size)); } - /* Set the initial volume */ + /* Set the initial volume. */ sink_set_volume_cb(u->sink); pa_log_debug("Connection authenticated, handing fd to IO thread..."); @@ -174,7 +174,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse pa_smoother_pause(u->smoother, pa_rtclock_now()); - /* Issue a FLUSH if we are connected */ + /* Issue a FLUSH if we are connected. */ if (u->fd >= 0) { pa_raop_flush(u->raop); } @@ -187,7 +187,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse pa_smoother_resume(u->smoother, pa_rtclock_now(), true); /* The connection can be closed when idle, so check to - see if we need to reestablish it */ + * see if we need to reestablish it. */ if (u->fd < 0) pa_raop_connect(u->raop); else @@ -226,7 +226,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse /*pollfd->events = */pollfd->revents = 0; if (u->sink->thread_info.state == PA_SINK_SUSPENDED) { - /* Our stream has been suspended so we just flush it.... */ + /* Our stream has been suspended so we just flush it... */ pa_raop_flush(u->raop); } return 0; @@ -268,19 +268,19 @@ static void sink_set_volume_cb(pa_sink *s) { pa_assert(u); - /* If we're muted we don't need to do anything */ + /* If we're muted we don't need to do anything. */ if (s->muted) return; /* Calculate the max volume of all channels. - We'll use this as our (single) volume on the APEX device and emulate - any variation in channel volumes in software */ + * We'll use this as our (single) volume on the APEX device and emulate + * any variation in channel volumes in software. */ v = pa_cvolume_max(&s->real_volume); - /* Create a pa_cvolume version of our single value */ + /* Create a pa_cvolume version of our single value. */ pa_cvolume_set(&hw, s->sample_spec.channels, v); - /* Perform any software manipulation of the volume needed */ + /* Perform any software manipulation of the volume needed. */ pa_sw_cvolume_divide(&s->soft_volume, &s->real_volume, &hw); pa_log_debug("Requested volume: %s", pa_cvolume_snprint_verbose(t, sizeof(t), &s->real_volume, &s->channel_map, false)); @@ -289,7 +289,7 @@ static void sink_set_volume_cb(pa_sink *s) { pa_cvolume_snprint_verbose(t, sizeof(t), &s->soft_volume, &s->channel_map, true)); /* Any necessary software volume manipulation is done so set - our hw volume (or v as a single value) on the device */ + * our hw volume (or v as a single value) on the device. */ pa_raop_client_set_volume(u->raop, v); } @@ -333,7 +333,7 @@ static void thread_func(void *userdata) { struct pollfd *pollfd; pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); - /* Render some data and write it to the fifo */ + /* Render some data and write it to the fifo. */ if (/*PA_SINK_IS_OPENED(u->sink->thread_info.state) && */pollfd->revents) { pa_usec_t usec; int64_t n; @@ -364,29 +364,29 @@ static void thread_func(void *userdata) { if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) { size_t rl; - /* We render real data */ + /* We render real data. */ if (u->raw_memchunk.length <= 0) { if (u->raw_memchunk.memblock) pa_memblock_unref(u->raw_memchunk.memblock); pa_memchunk_reset(&u->raw_memchunk); - /* Grab unencoded data */ + /* Grab unencoded data. */ pa_sink_render(u->sink, u->block_size, &u->raw_memchunk); } pa_assert(u->raw_memchunk.length > 0); - /* Encode it */ + /* Encode it. */ rl = u->raw_memchunk.length; u->encoding_overhead += u->next_encoding_overhead; pa_raop_client_encode_sample(u->raop, &u->raw_memchunk, &u->encoded_memchunk); u->next_encoding_overhead = (u->encoded_memchunk.length - (rl - u->raw_memchunk.length)); u->encoding_ratio = u->encoded_memchunk.length / (rl - u->raw_memchunk.length); } else { - /* We render some silence into our memchunk */ + /* We render some silence into our memchunk. */ memcpy(&u->encoded_memchunk, &silence, sizeof(pa_memchunk)); pa_memblock_ref(silence.memblock); - /* Calculate/store some values to be used with the smoother */ + /* Calculate/store some values to be used with the smoother. */ u->next_encoding_overhead = silence_overhead; u->encoding_ratio = silence_ratio; } @@ -405,8 +405,7 @@ static void thread_func(void *userdata) { continue; else if (errno == EAGAIN) { - /* OK, we filled all socket buffers up - * now. */ + /* OK, we filled all socket buffers up now. */ goto filled_up; } else { @@ -423,22 +422,21 @@ static void thread_func(void *userdata) { pollfd->revents = 0; if (u->encoded_memchunk.length > 0) { - /* we've completely written the encoded data, so update our overhead */ + /* We've completely written the encoded data, so update our overhead. */ u->encoding_overhead += u->next_encoding_overhead; /* OK, we wrote less that we asked for, * hence we can assume that the socket - * buffers are full now */ + * buffers are full now. */ goto filled_up; } } } filled_up: - /* At this spot we know that the socket buffers are * fully filled up. This is the best time to estimate - * the playback position of the server */ + * the playback position of the server. */ n = u->offset - u->encoding_overhead; @@ -460,7 +458,7 @@ static void thread_func(void *userdata) { pa_smoother_put(u->smoother, pa_rtclock_now(), usec); } - /* Hmm, nothing to do. Let's sleep */ + /* Hmm, nothing to do. Let's sleep... */ pollfd->events = POLLOUT; /*PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;*/ } @@ -482,7 +480,7 @@ static void thread_func(void *userdata) { } /* We expect this to happen on occasion if we are not sending data. - It's perfectly natural and normal and natural */ + * It's perfectly natural and normal and natural. */ if (u->rtpoll_item) pa_rtpoll_item_free(u->rtpoll_item); u->rtpoll_item = NULL; @@ -492,7 +490,7 @@ static void thread_func(void *userdata) { fail: /* If this was no regular exit from the loop we have to continue - * processing messages until we received PA_MESSAGE_SHUTDOWN */ + * processing messages until we received PA_MESSAGE_SHUTDOWN. */ pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL); pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); @@ -502,7 +500,7 @@ finish: pa_log_debug("Thread shutting down"); } -int pa__init(pa_module*m) { +int pa__init(pa_module *m) { struct userdata *u = NULL; pa_sample_spec ss; pa_modargs *ma = NULL; @@ -640,7 +638,7 @@ int pa__get_n_used(pa_module *m) { return pa_sink_linked_by(u->sink); } -void pa__done(pa_module*m) { +void pa__done(pa_module *m) { struct userdata *u; pa_assert(m); diff --git a/src/modules/raop/raop_client.c b/src/modules/raop/raop_client.c index 3b6c36e..29c4f08 100644 --- a/src/modules/raop/raop_client.c +++ b/src/modules/raop/raop_client.c @@ -80,9 +80,9 @@ struct pa_raop_client { /* Encryption Related bits */ AES_KEY aes; - uint8_t aes_iv[AES_CHUNKSIZE]; /* initialization vector for aes-cbc */ - uint8_t aes_nv[AES_CHUNKSIZE]; /* next vector for aes-cbc */ - uint8_t aes_key[AES_CHUNKSIZE]; /* key for aes-cbc */ + uint8_t aes_iv[AES_CHUNKSIZE]; /* Initialization vector for aes-cbc */ + uint8_t aes_nv[AES_CHUNKSIZE]; /* Next vector for aes-cbc */ + uint8_t aes_key[AES_CHUNKSIZE]; /* Key for aes-cbc */ pa_socket_client *sc; int fd; @@ -91,9 +91,9 @@ struct pa_raop_client { uint32_t rtptime; pa_raop_client_cb_t callback; - void* userdata; + void *userdata; pa_raop_client_closed_cb_t closed_callback; - void* closed_userdata; + void *closed_userdata; }; /** @@ -115,32 +115,32 @@ static inline void bit_writer(uint8_t **buffer, uint8_t *bit_pos, int *size, uin if (!*bit_pos) *size += 1; - /* Calc the number of bits left in the current byte of buffer */ + /* Calc the number of bits left in the current byte of buffer. */ bits_left = 7 - *bit_pos + 1; /* Calc the overflow of bits in relation to how much space we have left... */ bit_overflow = bits_left - data_bit_len; if (bit_overflow >= 0) { - /* We can fit the new data in our current byte */ - /* As we write from MSB->LSB we need to left shift by the overflow amount */ + /* We can fit the new data in our current byte. + * As we write from MSB->LSB we need to left shift by the overflow amount. */ bit_data = data << bit_overflow; if (*bit_pos) **buffer |= bit_data; else **buffer = bit_data; - /* If our data fits exactly into the current byte, we need to increment our pointer */ + /* If our data fits exactly into the current byte, we need to increment our pointer. */ if (0 == bit_overflow) { - /* Do not increment size as it will be incremented on next call as bit_pos is zero */ + /* Do not increment size as it will be incremented on next call as bit_pos is zero. */ *buffer += 1; *bit_pos = 0; } else { *bit_pos += data_bit_len; } } else { - /* bit_overflow is negative, there for we will need a new byte from our buffer */ - /* Firstly fill up what's left in the current byte */ + /* bit_overflow is negative, there for we will need a new byte from our buffer + * Firstly fill up what's left in the current byte. */ bit_data = data >> -bit_overflow; **buffer |= bit_data; - /* Increment our buffer pointer and size counter*/ + /* Increment our buffer pointer and size counter. */ *buffer += 1; *size += 1; **buffer = data << (8 + bit_overflow); @@ -173,7 +173,7 @@ static int rsa_encrypt(uint8_t *text, int len, uint8_t *res) { return size; } -static int aes_encrypt(pa_raop_client* c, uint8_t *data, int size) { +static int aes_encrypt(pa_raop_client *c, uint8_t *data, int size) { uint8_t *buf; int i=0, j; @@ -228,8 +228,8 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata c->callback(c->fd, c->userdata); } -static void rtsp_cb(pa_rtsp_client *rtsp, pa_rtsp_state state, pa_headerlist* headers, void *userdata) { - pa_raop_client* c = userdata; +static void rtsp_cb(pa_rtsp_client *rtsp, pa_rtsp_state state, pa_headerlist *headers, void *userdata) { + pa_raop_client *c = userdata; pa_assert(c); pa_assert(rtsp); pa_assert(rtsp == c->rtsp); @@ -245,12 +245,12 @@ static void rtsp_cb(pa_rtsp_client *rtsp, pa_rtsp_state state, pa_headerlist* he pa_log_debug("RAOP: CONNECTED"); ip = pa_rtsp_localip(c->rtsp); - /* First of all set the url properly */ + /* First of all set the url properly. */ url = pa_sprintf_malloc("rtsp://%s/%s", ip, c->sid); pa_rtsp_set_url(c->rtsp, url); pa_xfree(url); - /* Now encrypt our aes_public key to send to the device */ + /* Now encrypt our aes_public key to send to the device. */ i = rsa_encrypt(c->aes_key, AES_CHUNKSIZE, rsakey); pa_base64_encode(rsakey, i, &key); rtrimchar(key, '='); @@ -349,7 +349,7 @@ static void rtsp_cb(pa_rtsp_client *rtsp, pa_rtsp_state state, pa_headerlist* he pa_rtsp_client_free(c->rtsp); c->rtsp = NULL; if (c->fd > 0) { - /* We do not close the fd, we leave it to the closed callback to do that */ + /* We do not close the fd, we leave it to the closed callback to do that. */ c->fd = -1; } if (c->sc) { @@ -363,7 +363,7 @@ static void rtsp_cb(pa_rtsp_client *rtsp, pa_rtsp_state state, pa_headerlist* he } } -pa_raop_client* pa_raop_client_new(pa_core *core, const char* host) { +pa_raop_client* pa_raop_client_new(pa_core *core, const char *host) { pa_parsed_address a; pa_raop_client* c; @@ -392,10 +392,11 @@ pa_raop_client* pa_raop_client_new(pa_core *core, const char* host) { pa_raop_client_free(c); return NULL; } + return c; } -void pa_raop_client_free(pa_raop_client* c) { +void pa_raop_client_free(pa_raop_client *c) { pa_assert(c); if (c->rtsp) @@ -406,7 +407,7 @@ void pa_raop_client_free(pa_raop_client* c) { pa_xfree(c); } -int pa_raop_connect(pa_raop_client* c) { +int pa_raop_connect(pa_raop_client *c) { char *sci; struct { uint32_t a; @@ -423,30 +424,31 @@ int pa_raop_connect(pa_raop_client* c) { c->rtsp = pa_rtsp_client_new(c->core->mainloop, c->host, c->port, "iTunes/4.6 (Macintosh; U; PPC Mac OS X 10.3)"); - /* Initialise the AES encryption system */ + /* Initialise the AES encryption system. */ pa_random(c->aes_iv, sizeof(c->aes_iv)); pa_random(c->aes_key, sizeof(c->aes_key)); memcpy(c->aes_nv, c->aes_iv, sizeof(c->aes_nv)); AES_set_encrypt_key(c->aes_key, 128, &c->aes); - /* Generate random instance id */ + /* Generate random instance id. */ pa_random(&rand_data, sizeof(rand_data)); c->sid = pa_sprintf_malloc("%u", rand_data.a); sci = pa_sprintf_malloc("%08x%08x",rand_data.b, rand_data.c); pa_rtsp_add_header(c->rtsp, "Client-Instance", sci); pa_xfree(sci); pa_rtsp_set_callback(c->rtsp, rtsp_cb, c); + return pa_rtsp_connect(c->rtsp); } -int pa_raop_flush(pa_raop_client* c) { +int pa_raop_flush(pa_raop_client *c) { pa_assert(c); pa_rtsp_flush(c->rtsp, c->seq, c->rtptime); return 0; } -int pa_raop_client_set_volume(pa_raop_client* c, pa_volume_t volume) { +int pa_raop_client_set_volume(pa_raop_client *c, pa_volume_t volume) { int rv; double db; char *param; @@ -461,13 +463,14 @@ int pa_raop_client_set_volume(pa_raop_client* c, pa_volume_t volume) { param = pa_sprintf_malloc("volume: %0.6f\r\n", db); - /* We just hit and hope, cannot wait for the callback */ + /* We just hit and hope, cannot wait for the callback. */ rv = pa_rtsp_setparameter(c->rtsp, param); pa_xfree(param); + return rv; } -int pa_raop_client_encode_sample(pa_raop_client* c, pa_memchunk* raw, pa_memchunk* encoded) { +int pa_raop_client_encode_sample(pa_raop_client *c, pa_memchunk *raw, pa_memchunk *encoded) { uint16_t len; size_t bufmax; uint8_t *bp, bpos; @@ -495,25 +498,25 @@ int pa_raop_client_encode_sample(pa_raop_client* c, pa_memchunk* raw, pa_memchun bsize = (int)(raw->length / 4); length = bsize * 4; - /* Leave 16 bytes extra to allow for the ALAC header which is about 55 bits */ + /* Leave 16 bytes extra to allow for the ALAC header which is about 55 bits. */ bufmax = length + header_size + 16; pa_memchunk_reset(encoded); encoded->memblock = pa_memblock_new(c->core->mempool, bufmax); b = pa_memblock_acquire(encoded->memblock); memcpy(b, header, header_size); - /* Now write the actual samples */ + /* Now write the actual samples. */ bp = b + header_size; size = bpos = 0; bit_writer(&bp,&bpos,&size,1,3); /* channel=1, stereo */ - bit_writer(&bp,&bpos,&size,0,4); /* unknown */ - bit_writer(&bp,&bpos,&size,0,8); /* unknown */ - bit_writer(&bp,&bpos,&size,0,4); /* unknown */ - bit_writer(&bp,&bpos,&size,1,1); /* hassize */ - bit_writer(&bp,&bpos,&size,0,2); /* unused */ - bit_writer(&bp,&bpos,&size,1,1); /* is-not-compressed */ - - /* size of data, integer, big endian */ + bit_writer(&bp,&bpos,&size,0,4); /* Unknown */ + bit_writer(&bp,&bpos,&size,0,8); /* Unknown */ + bit_writer(&bp,&bpos,&size,0,4); /* Unknown */ + bit_writer(&bp,&bpos,&size,1,1); /* Hassize */ + bit_writer(&bp,&bpos,&size,0,2); /* Unused */ + bit_writer(&bp,&bpos,&size,1,1); /* Is-not-compressed */ + + /* Size of data, integer, big endian. */ bit_writer(&bp,&bpos,&size,(bsize>>24)&0xff,8); bit_writer(&bp,&bpos,&size,(bsize>>16)&0xff,8); bit_writer(&bp,&bpos,&size,(bsize>>8)&0xff,8); @@ -522,7 +525,7 @@ int pa_raop_client_encode_sample(pa_raop_client* c, pa_memchunk* raw, pa_memchun ibp = p = pa_memblock_acquire(raw->memblock); maxibp = p + raw->length - 4; while (ibp <= maxibp) { - /* Byte swap stereo data */ + /* Byte swap stereo data. */ bit_writer(&bp,&bpos,&size,*(ibp+1),8); bit_writer(&bp,&bpos,&size,*(ibp+0),8); bit_writer(&bp,&bpos,&size,*(ibp+3),8); @@ -534,28 +537,28 @@ int pa_raop_client_encode_sample(pa_raop_client* c, pa_memchunk* raw, pa_memchun pa_memblock_release(raw->memblock); encoded->length = header_size + size; - /* store the length (endian swapped: make this better) */ + /* Store the length (endian swapped: make this better). */ len = size + header_size - 4; *(b + 2) = len >> 8; *(b + 3) = len & 0xff; - /* encrypt our data */ + /* Encrypt our data. */ aes_encrypt(c, (b + header_size), size); - /* We're done with the chunk */ + /* We're done with the chunk. */ pa_memblock_release(encoded->memblock); return 0; } -void pa_raop_client_set_callback(pa_raop_client* c, pa_raop_client_cb_t callback, void *userdata) { +void pa_raop_client_set_callback(pa_raop_client *c, pa_raop_client_cb_t callback, void *userdata) { pa_assert(c); c->callback = callback; c->userdata = userdata; } -void pa_raop_client_set_closed_callback(pa_raop_client* c, pa_raop_client_closed_cb_t callback, void *userdata) { +void pa_raop_client_set_closed_callback(pa_raop_client *c, pa_raop_client_closed_cb_t callback, void *userdata) { pa_assert(c); c->closed_callback = callback; diff --git a/src/modules/raop/raop_client.h b/src/modules/raop/raop_client.h index b349a54..6ba32e9 100644 --- a/src/modules/raop/raop_client.h +++ b/src/modules/raop/raop_client.h @@ -24,19 +24,19 @@ typedef struct pa_raop_client pa_raop_client; -pa_raop_client* pa_raop_client_new(pa_core *core, const char* host); -void pa_raop_client_free(pa_raop_client* c); +pa_raop_client* pa_raop_client_new(pa_core *core, const char *host); +void pa_raop_client_free(pa_raop_client *c); -int pa_raop_connect(pa_raop_client* c); -int pa_raop_flush(pa_raop_client* c); +int pa_raop_connect(pa_raop_client *c); +int pa_raop_flush(pa_raop_client *c); -int pa_raop_client_set_volume(pa_raop_client* c, pa_volume_t volume); -int pa_raop_client_encode_sample(pa_raop_client* c, pa_memchunk* raw, pa_memchunk* encoded); +int pa_raop_client_set_volume(pa_raop_client *c, pa_volume_t volume); +int pa_raop_client_encode_sample(pa_raop_client *c, pa_memchunk *raw, pa_memchunk *encoded); typedef void (*pa_raop_client_cb_t)(int fd, void *userdata); -void pa_raop_client_set_callback(pa_raop_client* c, pa_raop_client_cb_t callback, void *userdata); +void pa_raop_client_set_callback(pa_raop_client *c, pa_raop_client_cb_t callback, void *userdata); typedef void (*pa_raop_client_closed_cb_t)(void *userdata); -void pa_raop_client_set_closed_callback(pa_raop_client* c, pa_raop_client_closed_cb_t callback, void *userdata); +void pa_raop_client_set_closed_callback(pa_raop_client *c, pa_raop_client_closed_cb_t callback, void *userdata); #endif diff --git a/src/modules/rtp/rtsp_client.c b/src/modules/rtp/rtsp_client.c index 6f828ba..56f6e15 100644 --- a/src/modules/rtp/rtsp_client.c +++ b/src/modules/rtp/rtsp_client.c @@ -73,7 +73,7 @@ struct pa_rtsp_client { char *transport; }; -pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char* hostname, uint16_t port, const char* useragent) { +pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char *hostname, uint16_t port, const char *useragent) { pa_rtsp_client *c; pa_assert(mainloop); @@ -94,7 +94,7 @@ pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char* hostna return c; } -void pa_rtsp_client_free(pa_rtsp_client* c) { +void pa_rtsp_client_free(pa_rtsp_client *c) { pa_assert(c); if (c->sc) @@ -355,25 +355,25 @@ void pa_rtsp_disconnect(pa_rtsp_client *c) { c->ioline = NULL; } -const char* pa_rtsp_localip(pa_rtsp_client* c) { +const char* pa_rtsp_localip(pa_rtsp_client *c) { pa_assert(c); return c->localip; } -uint32_t pa_rtsp_serverport(pa_rtsp_client* c) { +uint32_t pa_rtsp_serverport(pa_rtsp_client *c) { pa_assert(c); return c->rtp_port; } -void pa_rtsp_set_url(pa_rtsp_client* c, const char* url) { +void pa_rtsp_set_url(pa_rtsp_client *c, const char *url) { pa_assert(c); c->url = pa_xstrdup(url); } -void pa_rtsp_add_header(pa_rtsp_client *c, const char* key, const char* value) { +void pa_rtsp_add_header(pa_rtsp_client *c, const char *key, const char *value) { pa_assert(c); pa_assert(key); pa_assert(value); @@ -381,19 +381,19 @@ void pa_rtsp_add_header(pa_rtsp_client *c, const char* key, const char* value) { pa_headerlist_puts(c->headers, key, value); } -void pa_rtsp_remove_header(pa_rtsp_client *c, const char* key) { +void pa_rtsp_remove_header(pa_rtsp_client *c, const char *key) { pa_assert(c); pa_assert(key); pa_headerlist_remove(c->headers, key); } -static int rtsp_exec(pa_rtsp_client* c, const char* cmd, - const char* content_type, const char* content, +static int rtsp_exec(pa_rtsp_client *c, const char *cmd, + const char *content_type, const char *content, int expect_response, - pa_headerlist* headers) { - pa_strbuf* buf; - char* hdrs; + pa_headerlist *headers) { + pa_strbuf *buf; + char *hdrs; pa_assert(c); pa_assert(c->url); @@ -443,17 +443,22 @@ static int rtsp_exec(pa_rtsp_client* c, const char* cmd, return 0; } -int pa_rtsp_announce(pa_rtsp_client *c, const char* sdp) { +int pa_rtsp_announce(pa_rtsp_client *c, const char *sdp) { + int rv; + pa_assert(c); + if (!sdp) return -1; c->state = STATE_ANNOUNCE; - return rtsp_exec(c, "ANNOUNCE", "application/sdp", sdp, 1, NULL); + rv = rtsp_exec(c, "ANNOUNCE", "application/sdp", sdp, 1, NULL); + + return rv; } -int pa_rtsp_setup(pa_rtsp_client* c) { - pa_headerlist* headers; +int pa_rtsp_setup(pa_rtsp_client *c) { + pa_headerlist *headers; int rv; pa_assert(c); @@ -463,16 +468,18 @@ int pa_rtsp_setup(pa_rtsp_client* c) { c->state = STATE_SETUP; rv = rtsp_exec(c, "SETUP", NULL, NULL, 1, headers); + pa_headerlist_free(headers); return rv; } -int pa_rtsp_record(pa_rtsp_client* c, uint16_t* seq, uint32_t* rtptime) { - pa_headerlist* headers; - int rv; +int pa_rtsp_record(pa_rtsp_client *c, uint16_t *seq, uint32_t *rtptime) { + pa_headerlist *headers; char *info; + int rv; pa_assert(c); + if (!c->session) { /* No session in progress */ return -1; @@ -489,30 +496,40 @@ int pa_rtsp_record(pa_rtsp_client* c, uint16_t* seq, uint32_t* rtptime) { c->state = STATE_RECORD; rv = rtsp_exec(c, "RECORD", NULL, NULL, 1, headers); + pa_headerlist_free(headers); return rv; } int pa_rtsp_teardown(pa_rtsp_client *c) { + int rv; + pa_assert(c); c->state = STATE_TEARDOWN; - return rtsp_exec(c, "TEARDOWN", NULL, NULL, 0, NULL); + rv = rtsp_exec(c, "TEARDOWN", NULL, NULL, 0, NULL); + + return rv; } -int pa_rtsp_setparameter(pa_rtsp_client *c, const char* param) { +int pa_rtsp_setparameter(pa_rtsp_client *c, const char *param) { + int rv; + pa_assert(c); + if (!param) return -1; c->state = STATE_SET_PARAMETER; - return rtsp_exec(c, "SET_PARAMETER", "text/parameters", param, 1, NULL); + rv = rtsp_exec(c, "SET_PARAMETER", "text/parameters", param, 1, NULL); + + return rv; } int pa_rtsp_flush(pa_rtsp_client *c, uint16_t seq, uint32_t rtptime) { pa_headerlist* headers; - int rv; char *info; + int rv; pa_assert(c); @@ -523,6 +540,7 @@ int pa_rtsp_flush(pa_rtsp_client *c, uint16_t seq, uint32_t rtptime) { c->state = STATE_FLUSH; rv = rtsp_exec(c, "FLUSH", NULL, NULL, 1, headers); + pa_headerlist_free(headers); return rv; } diff --git a/src/modules/rtp/rtsp_client.h b/src/modules/rtp/rtsp_client.h index f0ff95a..d51acda 100644 --- a/src/modules/rtp/rtsp_client.h +++ b/src/modules/rtp/rtsp_client.h @@ -41,29 +41,29 @@ typedef enum { STATE_SET_PARAMETER, STATE_DISCONNECTED } pa_rtsp_state; -typedef void (*pa_rtsp_cb_t)(pa_rtsp_client *c, pa_rtsp_state state, pa_headerlist* hl, void *userdata); +typedef void (*pa_rtsp_cb_t)(pa_rtsp_client *c, pa_rtsp_state state, pa_headerlist *hl, void *userdata); -pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char* hostname, uint16_t port, const char* useragent); -void pa_rtsp_client_free(pa_rtsp_client* c); +pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char *hostname, uint16_t port, const char *useragent); +void pa_rtsp_client_free(pa_rtsp_client *c); -int pa_rtsp_connect(pa_rtsp_client* c); +int pa_rtsp_connect(pa_rtsp_client *c); void pa_rtsp_set_callback(pa_rtsp_client *c, pa_rtsp_cb_t callback, void *userdata); -void pa_rtsp_disconnect(pa_rtsp_client* c); +void pa_rtsp_disconnect(pa_rtsp_client *c); -const char* pa_rtsp_localip(pa_rtsp_client* c); -uint32_t pa_rtsp_serverport(pa_rtsp_client* c); -void pa_rtsp_set_url(pa_rtsp_client* c, const char* url); -void pa_rtsp_add_header(pa_rtsp_client *c, const char* key, const char* value); -void pa_rtsp_remove_header(pa_rtsp_client *c, const char* key); +const char* pa_rtsp_localip(pa_rtsp_client *c); +uint32_t pa_rtsp_serverport(pa_rtsp_client *c); +void pa_rtsp_set_url(pa_rtsp_client *c, const char *url); +void pa_rtsp_add_header(pa_rtsp_client *c, const char *key, const char *value); +void pa_rtsp_remove_header(pa_rtsp_client *c, const char *key); -int pa_rtsp_announce(pa_rtsp_client* c, const char* sdp); +int pa_rtsp_announce(pa_rtsp_client *c, const char *sdp); -int pa_rtsp_setup(pa_rtsp_client* c); -int pa_rtsp_record(pa_rtsp_client* c, uint16_t* seq, uint32_t* rtptime); -int pa_rtsp_teardown(pa_rtsp_client* c); +int pa_rtsp_setup(pa_rtsp_client *c); +int pa_rtsp_record(pa_rtsp_client *c, uint16_t *seq, uint32_t *rtptime); +int pa_rtsp_teardown(pa_rtsp_client *c); -int pa_rtsp_setparameter(pa_rtsp_client* c, const char* param); -int pa_rtsp_flush(pa_rtsp_client* c, uint16_t seq, uint32_t rtptime); +int pa_rtsp_setparameter(pa_rtsp_client *c, const char *param); +int pa_rtsp_flush(pa_rtsp_client *c, uint16_t seq, uint32_t rtptime); #endif -- 2.5.0