diff --git a/src/modules/module-raop-discover.c b/src/modules/module-raop-discover.c index 88ca2062e..dd26bad95 100644 --- a/src/modules/module-raop-discover.c +++ b/src/modules/module-raop-discover.c @@ -223,6 +223,8 @@ static void pw_properties_from_avahi_string(const char *key, const char *value, * 4 = FairPlay SAPv2.5. */ if (str_in_list(value, ",", "1")) value = "RSA"; + else if (str_in_list(value, ",", "4")) + value = "auth_setup"; else value = "none"; pw_properties_set(props, "raop.encryption.type", value); diff --git a/src/modules/module-raop-sink.c b/src/modules/module-raop-sink.c index 9365653a5..7a7f2a882 100644 --- a/src/modules/module-raop-sink.c +++ b/src/modules/module-raop-sink.c @@ -130,6 +130,7 @@ enum { enum { CRYPTO_NONE, CRYPTO_RSA, + CRYPTO_AUTH_SETUP, }; enum { CODEC_PCM, @@ -988,7 +989,7 @@ static int rtsp_do_announce(struct impl *impl) char iv[16*2]; int res, frames, i, ip_version; char *sdp; - char local_ip[256]; + char local_ip[256]; host = pw_properties_get(impl->props, "raop.hostname"); @@ -1048,6 +1049,32 @@ static int rtsp_do_announce(struct impl *impl) return res; } +static void rtsp_auth_setup_reply(void *data, int status, const struct spa_dict *headers) +{ + struct impl *impl = data; + + pw_log_info("reply %d", status); + + impl->encryption = CRYPTO_NONE; + + rtsp_do_announce(impl); +} + +static int rtsp_do_auth_setup(struct impl *impl) +{ + int res; + + char output[] = + "\x01" + "\x59\x02\xed\xe9\x0d\x4e\xf2\xbd\x4c\xb6\x8a\x63\x30\x03\x82\x07" + "\xa9\x4d\xbd\x50\xd8\xaa\x46\x5b\x5d\x8c\x01\x2a\x0c\x7e\x1d\x4e"; + + res = pw_rtsp_client_url_send(impl->rtsp, "/auth-setup", "POST", &impl->headers->dict, + "application/octet-stream", output, rtsp_auth_setup_reply, impl); + + return res; +} + static const char *find_attr(char **tokens, const char *key) { int i; @@ -1168,7 +1195,10 @@ static void rtsp_options_reply(void *data, int status, const struct spa_dict *he rtsp_do_auth(impl, headers); break; case 200: - rtsp_do_announce(impl); + if (impl->encryption == CRYPTO_AUTH_SETUP) + rtsp_do_auth_setup(impl); + else + rtsp_do_announce(impl); break; } } @@ -1648,6 +1678,8 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args) impl->encryption = CRYPTO_NONE; else if (spa_streq(str, "RSA")) impl->encryption = CRYPTO_RSA; + else if (spa_streq(str, "auth_setup")) + impl->encryption = CRYPTO_AUTH_SETUP; else { pw_log_error( "can't handle encryption type %s", str); res = -EINVAL; diff --git a/src/modules/module-raop/rtsp-client.c b/src/modules/module-raop/rtsp-client.c index c241bf40d..792b44190 100644 --- a/src/modules/module-raop/rtsp-client.c +++ b/src/modules/module-raop/rtsp-client.c @@ -273,12 +273,30 @@ static int process_input(struct pw_rtsp_client *client) int cseq; struct message *msg; const struct spa_dict_item *it; + const char *content_type; + unsigned int content_length; spa_dict_for_each(it, &client->headers->dict) pw_log_info(" %s: %s", it->key, it->value); cseq = pw_properties_get_int32(client->headers, "CSeq", 0); - + content_type = pw_properties_get(client->headers, "Content-Type"); + if (content_type != NULL && strcmp(content_type, "application/octet-stream") == 0) { + pw_log_info("binary response received"); + content_length = pw_properties_get_uint64(client->headers, "Content-Length", 0); + char content_buf[content_length]; + res = read(client->source->fd, content_buf, content_length); + pw_log_debug("read %d bytes", res); + if (res == 0) + return -EPIPE; + if (res < 0) { + res = -errno; + if (res != -EAGAIN && res != -EWOULDBLOCK) + return res; + return 0; + } + pw_properties_set(client->headers, "body", content_buf); + } if ((msg = find_pending(client, cseq)) != NULL) { msg->reply(msg->user_data, client->status, &client->headers->dict); spa_list_remove(&msg->link); @@ -466,7 +484,7 @@ int pw_rtsp_client_disconnect(struct pw_rtsp_client *client) return 0; } -int pw_rtsp_client_send(struct pw_rtsp_client *client, +int pw_rtsp_client_url_send(struct pw_rtsp_client *client, const char *url, const char *cmd, const struct spa_dict *headers, const char *content_type, const char *content, void (*reply) (void *user_data, int status, const struct spa_dict *headers), @@ -485,7 +503,7 @@ int pw_rtsp_client_send(struct pw_rtsp_client *client, cseq = ++client->cseq; - fprintf(f, "%s %s RTSP/1.0\r\n", cmd, client->url); + fprintf(f, "%s %s RTSP/1.0\r\n", cmd, url); fprintf(f, "CSeq: %d\r\n", cseq); if (headers != NULL) { @@ -519,3 +537,12 @@ int pw_rtsp_client_send(struct pw_rtsp_client *client, } return 0; } + +int pw_rtsp_client_send(struct pw_rtsp_client *client, + const char *cmd, const struct spa_dict *headers, + const char *content_type, const char *content, + void (*reply) (void *user_data, int status, const struct spa_dict *headers), + void *user_data) +{ + return pw_rtsp_client_url_send(client, client->url, cmd, headers, content_type, content, reply, user_data); +} diff --git a/src/modules/module-raop/rtsp-client.h b/src/modules/module-raop/rtsp-client.h index 4588eb830..1ff13ee59 100644 --- a/src/modules/module-raop/rtsp-client.h +++ b/src/modules/module-raop/rtsp-client.h @@ -71,6 +71,12 @@ int pw_rtsp_client_disconnect(struct pw_rtsp_client *client); int pw_rtsp_client_get_local_ip(struct pw_rtsp_client *client, int *version, char *ip, size_t len); +int pw_rtsp_client_url_send(struct pw_rtsp_client *client, const char *url, + const char *cmd, const struct spa_dict *headers, + const char *content_type, const char *content, + void (*reply) (void *user_data, int status, const struct spa_dict *headers), + void *user_data); + int pw_rtsp_client_send(struct pw_rtsp_client *client, const char *cmd, const struct spa_dict *headers, const char *content_type, const char *content,