Tidy up write encrypted. Explore some of the remote_control connections. Not working.

This commit is contained in:
Mike Brady
2022-06-23 09:40:30 +01:00
parent c3d465046a
commit fb151915ae
4 changed files with 169 additions and 24 deletions
+3
View File
@@ -310,6 +310,7 @@ typedef struct {
timing_t timing_type; // are we using NTP or PTP on this connection?
pthread_t *rtp_event_thread;
pthread_t *rtp_data_thread;
pthread_t rtp_ap2_control_thread;
pthread_t rtp_realtime_audio_thread;
pthread_t rtp_buffered_audio_thread;
@@ -335,12 +336,14 @@ typedef struct {
ap2_pairing ap2_control_pairing;
int event_socket;
int data_socket;
SOCKADDR ap2_remote_control_socket_addr; // a socket pointing to the control port of the client
socklen_t ap2_remote_control_socket_addr_length;
int ap2_control_socket;
int realtime_audio_socket;
int buffered_audio_socket;
uint16_t local_data_port;
uint16_t local_event_port;
uint16_t local_ap2_control_port;
uint16_t local_realtime_audio_port;
+59 -2
View File
@@ -1503,6 +1503,59 @@ int local_ptp_time_to_frame(uint64_t time, uint32_t *frame, rtsp_conn_info *conn
return result;
}
void rtp_data_receiver_cleanup_handler(void *arg) {
rtsp_conn_info *conn = (rtsp_conn_info *)arg;
debug(2, "Connection %d: AP2 Data Receiver Cleanup.", conn->connection_number);
}
void *rtp_data_receiver(void *arg) {
rtsp_conn_info *conn = (rtsp_conn_info *)arg;
debug(1, "Connection %d: AP2 Data Receiver started", conn->connection_number);
pthread_cleanup_push(rtp_data_receiver_cleanup_handler, arg);
listen(conn->data_socket, 5);
uint8_t packet[4096];
ssize_t nread;
SOCKADDR remote_addr;
memset(&remote_addr, 0, sizeof(remote_addr));
socklen_t addr_size = sizeof(remote_addr);
int fd = accept(conn->data_socket, (struct sockaddr *)&remote_addr, &addr_size);
debug(1,
"Connection %d: rtp_data_receiver accepted a connection on socket %d and moved to a new "
"socket %d.",
conn->connection_number, conn->data_socket, fd);
intptr_t pfd = fd;
pthread_cleanup_push(socket_cleanup, (void *)pfd);
int finished = 0;
do {
nread = recv(fd, packet, sizeof(packet), 0);
if (nread < 0) {
char errorstring[1024];
strerror_r(errno, (char *)errorstring, sizeof(errorstring));
debug(1, "Connection %d: error in ap2 rtp_data_receiver %d: \"%s\". Could not recv a packet.",
conn->connection_number, errno, errorstring);
// if ((config.diagnostic_drop_packet_fraction == 0.0) ||
// (drand48() > config.diagnostic_drop_packet_fraction)) {
} else if (nread > 0) {
// ssize_t plen = nread;
debug(1, "Connection %d: Packet Received on Data Port.", conn->connection_number);
// } else {
// debug(3, "Event Receiver Thread -- dropping incoming packet to simulate a bad network.");
// }
} else {
finished = 1;
}
} while (finished == 0);
pthread_cleanup_pop(1); // close the socket
pthread_cleanup_pop(1); // do the cleanup
debug(2, "Connection %d: AP2 Data Receiver RTP thread \"normal\" exit.", conn->connection_number);
pthread_exit(NULL);
}
void rtp_event_receiver_cleanup_handler(void *arg) {
rtsp_conn_info *conn = (rtsp_conn_info *)arg;
debug(2, "Connection %d: AP2 Event Receiver Cleanup.", conn->connection_number);
@@ -1510,7 +1563,7 @@ void rtp_event_receiver_cleanup_handler(void *arg) {
void *rtp_event_receiver(void *arg) {
rtsp_conn_info *conn = (rtsp_conn_info *)arg;
debug(2, "Connection %d: AP2 Event Receiver started", conn->connection_number);
debug(1, "Connection %d: AP2 Event Receiver started", conn->connection_number);
pthread_cleanup_push(rtp_event_receiver_cleanup_handler, arg);
listen(conn->event_socket, 5);
@@ -1522,6 +1575,10 @@ void *rtp_event_receiver(void *arg) {
socklen_t addr_size = sizeof(remote_addr);
int fd = accept(conn->event_socket, (struct sockaddr *)&remote_addr, &addr_size);
debug(2,
"Connection %d: rtp_event_receiver accepted a connection on socket %d and moved to a new "
"socket %d.",
conn->connection_number, conn->event_socket, fd);
intptr_t pfd = fd;
pthread_cleanup_push(socket_cleanup, (void *)pfd);
int finished = 0;
@@ -1539,7 +1596,7 @@ void *rtp_event_receiver(void *arg) {
} else if (nread > 0) {
// ssize_t plen = nread;
debug(1, "Packet Received on Event Port.");
debug(1, "Connection %d: Packet Received on Event Port.", conn->connection_number);
if (packet[1] == 0xD7) {
debug(1,
"Connection %d: AP2 Event Receiver -- Time Announce RTP packet of type 0x%02X length "
+1
View File
@@ -25,6 +25,7 @@ int frame_to_local_time(uint32_t timestamp, uint64_t *time, rtsp_conn_info *conn
int local_time_to_frame(uint64_t time, uint32_t *frame, rtsp_conn_info *conn);
#ifdef CONFIG_AIRPLAY_2
void *rtp_data_receiver(void *arg);
void *rtp_event_receiver(void *arg);
void *rtp_ap2_control_receiver(void *arg);
void *rtp_realtime_audio_receiver(void *arg);
+106 -22
View File
@@ -2,7 +2,7 @@
* RTSP protocol handler. This file is part of Shairport Sync
* Copyright (c) James Laird 2013
* Modifications associated with audio synchronization, mutithreading and
* Modifications associated with audio synchronization, multithreading and
* metadata handling copyright (c) Mike Brady 2014-2021
* All rights reserved.
*
@@ -811,10 +811,14 @@ char *msg_get_header(rtsp_message *msg, char *name) {
return NULL;
}
void debug_print_msg_headers(int level, rtsp_message *msg) {
void _debug_print_msg_headers(const char *filename, const int linenumber, int level,
rtsp_message *msg) {
unsigned int i;
if (msg->respcode != 0)
_debug(filename, linenumber, level, " Response Code: %d.", msg->respcode);
for (i = 0; i < msg->nheaders; i++) {
debug(level, " Type: \"%s\", content: \"%s\"", msg->name[i], msg->value[i]);
_debug(filename, linenumber, level, " Type: \"%s\", content: \"%s\"", msg->name[i],
msg->value[i]);
}
}
@@ -1046,24 +1050,31 @@ char *rtsp_plist_content(rtsp_message *message) {
#endif
void debug_log_rtsp_message(int level, char *prompt, rtsp_message *message) {
void _debug_log_rtsp_message(const char *filename, const int linenumber, int level, char *prompt,
rtsp_message *message) {
if (level > debuglev)
return;
if ((prompt) && (*prompt != '\0')) // okay to pass NULL or an empty list...
debug(level, prompt);
// debug_print_msg_headers(level, message);
_debug(filename, linenumber, level, prompt);
_debug_print_msg_headers(filename, linenumber, level, message);
#ifdef CONFIG_AIRPLAY_2
char *plist_content = rtsp_plist_content(message);
if (plist_content) {
debug(level, " Content Plist (as XML):\n--\n%s--", plist_content);
_debug(filename, linenumber, level, " Content Plist (as XML):\n--\n%s--", plist_content);
free(plist_content);
} else
#endif
{
debug(level, " No Content Plist. Content length: %d.", message->contentlength);
_debug(filename, linenumber, level, " No Content Plist. Content length: %d.",
message->contentlength);
}
}
#define debug_log_rtsp_message(level, prompt, message) \
_debug_log_rtsp_message(__FILE__, __LINE__, level, prompt, message)
#define debug_print_msg_headers(level, message) \
_debug_print_msg_headers(__FILE__, __LINE__, level, message)
#ifdef CONFIG_AIRPLAY_2
static void buf_add(ap2_buffer *buf, uint8_t *in, size_t in_len) {
if (buf->len + in_len > buf->size) {
@@ -1130,6 +1141,30 @@ static ssize_t read_encrypted(int fd, ap2_pairing *ctx, void *buf, size_t count)
return buf_remove(&ctx->plain_buf, buf, count);
}
static ssize_t write_encrypted(int fd, ap2_pairing *ctx, const void *buf, size_t count) {
uint8_t *encrypted;
size_t encrypted_len;
ssize_t ret = pair_encrypt(&encrypted, &encrypted_len, buf, count, ctx->cipher_ctx);
if (ret < 0) {
debug(1, pair_cipher_errmsg(ctx->cipher_ctx));
return -1;
}
size_t remain = encrypted_len;
while (remain > 0) {
ssize_t wrote = write(fd, encrypted + (encrypted_len - remain), remain);
if (wrote <= 0) {
free(encrypted);
return wrote;
}
remain -= wrote;
}
free(encrypted);
return count;
}
/*
static ssize_t write_encrypted(rtsp_conn_info *conn, const void *buf, size_t count) {
uint8_t *encrypted;
size_t encrypted_len;
@@ -1153,6 +1188,7 @@ static ssize_t write_encrypted(rtsp_conn_info *conn, const void *buf, size_t cou
free(encrypted);
return count;
}
*/
#endif
ssize_t read_from_rtsp_connection(rtsp_conn_info *conn, void *buf, size_t count) {
@@ -1417,7 +1453,7 @@ int msg_write_response(rtsp_conn_info *conn, rtsp_message *resp) {
#ifdef CONFIG_AIRPLAY_2
ssize_t reply;
if (conn->ap2_control_pairing.is_encrypted) {
reply = write_encrypted(conn, pkt, p - pkt);
reply = write_encrypted(conn->fd, &conn->ap2_control_pairing, pkt, p - pkt);
} else {
reply = write(conn->fd, pkt, p - pkt);
}
@@ -2246,9 +2282,21 @@ void handle_configure(rtsp_conn_info *conn __attribute__((unused)),
debug_log_rtsp_message(2, "POST /configure response:", resp);
}
void handle_feedback(__attribute__((unused)) rtsp_conn_info *conn,
__attribute__((unused)) rtsp_message *req,
void handle_feedback(rtsp_conn_info *conn, __attribute__((unused)) rtsp_message *req,
__attribute__((unused)) rtsp_message *resp) {
if (conn->airplay_stream_category == remote_control_stream) {
plist_t array_plist = plist_new_array();
plist_t response_plist = plist_new_dict();
plist_dict_set_item(response_plist, "streams", array_plist);
plist_to_bin(response_plist, &resp->content, &resp->contentlength);
plist_free(response_plist);
msg_add_header(resp, "Content-Type", "application/x-apple-binary-plist");
debug_log_rtsp_message(2, "FEEDBACK response (remote_control_stream):", resp);
}
/* not finished yet
plist_t payload_plist = plist_new_dict();
plist_dict_set_item(payload_plist, "type", plist_new_uint(103));
@@ -2868,7 +2916,7 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp)
conn->connection_number, req);
warn("Shairport Sync can not handle NTP streams.");
} else if (conn->airplay_stream_category == remote_control_stream) {
debug_log_rtsp_message(2, "SETUP \"isRemoteControlOnly\" message", req);
debug_log_rtsp_message(2, "SETUP (no stream) \"isRemoteControlOnly\" message", req);
// get a port to use as an event port
// bind a new TCP port and get a socket
@@ -2882,7 +2930,7 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp)
conn->connection_number, err);
}
debug(2, "Connection %d: TCP Remote Control event port opened: %u.",
debug(2, "Connection %d SETUP (RC): TCP Remote Control event port opened: %u.",
conn->connection_number, conn->local_event_port);
if (conn->rtp_event_thread != NULL)
debug(1, "previous rtp_event_thread allocation not freed, it seems.");
@@ -2890,7 +2938,6 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp)
if (conn->rtp_event_thread == NULL)
die("Couldn't allocate space for pthread_t");
pthread_create(conn->rtp_event_thread, NULL, &rtp_event_receiver, (void *)conn);
plist_dict_set_item(setupResponsePlist, "eventPort",
plist_new_uint(conn->local_event_port));
plist_dict_set_item(setupResponsePlist, "timingPort", plist_new_uint(0));
@@ -3108,10 +3155,34 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp)
resp->respcode = 200;
} else if (conn->airplay_stream_category == remote_control_stream) {
debug(2, "Connection %d: SETUP: Remote Control Stream received.", conn->connection_number);
debug_log_rtsp_message(2, "Remote Control Stream stream (second) message", req);
// get a port to use as an data port
// bind a new TCP port and get a socket
conn->local_data_port = 0; // any port
int err =
bind_socket_and_port(SOCK_STREAM, conn->connection_ip_family, conn->self_ip_string,
conn->self_scope_id, &conn->local_data_port, &conn->data_socket);
if (err) {
die("SETUP on Connection %d: Error %d: could not find a TCP port to use as a data "
"port",
conn->connection_number, err);
}
debug(1, "Connection %d SETUP (RC): TCP Remote Control data port opened: %u.",
conn->connection_number, conn->local_data_port);
if (conn->rtp_data_thread != NULL)
debug(1, "previous rtp_data_thread allocation not freed, it seems.");
conn->rtp_data_thread = malloc(sizeof(pthread_t));
if (conn->rtp_data_thread == NULL)
die("Couldn't allocate space for pthread_t");
pthread_create(conn->rtp_data_thread, NULL, &rtp_data_receiver, (void *)conn);
plist_t coreResponseDict = plist_new_dict();
plist_dict_set_item(coreResponseDict, "streamID", plist_new_uint(1));
plist_dict_set_item(coreResponseDict, "type", plist_new_uint(130));
plist_dict_set_item(coreResponseDict, "dataPort", plist_new_uint(conn->local_data_port));
plist_t coreResponseArray = plist_new_array();
plist_array_append_item(coreResponseArray, coreResponseDict);
plist_dict_set_item(setupResponsePlist, "streams", coreResponseArray);
@@ -4844,9 +4915,16 @@ static void *rtsp_conversation_thread_func(void *pconn) {
(strcmp(req->method, "POST") ==
0)) // the options message is very common, so don't log it until level 3
dl = 3;
debug(dl, "Connection %d: Received an RTSP Packet of type \"%s\":", conn->connection_number,
req->method),
debug_print_msg_headers(dl, req);
if (conn->airplay_stream_category == remote_control_stream) {
debug(dl, "Connection %d (RC): Received an RTSP Packet of type \"%s\":",
conn->connection_number, req->method),
debug_log_rtsp_message(dl, NULL, req);
} else {
debug(dl, "Connection %d: Received an RTSP Packet of type \"%s\":", conn->connection_number,
req->method),
debug_log_rtsp_message(dl, NULL, req);
}
apple_challenge(conn->fd, req, resp);
hdr = msg_get_header(req, "CSeq");
if (hdr)
@@ -4900,9 +4978,13 @@ static void *rtsp_conversation_thread_func(void *pconn) {
}
}
}
debug(dl, "Connection %d: RTSP Response:", conn->connection_number);
debug_print_msg_headers(dl, resp);
if (conn->airplay_stream_category == remote_control_stream) {
debug(dl, "Connection %d (RC): RTSP Response:", conn->connection_number);
debug_log_rtsp_message(dl, NULL, resp);
} else {
debug(dl, "Connection %d: RTSP Response:", conn->connection_number);
debug_log_rtsp_message(dl, NULL, resp);
}
if (conn->stop == 0) {
int err = msg_write_response(conn, resp);
if (err) {
@@ -5131,7 +5213,9 @@ void *rtsp_listen_loop(__attribute((unused)) void *arg) {
t2 = secondary_txt_records; // second set of text records in AirPlay 2 only
#endif
build_bonjour_strings(NULL); // no conn yet
mdns_register(t1, t2); // note that the dacp thread could still be using the mdns stuff after all player threads have been terminated, so mdns_unregister can't be in the rtsp_listen_loop cleanup.
mdns_register(t1, t2); // note that the dacp thread could still be using the mdns stuff after
// all player threads have been terminated, so mdns_unregister can't be
// in the rtsp_listen_loop cleanup.
pthread_setcancelstate(oldState, NULL);
int acceptfd;