mirror of
https://github.com/morgan9e/UxPlay
synced 2026-04-14 00:04:13 +09:00
cleanup conn->raop to raop
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user