cleanup conn->raop to raop

This commit is contained in:
F. Duncanh
2025-12-15 00:25:31 -05:00
parent 060a0abc00
commit 2e83032686

View File

@@ -23,9 +23,10 @@ static void
http_handler_server_info(raop_conn_t *conn, http_request_t *request, http_response_t *response,
char **response_data, int *response_datalen) {
assert(conn->raop->dnssd);
raop_t *raop = conn->raop;
assert(raop->dnssd);
int hw_addr_raw_len = 0;
const char *hw_addr_raw = dnssd_get_hw_addr(conn->raop->dnssd, &hw_addr_raw_len);
const char *hw_addr_raw = dnssd_get_hw_addr(raop->dnssd, &hw_addr_raw_len);
char *hw_addr = calloc(1, 3 * hw_addr_raw_len);
utils_hwaddr_airplay(hw_addr, 3 * hw_addr_raw_len, hw_addr_raw, hw_addr_raw_len);
@@ -84,6 +85,7 @@ http_handler_server_info(raop_conn_t *conn, http_request_t *request, http_respon
static void
http_handler_scrub(raop_conn_t *conn, http_request_t *request, http_response_t *response,
char **response_data, int *response_datalen) {
raop_t *raop = conn->raop;
const char *url = http_request_get_url(request);
const char *data = strstr(url, "?");
float scrub_position = 0.0f;
@@ -94,18 +96,19 @@ http_handler_scrub(raop_conn_t *conn, http_request_t *request, http_response_t *
double value = strtod(position, &end);
if (end && end != position) {
scrub_position = (float) value;
logger_log(conn->raop->logger, LOGGER_DEBUG, "http_handler_scrub: got position = %.6f",
logger_log(raop->logger, LOGGER_DEBUG, "http_handler_scrub: got position = %.6f",
scrub_position);
}
}
logger_log(conn->raop->logger, LOGGER_DEBUG, "**********************SCRUB %f ***********************",scrub_position);
conn->raop->callbacks.on_video_scrub(conn->raop->callbacks.cls, scrub_position);
logger_log(raop->logger, LOGGER_DEBUG, "**********************SCRUB %f ***********************",scrub_position);
raop->callbacks.on_video_scrub(raop->callbacks.cls, scrub_position);
}
static void
http_handler_rate(raop_conn_t *conn, http_request_t *request, http_response_t *response,
char **response_data, int *response_datalen) {
raop_t *raop = conn->raop;
const char *url = http_request_get_url(request);
const char *data = strstr(url, "?");
float rate_value = 0.0f;
@@ -116,18 +119,20 @@ http_handler_rate(raop_conn_t *conn, http_request_t *request, http_response_t *r
float value = strtof(rate, &end);
if (end && end != rate) {
rate_value = value;
logger_log(conn->raop->logger, LOGGER_DEBUG, "http_handler_rate: got rate = %.6f", rate_value);
logger_log(raop->logger, LOGGER_DEBUG, "http_handler_rate: got rate = %.6f", rate_value);
}
}
conn->raop->callbacks.on_video_rate(conn->raop->callbacks.cls, rate_value);
raop->callbacks.on_video_rate(raop->callbacks.cls, rate_value);
}
static void
http_handler_stop(raop_conn_t *conn, http_request_t *request, http_response_t *response,
char **response_data, int *response_datalen) {
logger_log(conn->raop->logger, LOGGER_INFO, "client HTTP request POST stop");
conn->raop->callbacks.on_video_stop(conn->raop->callbacks.cls);
raop_t *raop = conn->raop;
logger_log(raop->logger, LOGGER_INFO, "client HTTP request POST stop");
raop->callbacks.on_video_stop(raop->callbacks.cls);
}
/* handles PUT /setProperty http requests from Client to Server */
@@ -137,9 +142,10 @@ http_handler_set_property(raop_conn_t *conn,
http_request_t *request, http_response_t *response,
char **response_data, int *response_datalen) {
raop_t *raop = conn->raop;
const char *url = http_request_get_url(request);
const char *property = url + strlen("/setProperty?");
logger_log(conn->raop->logger, LOGGER_DEBUG, "http_handler_set_property: %s", property);
logger_log(raop->logger, LOGGER_DEBUG, "http_handler_set_property: %s", property);
/* actionAtItemEnd: values:
@@ -152,7 +158,7 @@ http_handler_set_property(raop_conn_t *conn,
selectedMediaArray contains plist with language choice:
*/
airplay_video_t *airplay_video = conn->raop->airplay_video[conn->raop->current_video];
airplay_video_t *airplay_video = raop->airplay_video[raop->current_video];
if (!strcmp(property, "selectedMediaArray")) {
/* verify that this request contains a binary plist*/
char *header_str = NULL;
@@ -161,7 +167,7 @@ http_handler_set_property(raop_conn_t *conn,
bool is_plist = strstr(header_str,"apple-binary-plist");
free(header_str);
if (!is_plist) {
logger_log(conn->raop->logger, LOGGER_DEBUG, "POST /setProperty?selectedMediaArray"
logger_log(raop->logger, LOGGER_DEBUG, "POST /setProperty?selectedMediaArray"
"does not provide an apple-binary-plist");
goto post_error;
}
@@ -172,7 +178,7 @@ http_handler_set_property(raop_conn_t *conn,
plist_t req_value_node = plist_dict_get_item(req_root_node, "value");
if (!req_value_node || !PLIST_IS_ARRAY(req_value_node)) {
logger_log(conn->raop->logger, LOGGER_INFO, "POST /setProperty?selectedMediaArray"
logger_log(raop->logger, LOGGER_INFO, "POST /setProperty?selectedMediaArray"
" did not provide expected plist from client");
goto post_error;
}
@@ -217,7 +223,7 @@ http_handler_set_property(raop_conn_t *conn,
if (language_code && language_name) {
set_language_code(airplay_video, language_code, strlen(language_code));
set_language_name(airplay_video, language_name, strlen(language_name));
logger_log(conn->raop->logger, LOGGER_INFO, "stored language from MediaSelectionOptions: %s \"%s\"",
logger_log(raop->logger, LOGGER_INFO, "stored language from MediaSelectionOptions: %s \"%s\"",
get_language_code(airplay_video), get_language_name(airplay_video));
}
plist_mem_free(language_name);
@@ -225,7 +231,7 @@ http_handler_set_property(raop_conn_t *conn,
} else if (!strcmp(property, "reverseEndTime") ||
!strcmp(property, "forwardEndTime") ||
!strcmp(property, "actionAtItemEnd")) {
logger_log(conn->raop->logger, LOGGER_DEBUG, "property %s is known but unhandled", property);
logger_log(raop->logger, LOGGER_DEBUG, "property %s is known but unhandled", property);
plist_t errResponse = plist_new_dict();
plist_t errCode = plist_new_uint(0);
@@ -234,7 +240,7 @@ http_handler_set_property(raop_conn_t *conn,
plist_free(errResponse);
http_response_add_header(response, "Content-Type", "text/x-apple-plist+xml");
} else {
logger_log(conn->raop->logger, LOGGER_DEBUG, "property %s is unknown, unhandled", property);
logger_log(raop->logger, LOGGER_DEBUG, "property %s is unknown, unhandled", property);
goto post_error;
}
return;
@@ -247,20 +253,22 @@ http_handler_set_property(raop_conn_t *conn,
static void
http_handler_get_property(raop_conn_t *conn, http_request_t *request, http_response_t *response,
char **response_data, int *response_datalen) {
raop_t *raop = conn->raop;
const char *url = http_request_get_url(request);
const char *property = url + strlen("getProperty?");
logger_log(conn->raop->logger, LOGGER_DEBUG, "http_handler_get_property: %s (unhandled)", property);
logger_log(raop->logger, LOGGER_DEBUG, "http_handler_get_property: %s (unhandled)", property);
}
/* this request (for a variant FairPlay decryption) cannot be handled by UxPlay */
static void
http_handler_fpsetup2(raop_conn_t *conn, http_request_t *request, http_response_t *response,
char **response_data, int *response_datalen) {
logger_log(conn->raop->logger, LOGGER_WARNING, "client HTTP request POST fp-setup2 is unhandled");
raop_t *raop = conn->raop;
logger_log(raop->logger, LOGGER_WARNING, "client HTTP request POST fp-setup2 is unhandled");
http_response_add_header(response, "Content-Type", "application/x-apple-binary-plist");
int req_datalen = 0;
const unsigned char *req_data = (unsigned char *) http_request_get_data(request, &req_datalen);
logger_log(conn->raop->logger, LOGGER_ERR, "only FairPlay version 0x03 is implemented, version is 0x%2.2x",
logger_log(raop->logger, LOGGER_ERR, "only FairPlay version 0x03 is implemented, version is 0x%2.2x",
req_data[4]);
http_response_init(response, "HTTP/1.1", 421, "Misdirected Request");
}
@@ -341,6 +349,7 @@ static void
http_handler_playback_info(raop_conn_t *conn, http_request_t *request, http_response_t *response,
char **response_data, int *response_datalen)
{
raop_t *raop = conn->raop;
//const char *session_id = http_request_get_header(request, "X-Apple-Session-ID");
playback_info_t playback_info;
@@ -350,16 +359,16 @@ http_handler_playback_info(raop_conn_t *conn, http_request_t *request, http_resp
//ayback_info.ready_to_play = true; // ???;
//ayback_info.playback_likely_to_keep_up = true;
conn->raop->callbacks.on_video_acquire_playback_info(conn->raop->callbacks.cls, &playback_info);
raop->callbacks.on_video_acquire_playback_info(raop->callbacks.cls, &playback_info);
if (playback_info.duration == -1.0) {
/* video has finished, reset */
logger_log(conn->raop->logger, LOGGER_DEBUG, "playback_info not available (finishing)");
//httpd_remove_known_connections(conn->raop->httpd);
logger_log(raop->logger, LOGGER_DEBUG, "playback_info not available (finishing)");
//httpd_remove_known_connections(raop->httpd);
http_response_set_disconnect(response,1);
conn->raop->callbacks.video_reset(conn->raop->callbacks.cls, true, false);
raop->callbacks.video_reset(raop->callbacks.cls, true, false);
return;
} else if (playback_info.position == -1.0) {
logger_log(conn->raop->logger, LOGGER_DEBUG, "playback_info not available");
logger_log(raop->logger, LOGGER_DEBUG, "playback_info not available");
return;
}
@@ -392,29 +401,30 @@ static void
http_handler_reverse(raop_conn_t *conn, http_request_t *request, http_response_t *response,
char **response_data, int *response_datalen) {
raop_t *raop = conn->raop;
/* get http socket for send */
int socket_fd = httpd_get_connection_socket (conn->raop->httpd, (void *) conn);
int socket_fd = httpd_get_connection_socket (raop->httpd, (void *) conn);
if (socket_fd < 0) {
logger_log(conn->raop->logger, LOGGER_ERR, "fcup_request failed to retrieve socket_fd from httpd");
logger_log(raop->logger, LOGGER_ERR, "fcup_request failed to retrieve socket_fd from httpd");
/* shut down connection? */
}
const char *purpose = http_request_get_header(request, "X-Apple-Purpose");
const char *connection = http_request_get_header(request, "Connection");
const char *upgrade = http_request_get_header(request, "Upgrade");
logger_log(conn->raop->logger, LOGGER_INFO, "client requested reverse connection: %s; purpose: %s \"%s\"",
logger_log(raop->logger, LOGGER_INFO, "client requested reverse connection: %s; purpose: %s \"%s\"",
connection, upgrade, purpose);
httpd_set_connection_type(conn->raop->httpd, (void *) conn, CONNECTION_TYPE_PTTH);
int type_PTTH = httpd_count_connection_type(conn->raop->httpd, CONNECTION_TYPE_PTTH);
httpd_set_connection_type(raop->httpd, (void *) conn, CONNECTION_TYPE_PTTH);
int type_PTTH = httpd_count_connection_type(raop->httpd, CONNECTION_TYPE_PTTH);
if (type_PTTH == 1) {
logger_log(conn->raop->logger, LOGGER_DEBUG, "will use socket %d for %s connections", socket_fd, purpose);
logger_log(raop->logger, LOGGER_DEBUG, "will use socket %d for %s connections", socket_fd, purpose);
http_response_init(response, "HTTP/1.1", 101, "Switching Protocols");
http_response_add_header(response, "Connection", "Upgrade");
http_response_add_header(response, "Upgrade", "PTTH/1.0");
} else {
logger_log(conn->raop->logger, LOGGER_ERR, "multiple TPPH connections (%d) are forbidden", type_PTTH );
logger_log(raop->logger, LOGGER_ERR, "multiple TPPH connections (%d) are forbidden", type_PTTH );
}
}
@@ -427,22 +437,23 @@ static void
http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t *response,
char **response_data, int *response_datalen) {
airplay_video_t *airplay_video = conn->raop->airplay_video[conn->raop->current_video];
raop_t *raop = conn->raop;
airplay_video_t *airplay_video = raop->airplay_video[raop->current_video];
bool data_is_plist = false;
plist_t req_root_node = NULL;
uint64_t uint_val = 0;
int request_id = 0;
int fcup_response_statuscode = 0;
bool logger_debug = (logger_get_level(conn->raop->logger) >= LOGGER_DEBUG);
bool logger_debug = (logger_get_level(raop->logger) >= LOGGER_DEBUG);
const char* session_id = http_request_get_header(request, "X-Apple-Session-ID");
if (!session_id) {
logger_log(conn->raop->logger, LOGGER_ERR, "Play request had no X-Apple-Session-ID");
logger_log(raop->logger, LOGGER_ERR, "Play request had no X-Apple-Session-ID");
goto post_action_error;
}
const char *apple_session_id = get_apple_session_id(airplay_video);
if (strcmp(session_id, apple_session_id)){
logger_log(conn->raop->logger, LOGGER_ERR, "X-Apple-Session-ID has changed:\n was:\"%s\"\n now:\"%s\"",
logger_log(raop->logger, LOGGER_ERR, "X-Apple-Session-ID has changed:\n was:\"%s\"\n now:\"%s\"",
apple_session_id, session_id);
goto post_action_error;
}
@@ -450,11 +461,11 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t
/* verify that this request contains a binary plist*/
char *header_str = NULL;
http_request_get_header_string(request, &header_str);
logger_log(conn->raop->logger, LOGGER_DEBUG, "request header: %s", header_str);
logger_log(raop->logger, LOGGER_DEBUG, "request header: %s", header_str);
data_is_plist = (strstr(header_str,"apple-binary-plist") != NULL);
free(header_str);
if (!data_is_plist) {
logger_log(conn->raop->logger, LOGGER_INFO, "POST /action: did not receive expected plist from client");
logger_log(raop->logger, LOGGER_INFO, "POST /action: did not receive expected plist from client");
goto post_action_error;
}
@@ -462,7 +473,7 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t
int request_datalen = 0;
const char *request_data = http_request_get_data(request, &request_datalen);
if (request_datalen == 0) {
logger_log(conn->raop->logger, LOGGER_INFO, "POST /action: did not receive expected plist from client");
logger_log(raop->logger, LOGGER_INFO, "POST /action: did not receive expected plist from client");
goto post_action_error;
}
plist_from_bin(request_data, request_datalen, &req_root_node);
@@ -483,7 +494,7 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t
if (!type) {
goto post_action_error;
}
logger_log(conn->raop->logger, LOGGER_DEBUG, "action type is %s", type);
logger_log(raop->logger, LOGGER_DEBUG, "action type is %s", type);
/* check that plist structure is as expected*/
plist_t req_params_node = NULL;
if (PLIST_IS_DICT (req_root_node)) {
@@ -501,25 +512,25 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t
char* remove_uuid = NULL;
plist_get_string_val(req_params_item_uuid_node, &remove_uuid);
assert(remove_uuid);
int id = get_playlist_by_uuid(conn->raop, remove_uuid);
if (id == conn->raop->current_video) {
conn->raop->current_video = -1;
float position = conn->raop->callbacks.on_video_playlist_remove(conn->raop->callbacks.cls);
int id = get_playlist_by_uuid(raop, remove_uuid);
if (id == raop->current_video) {
raop->current_video = -1;
float position = raop->callbacks.on_video_playlist_remove(raop->callbacks.cls);
float duration = get_duration(airplay_video);
if (duration < (float) MIN_STORED_AIRPLAY_VIDEO_DURATION_SECONDS) {
airplay_video_destroy(airplay_video); /* short duration == probably advertisements */
conn->raop->airplay_video[id] = NULL;
raop->airplay_video[id] = NULL;
} else {
set_resume_position_seconds(airplay_video, position);
conn->raop->interrupted_video = id;
raop->interrupted_video = id;
}
} else {
logger_log(conn->raop->logger, LOGGER_WARNING, "playlistRemove uuid %s does not match current_video\n", remove_uuid);
logger_log(raop->logger, LOGGER_WARNING, "playlistRemove uuid %s does not match current_video\n", remove_uuid);
}
plist_mem_free (remove_uuid);
} else if (!strcmp(type, "playlistInsert")) {
logger_log(conn->raop->logger, LOGGER_INFO, "action type playlistInsert (start playback)");
logger_log(raop->logger, LOGGER_INFO, "action type playlistInsert (start playback)");
plist_t req_params_item_node = plist_dict_get_item(req_params_node, "item");
if (!req_params_item_node || !PLIST_IS_DICT (req_params_item_node)) {
goto post_action_error;
@@ -528,11 +539,11 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t
char* remove_uuid = NULL;
plist_get_string_val(req_params_item_uuid_node, &remove_uuid);
if (remove_uuid) {
int id = get_playlist_by_uuid(conn->raop, remove_uuid);
int id = get_playlist_by_uuid(raop, remove_uuid);
if (id >= 0) {
logger_log(conn->raop->logger, LOGGER_INFO, "playlistInsert uuid %s is stored at airplay_video[%d]", remove_uuid, id);
logger_log(raop->logger, LOGGER_INFO, "playlistInsert uuid %s is stored at airplay_video[%d]", remove_uuid, id);
} else {
logger_log(conn->raop->logger, LOGGER_INFO, "playlistInsert uuid %s is not a stored playlist", remove_uuid);
logger_log(raop->logger, LOGGER_INFO, "playlistInsert uuid %s is not a stored playlist", remove_uuid);
}
plist_mem_free(remove_uuid);
char *plist_xml = NULL;
@@ -541,7 +552,7 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t
printf("playlistInsert parameter item list is:\n%s", plist_xml);
plist_mem_free(plist_xml);
}
logger_log(conn->raop->logger, LOGGER_ERR, "FIXME: playlistInsert is not yet implemented");
logger_log(raop->logger, LOGGER_ERR, "FIXME: playlistInsert is not yet implemented");
} else if (!strcmp(type, "unhandledURLResponse")) {
/* handling type "unhandledURLResponse" (case 1)*/
@@ -555,7 +566,7 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t
plist_get_uint_val(req_params_fcup_response_statuscode_node, &uint_val);
fcup_response_statuscode = (int) uint_val;
uint_val = 0;
logger_log(conn->raop->logger, LOGGER_DEBUG, "FCUP_Response_StatusCode = %d",
logger_log(raop->logger, LOGGER_DEBUG, "FCUP_Response_StatusCode = %d",
fcup_response_statuscode);
}
@@ -565,7 +576,7 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t
plist_get_uint_val(req_params_fcup_response_requestid_node, &uint_val);
request_id = (int) uint_val;
uint_val = 0;
logger_log(conn->raop->logger, LOGGER_DEBUG, "FCUP_Response_RequestID = %d", request_id);
logger_log(raop->logger, LOGGER_DEBUG, "FCUP_Response_RequestID = %d", request_id);
}
}
@@ -578,7 +589,7 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t
if (!fcup_response_url) {
goto post_action_error;
}
logger_log(conn->raop->logger, LOGGER_DEBUG, "FCUP_Response_URL = %s", fcup_response_url);
logger_log(raop->logger, LOGGER_DEBUG, "FCUP_Response_URL = %s", fcup_response_url);
plist_t req_params_fcup_response_data_node = plist_dict_get_item(req_params_node, "FCUP_Response_Data");
if (!PLIST_IS_DATA(req_params_fcup_response_data_node)){
@@ -605,7 +616,7 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t
int playlist_len = strlen(playlist);
if (logger_debug) {
logger_log(conn->raop->logger, LOGGER_DEBUG, "begin FCUP Response data:\n%s\nend FCUP Response data", playlist);
logger_log(raop->logger, LOGGER_DEBUG, "begin FCUP Response data:\n%s\nend FCUP Response data", playlist);
}
char *ptr = strstr(fcup_response_url, "/master.m3u8");
@@ -633,9 +644,9 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t
--uri_num; // (next num is current num + 1)
int ret = store_media_playlist(airplay_video, playlist, &count, &duration, uri_num);
if (ret == 1) {
logger_log(conn->raop->logger, LOGGER_DEBUG,"media_playlist is a duplicate: do not store");
logger_log(raop->logger, LOGGER_DEBUG,"media_playlist is a duplicate: do not store");
} else if (count) {
logger_log(conn->raop->logger, LOGGER_DEBUG,
logger_log(raop->logger, LOGGER_DEBUG,
"\n%s:\nreceived media playlist has %5d chunks, total duration %9.3f secs\n",
fcup_response_url, count, duration);
}
@@ -651,14 +662,14 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t
get_next_FCUP_RequestID(airplay_video));
set_next_media_uri_id(airplay_video, ++uri_num);
} else {
conn->raop->callbacks.on_video_play(conn->raop->callbacks.cls,
raop->callbacks.on_video_play(raop->callbacks.cls,
get_playback_location(airplay_video),
get_start_position_seconds(airplay_video));
}
} else {
logger_log(conn->raop->logger, LOGGER_INFO, "unknown action type (unhandled)");
logger_log(raop->logger, LOGGER_INFO, "unknown action type (unhandled)");
}
plist_mem_free(type);
plist_free(req_root_node);
@@ -682,6 +693,7 @@ static void
http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *response,
char **response_data, int *response_datalen) {
raop_t *raop = conn->raop;
char* playback_location = NULL;
char* client_proc_name = NULL;
plist_t req_root_node = NULL;
@@ -690,11 +702,11 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r
char supported_hls_proc_names[] = "YouTube;";
airplay_video_t *airplay_video = NULL;
logger_log(conn->raop->logger, LOGGER_DEBUG, "http_handler_play");
logger_log(raop->logger, LOGGER_DEBUG, "http_handler_play");
const char* apple_session_id = http_request_get_header(request, "X-Apple-Session-ID");
if (!apple_session_id) {
logger_log(conn->raop->logger, LOGGER_ERR, "Play request had no X-Apple-Session-ID");
logger_log(raop->logger, LOGGER_ERR, "Play request had no X-Apple-Session-ID");
goto play_error;
}
@@ -704,13 +716,13 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r
if (request_datalen > 0) {
char *header_str = NULL;
http_request_get_header_string(request, &header_str);
logger_log(conn->raop->logger, LOGGER_DEBUG, "request header:\n%s", header_str);
logger_log(raop->logger, LOGGER_DEBUG, "request header:\n%s", header_str);
data_is_binary_plist = (strstr(header_str, "x-apple-binary-plist") != NULL);
free (header_str);
}
if (!data_is_binary_plist) {
logger_log(conn->raop->logger, LOGGER_ERR, "Play request Content is not binary_plist (unsupported)");
logger_log(raop->logger, LOGGER_ERR, "Play request Content is not binary_plist (unsupported)");
goto play_error;
}
@@ -726,22 +738,22 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r
/* check if playlist is already dowloaded and stored (may have been interruoted by advertisements ) */
#if 0
for (int i = 0; i < MAX_AIRPLAY_VIDEO; i++) {
printf("old: airplay_video[%d] %p %s %f\n", i, conn->raop->airplay_video[i],
get_playback_uuid(conn->raop->airplay_video[i]),
get_duration(conn->raop->airplay_video[i]));
printf("old: airplay_video[%d] %p %s %f\n", i, raop->airplay_video[i],
get_playback_uuid(raop->airplay_video[i]),
get_duration(raop->airplay_video[i]));
}
printf("\n");
printf("new playback_uuid %s\n\n", playback_uuid);
#endif
int id = -1;
id = get_playlist_by_uuid(conn->raop, playback_uuid);
id = get_playlist_by_uuid(raop, playback_uuid);
if (id >= 0) {
printf("use: airplay_video[%d] %p %s %s\n", id, airplay_video, playback_uuid, get_playback_uuid(airplay_video));
airplay_video = conn->raop->airplay_video[id];
airplay_video = raop->airplay_video[id];
assert(airplay_video);
set_apple_session_id(airplay_video, apple_session_id, strlen(apple_session_id));
conn->raop->callbacks.on_video_play(conn->raop->callbacks.cls,
raop->callbacks.on_video_play(raop->callbacks.cls,
get_playback_location(airplay_video),
get_start_position_seconds(airplay_video));
plist_mem_free(playback_uuid);
@@ -752,14 +764,14 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r
/* remove short stort playlists (probably advertisements */
int count = 0;
for (int i = 0; i < MAX_AIRPLAY_VIDEO; i++) {
if (conn->raop->airplay_video[i]) {
float duration = get_duration(conn->raop->airplay_video[i]);
if (raop->airplay_video[i]) {
float duration = get_duration(raop->airplay_video[i]);
if (duration < (float) MIN_STORED_AIRPLAY_VIDEO_DURATION_SECONDS ) {
logger_log(conn->raop->logger, LOGGER_INFO,
logger_log(raop->logger, LOGGER_INFO,
"deleting playlist playback_uuid %s duration (seconds) %f",
get_playback_uuid(conn->raop->airplay_video[i]), duration);
airplay_video_destroy(conn->raop->airplay_video[i]);
conn->raop->airplay_video[i] = NULL;
get_playback_uuid(raop->airplay_video[i]), duration);
airplay_video_destroy(raop->airplay_video[i]);
raop->airplay_video[i] = NULL;
} else {
count++;
//printf(" %d %d duration %f : keep\n", i, count, duration);
@@ -769,28 +781,28 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r
/* initialize new airplay_video structure to hold playlist */
for (int i = 0; i < MAX_AIRPLAY_VIDEO; i++) {
if (conn->raop->airplay_video[i]) {
if (raop->airplay_video[i]) {
continue;
}
id = i;
break;
}
if (id == -1) {
logger_log(conn->raop->logger, LOGGER_ERR, "no unused airplay_video structures are available"
logger_log(raop->logger, LOGGER_ERR, "no unused airplay_video structures are available"
" MAX_AIRPLAY_VIDEO = %d\n", MAX_AIRPLAY_VIDEO);
exit(1);
}
airplay_video = airplay_video_init(conn->raop, conn->raop->port, conn->raop->lang);
airplay_video = airplay_video_init(raop, raop->port, raop->lang);
if (airplay_video) {
set_playback_uuid(airplay_video, playback_uuid, strlen(playback_uuid));
plist_mem_free (playback_uuid);
conn->raop->current_video = id;
conn->raop->airplay_video[id] = airplay_video;
raop->current_video = id;
raop->airplay_video[id] = airplay_video;
count++;
printf("created new airplay_video %p %s\n\n", airplay_video, get_playback_uuid(airplay_video));
} else {
logger_log(conn->raop->logger, LOGGER_ERR, "failed to allocate airplay_video[%d]\n", id);
logger_log(raop->logger, LOGGER_ERR, "failed to allocate airplay_video[%d]\n", id);
exit(-1);
}
@@ -798,18 +810,18 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r
if (count == MAX_AIRPLAY_VIDEO) {
int next = (id + 1) % (int) MAX_AIRPLAY_VIDEO;
logger_log(conn->raop->logger, LOGGER_INFO,
logger_log(raop->logger, LOGGER_INFO,
"deleting playlist playback_uuid %s duration (seconds) %f",
get_playback_uuid(conn->raop->airplay_video[next]),
get_duration(conn->raop->airplay_video[next]));
airplay_video_destroy(conn->raop->airplay_video[next]);
conn->raop->airplay_video[next] = NULL;
get_playback_uuid(raop->airplay_video[next]),
get_duration(raop->airplay_video[next]));
airplay_video_destroy(raop->airplay_video[next]);
raop->airplay_video[next] = NULL;
}
#if 0
for (int i = 0; i < MAX_AIRPLAY_VIDEO; i++) {
printf("new: airplay_video[%d] %p %s %f\n", i, conn->raop->airplay_video[i],
get_playback_uuid(conn->raop->airplay_video[i]),
get_duration(conn->raop->airplay_video[i]));
printf("new: airplay_video[%d] %p %s %f\n", i, raop->airplay_video[i],
get_playback_uuid(raop->airplay_video[i]),
get_duration(raop->airplay_video[i]));
}
#endif
set_apple_session_id(airplay_video, apple_session_id, strlen(apple_session_id));
@@ -827,7 +839,7 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r
} else {
plist_get_string_val(req_client_proc_name_node, &client_proc_name);
if (!strstr(supported_hls_proc_names, client_proc_name)){
logger_log(conn->raop->logger, LOGGER_WARNING, "Unsupported HLS streaming format: clientProcName %s not found in supported list: %s",
logger_log(raop->logger, LOGGER_WARNING, "Unsupported HLS streaming format: clientProcName %s not found in supported list: %s",
client_proc_name, supported_hls_proc_names);
}
plist_mem_free(client_proc_name);
@@ -835,7 +847,7 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r
plist_t req_start_position_seconds_node = plist_dict_get_item(req_root_node, "Start-Position-Seconds");
if (!req_start_position_seconds_node) {
logger_log(conn->raop->logger, LOGGER_INFO, "No Start-Position-Seconds in Play request");
logger_log(raop->logger, LOGGER_INFO, "No Start-Position-Seconds in Play request");
} else {
double start_position = 0.0;
plist_get_real_val(req_start_position_seconds_node, &start_position);
@@ -845,7 +857,7 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r
const char *uri_suffix = strstr(playback_location, "/master.m3u8");
if (!uri_suffix) {
logger_log(conn->raop->logger, LOGGER_ERR, "Content-Location has unsupported form:\n%s\n", playback_location);
logger_log(raop->logger, LOGGER_ERR, "Content-Location has unsupported form:\n%s\n", playback_location);
goto play_error;
} else {
size_t len = strlen(get_uri_local_prefix(airplay_video)) + strlen(uri_suffix);
@@ -876,10 +888,10 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r
if (req_root_node) {
plist_free(req_root_node);
}
logger_log(conn->raop->logger, LOGGER_ERR, "Could not find valid Plist Data for POST/play request, Unhandled");
logger_log(raop->logger, LOGGER_ERR, "Could not find valid Plist Data for POST/play request, Unhandled");
http_response_init(response, "HTTP/1.1", 400, "Bad Request");
http_response_set_disconnect(response, 1);
conn->raop->callbacks.conn_reset(conn->raop->callbacks.cls, 2);
raop->callbacks.conn_reset(raop->callbacks.cls, 2);
}
/* the HLS handler handles http requests GET /[uri] on the HLS channel from the media player to the Server, asking for
@@ -893,7 +905,8 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r
static void
http_handler_hls(raop_conn_t *conn, http_request_t *request, http_response_t *response,
char **response_data, int *response_datalen) {
airplay_video_t *airplay_video = conn->raop->airplay_video[conn->raop->current_video];
raop_t *raop = conn->raop;
airplay_video_t *airplay_video = raop->airplay_video[raop->current_video];
const char *method = http_request_get_method(request);
assert (!strcmp(method, "GET"));
const char *url = http_request_get_url(request);
@@ -902,7 +915,7 @@ http_handler_hls(raop_conn_t *conn, http_request_t *request, http_response_t *r
//don't accept Upgrade: h2c request ?
char *header_str = NULL;
http_request_get_header_string(request, &header_str);
logger_log(conn->raop->logger, LOGGER_INFO,
logger_log(raop->logger, LOGGER_INFO,
"%s\nhls upgrade request declined", header_str);
free (header_str);
return;
@@ -918,7 +931,7 @@ http_handler_hls(raop_conn_t *conn, http_request_t *request, http_response_t *r
*response_data = data;
*response_datalen = (int ) len;
} else {
logger_log(conn->raop->logger, LOGGER_ERR,"requested master playlist %s not found", url);
logger_log(raop->logger, LOGGER_ERR,"requested master playlist %s not found", url);
*response_datalen = 0;
}
@@ -930,10 +943,10 @@ http_handler_hls(raop_conn_t *conn, http_request_t *request, http_response_t *r
char *data = adjust_yt_condensed_playlist(media_playlist);
*response_data = data;
*response_datalen = strlen(data);
logger_log(conn->raop->logger, LOGGER_INFO,
logger_log(raop->logger, LOGGER_INFO,
"Requested media_playlist %s has %5d chunks, total duration %9.3f secs", url, chunks, duration);
} else {
logger_log(conn->raop->logger, LOGGER_ERR,"requested media playlist %s not found", url);
logger_log(raop->logger, LOGGER_ERR,"requested media playlist %s not found", url);
*response_datalen = 0;
}